[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