d2d2c9e958
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@720 8092fc87-c524-0410-9efc-e669fe64eaf9
329 lines
11 KiB
Plaintext
329 lines
11 KiB
Plaintext
The TFB Graphics Libraries
|
|
|
|
Initial documentation by Michael Martin, 4 Feb 2003
|
|
|
|
The graphics system in UQM has three major subsystems:
|
|
|
|
- The "legacy" system, which most of the core code uses. This
|
|
involves the foo_blt () routines in 3do_blt.c, and the data
|
|
types CONTEXT, FRAME, DRAWABLE, and possibly others. I'm
|
|
less familiar with this code, and want to eradicate as much of it as
|
|
I can, but for now, its lowest level has been rewritten as direct
|
|
calls to:
|
|
|
|
- The TFB_Draw* commands, documented below in great detail. These
|
|
routines deal with the datatype TFB_Image, and the more primitive
|
|
TFB_Canvas. They also support drawing to one of several 'screens',
|
|
but since only one thread should be allowed to touch the screen,
|
|
the TFB_DrawScreen routines end up constructing inputs to:
|
|
|
|
- The DCQ/DrawCommand library. This is a ring queue with commands for
|
|
rendering graphics on the actual screen. It interacts to some
|
|
degree with the CONTEXT datatype, but otherwise is defined entirely
|
|
in terms of TFB_Images and TFB_Canvases.
|
|
|
|
THE LEGACY LIBRARY
|
|
--------------------
|
|
|
|
The datatypes the code uses directly are CONTEXT, FRAME, and FONT, all
|
|
of which are really pointers to void. Pointers to those are PCONTEXT,
|
|
PFRAME, and PFONT. Then there's DRAWABLE, which is a DWORD, and its
|
|
pointer type PDRAWABLE. (These are defined in sc2code/libs/gfxlib.h.)
|
|
I'm not sure how DRAWABLE values are transformed into actual drawable
|
|
entities.
|
|
|
|
The full structures for these are in various files in
|
|
sc2code/libs/graphics.
|
|
|
|
context.h: defines CONTEXT_DESC and PCONTEXT_DESC (and the equivalent
|
|
CONTEXTPTR -- insert various sorts of incomprenshible
|
|
muttering here),
|
|
|
|
display.h: defines a DISPLAY_INTERFACE and PDISPLAY_INTERFACE type (as
|
|
well as a global _pCurDisplay).
|
|
|
|
drawable.h: defines FRAME_DESC and DRAWABLE_DESC, and the pointer
|
|
types PFRAME_DESC and PDRAWABLE_DESC. FRAME_DESC has a
|
|
TFB_Image pointer as a member. DRAWABLE_DESC currently
|
|
still uses a rather annoying technique where the last
|
|
member of a struct is a 1-element array, more memory than
|
|
that is actually allocated, and the array's bounds are
|
|
deliberately overflowed to get at multiple frames.
|
|
|
|
font.h: defines FONT_DESC and PFONT_DESC.
|
|
|
|
(Details on how all these data types work is forthcoming.)
|
|
|
|
THE TFB_DRAW LIBRARY
|
|
----------------------
|
|
|
|
The TFB_Draw commands have a single header file:
|
|
sc2code/libs/graphics/tfb_draw.h. This file declares the following
|
|
data types:
|
|
|
|
SCREEN: This is an enum, naming the various screens that the DrawCmd
|
|
library can draw to. Valid values at present are
|
|
TFB_SCREEN_MAIN, TFB_SCREEN_EXTRA, and TFB_SCREEN_TRANSITION.
|
|
These correspond to various objects that are of type TFB_Canvas.
|
|
|
|
(The maximal number of screens is provided by a bogus last
|
|
element, TFB_GFX_NUMSCREENS. Keep that as the last element
|
|
and the allocators will operate properly regardless of any
|
|
screens you may later want to add.)
|
|
|
|
TFB_Canvas: This is, for the purposes of most of the code, a void
|
|
pointer. The implementations of TFB_DrawCanvas commands
|
|
cast them to the appropriate type. (The only
|
|
implementation of these commands casts them to
|
|
SDL_Surface*.)
|
|
|
|
TFB_Palette: Four UBYTES, r, g, b, and 'unused'. This is designed at
|
|
present to be directly castable to SDL_Color, which most
|
|
things do. We should probably do something about that at
|
|
some point.
|
|
|
|
TFB_Image: The most important image structure. This has two
|
|
TFB_Canvases (one for the 'core' image, one for a scaled
|
|
version of it), a pointer to a TFB_Palette array, a
|
|
colormap index, a scaling constant, a Mutex from the
|
|
threading library (to ensure internal consistency if
|
|
multiple threads are doing stuff), and a 'dirty bit' which
|
|
means that, if the image is scaled, the ScaledImg needs to
|
|
be recomputed.
|
|
|
|
TFB_DrawScreen
|
|
--------------
|
|
|
|
When you wish to draw graphics directly on the screen, you call these
|
|
routines, which enqueue the DrawCommands:
|
|
|
|
----
|
|
|
|
void TFB_DrawScreen_Line (int x1, int y1, int x2, int y2,
|
|
int r, int g, int b,
|
|
SCREEN dest);
|
|
|
|
Draws a line from (x1, y1)-(x2, y2) of a color specified by r, g, and
|
|
b on the specified screen.
|
|
|
|
We have a known bug here in that if a corner of one of these lines is
|
|
outside of the context's clipping rectangle, the slope of the line may
|
|
change.
|
|
|
|
----
|
|
|
|
void TFB_DrawScreen_Rect (PRECT rect,
|
|
int r, int g, int b,
|
|
SCREEN dest);
|
|
|
|
Draws a (filled) rectangle with the specified color on the destination
|
|
screen. PRECT is part of the legacy library.
|
|
|
|
void TFB_DrawScreen_Copy (PRECT r, SCREEN src, SCREEN dest);
|
|
|
|
Copies data between screens. The PRECT defines the region to copy.
|
|
This can be handy in saving and restoring background information.
|
|
|
|
----
|
|
|
|
void TFB_DrawScreen_Image (TFB_Image *img,
|
|
int x, int y,
|
|
BOOLEAN scaled,
|
|
TFB_Palette *palette,
|
|
SCREEN dest);
|
|
|
|
void TFB_DrawScreen_FilledImage (TFB_Image *img,
|
|
int x, int y,
|
|
BOOLEAN scaled,
|
|
int r, int g, int b,
|
|
SCREEN dest);
|
|
|
|
These two routines draw images. img, x, and y are all straightforward
|
|
(x and y refer to the upper left of the image), and scaled indicates
|
|
whether or not the NormalImg or ScaledImg should be used, and dest
|
|
names the target screen.
|
|
|
|
For TFB_DrawScreen_Image, the 'palette' argument refers to a
|
|
256-element array of TFB_Palette that describes the palette to use.
|
|
(The default is cached in TFB_Image itself.) Various techniques are
|
|
used to cache the palette values to keep spurious palette-switch
|
|
commands from flooding the DrawCmd queue. However, switching the
|
|
palette many times per frame is likely to seriously degrade
|
|
performance.
|
|
|
|
TFB_DrawScreen_FilledImage draws every non-transparent pixel in img in
|
|
the color specified by r, g, b. (Fonts and some menus do this.)
|
|
|
|
----
|
|
|
|
void TFB_DrawScreen_WaitForSignal (void);
|
|
|
|
Puts this thread to sleep until all commands queued to this point are
|
|
executed. Mostly used to keep from spamming the DrawCmd queue, and to
|
|
ensure proper operation of the next two routines.
|
|
|
|
----
|
|
|
|
void TFB_DrawScreen_CopyToImage (TFB_Image *img,
|
|
PRECT lpRect,
|
|
SCREEN src);
|
|
|
|
Load the pixels from the rectangle lpRect in screen src into img. If
|
|
you're actually working with the pixels directly, you'll want to do a
|
|
TFB_DrawScreen_WaitForSignal () to ensure the image has actually been
|
|
updated. (If you're just passing it to other TFB_DrawScreen commands,
|
|
that's unnecessary, because ordering within a thread is guaranteed.)
|
|
|
|
----
|
|
|
|
void TFB_DrawScreen_DeleteImage (TFB_Image *img);
|
|
|
|
Deallocates all memory associated with img. This REALLY doesn't
|
|
belong here. It should be a TFB_DrawImage command, with a requirement
|
|
that you WaitForSignal lfirst.
|
|
|
|
----
|
|
|
|
TFB_DrawImage
|
|
-------------
|
|
|
|
These routines are similar to a subset of the TFB_DrawScreen commands,
|
|
except that instead of drawing on the screen at some later time, they
|
|
draw directly and immediately onto a TFB_Image. The arguments all
|
|
mean the same things as they did for TFB_DrawScreen.
|
|
|
|
----
|
|
|
|
void TFB_DrawImage_Line (int x1, int y1, int x2, int y2,
|
|
int r, int g, int b,
|
|
TFB_Image *dest);
|
|
|
|
void TFB_DrawImage_Rect (PRECT rect,
|
|
int r, int g, int b,
|
|
TFB_Image *image);
|
|
|
|
void TFB_DrawImage_Image (TFB_Image *img,
|
|
int x, int y,
|
|
BOOLEAN scaled,
|
|
TFB_Palette *palette,
|
|
TFB_Image *target);
|
|
|
|
void TFB_DrawImage_FilledImage (TFB_Image *img,
|
|
int x, int y,
|
|
BOOLEAN scaled,
|
|
int r, int g, int b,
|
|
TFB_Image *target);
|
|
|
|
----
|
|
|
|
TFB_DrawCanvas
|
|
--------------
|
|
|
|
These routines are, quite literally, identical in every way to the
|
|
TFB_DrawImage routines, except that they draw on TFB_Canvases instead.
|
|
They are defined in graphics-library-specific locations. There is, at
|
|
present, only one implementation of these, in
|
|
libs/graphics/sdl/canvas.c.
|
|
|
|
void TFB_DrawCanvas_Line (int x1, int y1, int x2, int y2,
|
|
int r, int g, int b,
|
|
TFB_Canvas dest);
|
|
|
|
void TFB_DrawCanvas_Rect (PRECT rect,
|
|
int r, int g, int b,
|
|
TFB_Canvas image);
|
|
|
|
void TFB_DrawCanvas_Image (TFB_Image *img,
|
|
int x, int y,
|
|
BOOLEAN scaled,
|
|
TFB_Palette *palette,
|
|
TFB_Canvas target);
|
|
|
|
void TFB_DrawCanvas_FilledImage (TFB_Image *img,
|
|
int x, int y,
|
|
BOOLEAN scaled,
|
|
int r, int g, int b,
|
|
TFB_Canvas target);
|
|
|
|
----
|
|
|
|
Creation and Destruction of TFB_Images, TFB_Canvases, and TFB_Palettes
|
|
----------------------------------------------------------------------
|
|
|
|
Various commands exist for creating and destroying the TFB_Draw data
|
|
types. The concept of "ownership" is critical here. If a data object
|
|
owns a pointer inside of it, that pointer's referent is deallocated
|
|
when the data object is deallocated. If a pointer variable owns its
|
|
referent, it's permissible to delete it.
|
|
|
|
TFB_Canvas and TFB_Palette are primitives. TFB_Image owns NormalImg,
|
|
ScaledImg, and Palette, and will delete them when it is itself
|
|
deleted.
|
|
|
|
That said, here are the routines:
|
|
|
|
---
|
|
|
|
TFB_Image *TFB_DrawImage_New (TFB_Canvas canvas)
|
|
|
|
Creates a new TFB_Image, which the caller then owns. The caller must
|
|
own the canvas, and transfers ownership of that canvas to the image.
|
|
The Palette value is automatically created (and the image owns it);
|
|
ScaledImg will be NULL until you scale the image and draw it to the
|
|
screen.
|
|
|
|
---
|
|
|
|
void TFB_DrawImage_Delete (TFB_Image *image)
|
|
|
|
Deletes the image, and all non-NULL components. You must own the
|
|
image you delete.
|
|
|
|
---
|
|
|
|
TFB_Canvas TFB_DrawCanvas_New_TrueColor (int w, int h, BOOLEAN has_alpha);
|
|
|
|
TFB_Canvas TFB_DrawCanvas_New_Paletted (int w, int h,
|
|
TFB_Palette *palette,
|
|
int transparent_index);
|
|
|
|
These create new TFB_Canvases, which the caller will then own. Width
|
|
and height are straightforward. The TrueColor variant produces Canvases
|
|
with the same color depth and pixel format as the screen. The
|
|
has_alpha flag indicates whether or not the canvas has an alpha
|
|
channel.
|
|
|
|
The Paletted variant produces 8-bit paletted canvases. The palette
|
|
argument is optional (it can be NULL, in which case you'll need to set
|
|
it later - TFB_Images tend to do this when drawn), as is the
|
|
transparent_index (if -1, there is no transparency; otherwise, it's
|
|
the index of the transparent color).
|
|
|
|
---
|
|
|
|
TFB_Canvas TFB_DrawCanvas_ToScreenFormat (TFB_Canvas canvas);
|
|
|
|
Returns a canvas that, if possible, matches the graphics configuration
|
|
of the screen. You must own the source canvas. If the conversion is
|
|
possible, it makes the conversion, deletes its argument, and returns
|
|
the converted version; if conversion is not possible, the canvas is
|
|
returned intact.
|
|
|
|
Regardless of success or failure, the caller owns the result.
|
|
|
|
---
|
|
|
|
TFB_Palette *TFB_DrawCanvas_ExtractPalette (TFB_Canvas canvas);
|
|
|
|
Allocates and returns a 256-entry TFB_Palette array that describes the
|
|
palette of the canvas, or returns NULL if the canvas is true-color.
|
|
If the result is non-NULL, the caller owns the result. The caller
|
|
need not own canvas.
|
|
|
|
|
|
DRAWCMD LIBRARY
|
|
-----------------
|
|
|
|
Documentation yet to be written. UQM code shouldn't really mess with
|
|
the DrawCmd library directly.
|