[SDL] 2D API evolution (SDL 1.3/2.0)
David Olofson
david at olofson.net
Sun Aug 27 10:08:52 PDT 2006
On Sunday 27 August 2006 10:22, Sam Lantinga wrote:
[...]
> On an amusing note, I put together a script to generate the blit
> combinations needed for 32-bit pixel formats in 1.3, and it
> generated on the order of 800 blitters, and the resulting object
> code was as big as the entire rest of the library combined.
>
> I think I'll need to pare down some functionality and add some
> multi-purpose blitters in order to make this reasonable... :)
Either that, or generate some or all of the blitter code on the fly,
or something...
As to "or something", one way of splitting blitters into multiple
stages is to arrange them as "pipelines" of callbacks, where each
call deals with a single span of pixels. I did this in ZeeSpace, for
simplicity in dealing with polygons, circular regions etc, rather
than speed - but it seems like it have the potential of delivering
both.
This method would even integrate with hardware acceleration to some
extent. One set of vertices per span indeed, but with a fast
accelerator and a good driver, that's probably still faster than
blending with the CPU. After all, modern accelerators are *built* to
push thousands of polygons per frame...
If N function calls per span is too much overhead, "span tables" would
offer pretty much the same level of simplicity without losing the
ability to deal transparently with polygons, curved shapes etc.
However, now you run into issues with intermediate buffers and cache
abuse instead, so I doubt it's a win when dealing with anything but
very small regions.
If per-polygon state initialization is an issue (and I believe it is
in all but the most trivial cases), it's probably much better to deal
with the "blitter units" as closures. That is, to use a blitter unit,
you call a function to instantiate a closure, then you call a
do_one_span() function for each span, passing the closure instance
pointer as an argument, and finally, you destroy the closure using a
third call. This allows blitter units to have a lot of arguments, and
to keep any amount of per-polygon state across spans, without having
tons of arguments and stuff to the do_one_span() call.
Some (pseudo)code to clarify:
------------------------------------------------------------
typedef void *SDL_BlitterClosure;
typedef struct SDL_BlitterUnit
{
SDL_BlitterClosure *(*instantiate)(...source + dest surfaces,
region data and whatnot...);
int (*process_straight)(SDL_BlitterClosure *closure,
void *src, void *dst, int pixels);
int (*process_transform)(SDL_BlitterClosure *closure,
int tex_x1, int tex_y1,
int tex_x2, int tex_y2,
void *dst, int pixels);
void (*destroy)(SDL_BlitterClosure *closure);
} SDL_BlitterUnit;
------------------------------------------------------------
There are countless ways to deal with the texture coordinates for
transforming blitter units, but I think the one above is a rather
simple yet effective one. (The blitter is supposed to map a line from
(tex_x1, tex_y1) through (tex_x2, tex_y2) to a horizontal line of
length 'pixels' and write the result to *dst++.)
Once the transform is done, the rest of the pipeline will concist of
process_straight() calls, where you just do something with *src
and/or *dst and write the result to *dst++; repeat for 'pixel'.
Doesn't get any simpler than that, I think.
//David Olofson - Programmer, Composer, Open Source Advocate
.------- http://olofson.net - Games, SDL examples -------.
| http://zeespace.net - 2.5D rendering engine |
| http://audiality.org - Music/audio engine |
| http://eel.olofson.net - Real time scripting |
'-- http://www.reologica.se - Rheology instrumentation --'
More information about the SDL
mailing list