SDL_Advanced2D

Well, unless there are even more issues we’ve not yet brought up, I
think I’m starting to see the outline of a solution here; what should
and shouldn’t be in the SDL 1.3/2.0 core, how to deal with “advanced
2D” rendering (scaling, rotation, free form polygons etc), how to
deal with the Direct3D vs OpenGL issue etc.

The basic structure:

* SDL video stays focused on setting up the display
  and implementing accelerated and software blits.

* More advanced 2D rendering is left to add-on
  libraries that should support both OpenGL and
  Direct3D, and preferably also implement software
  rendering.

* 3D is handled by means of the applications
  directly using OpenGL and/or Direct3D. (Direct3D
  for large user base with minimal effort, OpenGL for
  portability, both for maximizing the user base.)

* A nice and clean portable 3D API that runs
  everywhere might be another nice project, that can
  be implemented in pretty much the same way as an
  advanced 2D add-on library, as long as SDL allows
  add-on libs to access both OpenGL and Direct3D.

It seems like using Direct3D together with SDL is entirely doable with
SDL 1.2 already, so I forsee no major issues there. So, I think we
could in fact have the Advanced3D add-on lib work with SDL 1.2 as
well as SDL 1.3/2.0 with little extra work.

As to the API and feature set, I’m thinking OpenGL minus all things
strictly 3D related. Matrix based transformations? I dunno… Nice
and handy (if you know your way around the maths, at least), but
maybe overkill for 2D graphics in general? Anyway, something like
this:-----------------------------------------------------
/* Primitives for A2D_Begin() */
typedef enum
{
A2D_POINTS,
A2D_LINES,
A2D_LINE_LOOP,
A2D_LINE_STRIP,
A2D_TRIANGLES,
A2D_TRIANGLE_STRIP,
A2D_TRIANGLE_FAN,
A2D_QUADS,
A2D_QUAD_STRIP,
A2D_POLYGON
} A2D_Primitives;

/* Modes for A2D_FilterMode() */
typedef enum
{
A2D_NEAREST,
A2D_NEAREST_MIPMAP,
A2D_LINEAR,
A2D_LINEAR_MIPMAP,
A2D_CUBIC,
A2D_CUBIC_MIPMAP
} A2D_FilterModes;

/* Modes for A2D_BlendMode() /
typedef enum
{
A2D_OPAQUE, /
Opaque rendering /
A2D_MASK, /
Copy if src alpha > 0 /
A2D_SRCALPHA, /
Source alpha blending /
A2D_DSTALPHA, /
Destination alpha blending /
A2D_ADD, /
Additive blending /
A2D_SUBTRACT, /
Subtractive blending /
A2D_MODULATE /
Modulation (multiplication) */
} A2D_BlendModes;

/*

  • Select target surface for subsequent rendering.
    */
    void A2D_Target(SDL_Surface *target);

/*

  • Select texture for subsequent rendering.
  • Pass 0 for ‘texid’ to disable texturing, for
  • same results as using an opaque white texture.
    */
    void A2D_Texture(SDL_TextureID texid);

/*

  • Set texture filtering mode.
    */
    void A2D_FilterMode(A2D_FilterModes fm);

/*

  • Set rendering blend function.
    */
    void A2D_BlendMode(A2D_BlendModes mode);

/* Rendering functions */
void A2D_Begin(A2D_Primitives prim);
void A2D_Vertex(float x, float y);
void A2D_TexCoord(float x, float y);
void A2D_ColorRGB(Uint8 r, Uint8 g, Uint8 b);
void A2D_ColorRGBA(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
void A2D_End(void);

/*

  • Ensure that changes to the current target surface are
  • made visible.
    */
    void A2D_Update(void);

/*

  • Quickly fill the current target surface with the
  • specified color.
    */
    void A2D_Clear(float r, float g, float b, float a);

//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 --’

David Olofson <david olofson.net> writes:

/*

  • Ensure that changes to the current target surface are
  • made visible.
    */
    void A2D_Update(void);

I like the simple API. There is an urge to add higher level things, but I don’t
believe they should be in early releases (if ever).

I have a question about this one Update call? My guess is that it is necessary
to flush or sync the drawing api before calling the regular SDL flip/update? My
guess is that the simple OpenGL video backend will already be doing a flush
before flipping?

I think the A2D API should also obey the SDL_Surface rectangular clipping area.
It would be great if that didn’t need additional API on the A2D side.

Hello !

  • SDL video stays focused on setting up the display
    and implementing accelerated and software blits.

  • More advanced 2D rendering is left to add-on
    libraries that should support both OpenGL and
    Direct3D, and preferably also implement software
    rendering.

  • 3D is handled by means of the applications
    directly using OpenGL and/or Direct3D. (Direct3D
    for large user base with minimal effort, OpenGL for
    portability, both for maximizing the user base.)

SDL should not provide any 3D commands.
Even the Analogie could be used in SDL 1.3
HW Surfaces are DirectDraw HW Surfaces or Textures
in OpenGL or D3D. SW Surfaces are really the things in
System Memory.

SDL 1.3 only needs to provide the things it did in SDL 1.2
With things i mean rectangle blitting, rectangle filling
and so on. That it supports MultWindow, Float Audio and so
on is great and makes it even more complete.

  • A nice and clean portable 3D API that runs
    everywhere might be another nice project, that can
    be implemented in pretty much the same way as an
    advanced 2D add-on library, as long as SDL allows
    add-on libs to access both OpenGL and Direct3D.

A port of some 3D engine might be the simplest way to do this.
A 2D addon lib. that supports Rotozooming, Scaling, Linedrawing
needs a little bit more work, but only for the 2D VideoModes.
The OGL and D3D part of this 2D lib. will be really small, as
most/all of these fuctions are already in these APIs.

It seems like using Direct3D together with SDL is entirely doable with
SDL 1.2 already, so I forsee no major issues there. So, I think we
could in fact have the Advanced3D add-on lib work with SDL 1.2 as
well as SDL 1.3/2.0 with little extra work.

For me SDL 1.2 is a thing of the past,
it will get bug fixes in the future.
But for binary comp. it should stay the way it is.

SDL 1.3/2.0 is the next step and
we should not try to clutter SDL 1.2.

CU

David Olofson <david olofson.net> writes:

/*

  • Ensure that changes to the current target surface are
  • made visible.
    */
    void A2D_Update(void);

I like the simple API. There is an urge to add higher level things,
but I don’t believe they should be in early releases (if ever).

Right. The consequence of adding all sorts of “handy” stuff is usually
that the thing eventually looks so big and complex that it scares
people away.

In this case, I don’t think it would take much complexity before
people just use OpenGL instead, even if that means they lose the free
Direct3D support bonus.

I have a question about this one Update call? My guess is that it is
necessary to flush or sync the drawing api before calling the
regular SDL flip/update?

Well, I’m not sure about this one, actually.

If you were to do some rendering using SDL_Advanced2D, and then lock
the target surface to grab a screenshot or something, you’d have to
make sure that the driver and hardware would actually finish
rendering. Then again, doesn’t the driver handle that automatically
as a side effect of locking the target surface? (glReadPixels(),
unless some platform specific shortcut is used…)

My guess is that the simple OpenGL video backend will already be
doing a flush before flipping?

Actually, it shouldn’t need to, I think.

The idea with the A2D_Update() was just to wrap whatever has to be
done in a concistent API for Advanced2D.

For example, if you’re rendering to an ordinary SDL surface (that is,
using the software rasterizer), A2D_Update() does nothing, as the
rendering is already done. (Well, that could change with a
multithreaded rasterizer for SMP systems, of course…)

Over SDL 1.2, there are several different ways of doing it, depending
on what kind of display setup you have. If you’re using the software
rasterizer over a 2D backend, it’s SDL_Flip(). If you’re using
OpenGL, it’s SDL_GL_SwapBuffers(). If you’re using Direct3D "over"
SDL, it’s… well, I don’t know. Something completely different, at
least! :smiley:

It feels kinda’ silly not to wrap this mess when you’re already
wrapping the rest - especially since updating the wrong way can
result in very weird problems. Also, people not used to using OpenGL
with SDL may not even be aware that there are different ways of
updating the display, even under SDL.

I think the A2D API should also obey the SDL_Surface rectangular
clipping area. It would be great if that didn’t need additional API
on the A2D side.

Yep, that’s the idea.

Is it sufficient if the clip rect is checked by the A2D_Begin() call?
(I think doing it in A2D_Target() only is a bit shaky, for no real
reason. Confusing if changing the clip rect a few times to render a
screen just doesn’t seem to work…)

I also intended to piggy-back on the texture management of SDL 1.3, as
that seems to be the sensible way of doing it. (Some extra calls
would be needed when running A2D over SDL 1.2, of course.)

Not sure if SDL needs to provide some hooks to do this stuff
properly… What I’d really want to avoid is this horrible wrapping
of SDL objects that you often end up doing when adding layers over
SDL 1.2. For low level stuff like this, that shouldn’t really be
needed. Using A2D should feel like using an SDL version with some
extra rendering capabilities.

//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 --'On Tuesday 29 August 2006 23:53, Pete Shinners wrote:

[…]

SDL should not provide any 3D commands.
Even the Analogie could be used in SDL 1.3
HW Surfaces are DirectDraw HW Surfaces or Textures
in OpenGL or D3D. SW Surfaces are really the things in
System Memory.

SDL 1.3 only needs to provide the things it did in SDL 1.2
With things i mean rectangle blitting, rectangle filling
and so on. That it supports MultWindow, Float Audio and so
on is great and makes it even more complete.

Exactly. As long as there is a way to add portable “advanced” 2D and
3D rendering by means of add-on libraries, SDL doesn’t need to - and
probably shouldn’t - deal with it directly.

As this seems to be very much doable (even over SDL 1.2, although that
would be a bit messier), I’m no longer all that interested in having
this stuff inside the SDL core. Also, I think it might be a bit
easier to maintain Advanced2D as a separate add-on library, because
that makes it dead simple to test SDL without Advanced2D anywhere
near it, test Advanced2D with other versions of SDL and things like
that.

* A nice and clean portable 3D API that runs
everywhere might be another nice project, that can
be implemented in pretty much the same way as an
advanced 2D add-on library, as long as SDL allows
add-on libs to access both OpenGL and Direct3D.

A port of some 3D engine might be the simplest way to do this.

Most 3D engines I know of are way too high level to be regarded as a
3D rendering API. They range from somewhere around "retained mode"
through nearly complete game engines.

What I’m thinking about is something like OpenGL with extensions,
feature enumerations and other mess designed cleanly into the API.
Something that you could port something like the Q3A engine over to,
to have it run over both OpenGL and Direct3D. Something that you
would use instead of OpenGL or Direct3D, because it’s nicer to deal
with and runs over both types of drivers.

Anyway, I’m not all that into 3D, so I’ll leave this to people who
are, at least until I get started on a 3D project and find that the
solution is still missing. :slight_smile:

A 2D addon lib. that supports Rotozooming, Scaling, Linedrawing
needs a little bit more work, but only for the 2D VideoModes.

Right. Don’t know how high priority this is though, as it’s very
hard to do this stuff fast, while most users who’d really need it
don’t have the CPU power to use it anyway… AFAICT, this is pretty
much only about laptops with crappy “mobile” video chipsets and fast
CPUs.

Even so, my usual excuse for implementing it anyway: A slow
implementation is a lot more useful than no implementation. :slight_smile:

Could be used for load time rendering and image processing, for
example, even if it’s “dog slow”. Many SDL 1.2 based games have
custom code for that sort of stuff - and some should have, but
don’t, because it’s too much work to implement.

The OGL and D3D part of this 2D lib. will be really small, as
most/all of these fuctions are already in these APIs.

Yeah. Apart from simplified blend modes and stuff, the proposed A2D
calls map pretty much directly to OpenGL calls with similar names and
mostly identical semantics.

It seems like using Direct3D together with SDL is entirely doable
with SDL 1.2 already, so I forsee no major issues there. So, I
think we could in fact have the Advanced3D add-on lib work with
SDL 1.2 as well as SDL 1.3/2.0 with little extra work.

For me SDL 1.2 is a thing of the past,
it will get bug fixes in the future.
But for binary comp. it should stay the way it is.

SDL 1.3/2.0 is the next step and
we should not try to clutter SDL 1.2.

Well, having the Advanced2D add-on lib support SDL 1.2 as well doesn’t
physically affect SDL 1.2. It just means you have the choice of
compiling with SDL 1.2 instead of 1.3/2.0 if you want to build an
Advanced2D application on some platform that isn’t supported by SDL
1.3/2.0. OpenGL and Direct3D acceleration will still work where
applicable, but multiwindow won’t, and an application that messes a
lot with the textures using SDL 1.3/2.0 render calls might need some
tweaking.

From the Advanced2D perspective, it’s little more than a matter of
adding texture management, I think. It almost seems stupid to not
just do it. :slight_smile:

//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 --'On Tuesday 29 August 2006 23:54, Torsten Giebl wrote:

Well, unless there are even more issues we’ve not yet brought up, I
think I’m starting to see the outline of a solution here; what should
and shouldn’t be in the SDL 1.3/2.0 core, how to deal with “advanced
2D” rendering (scaling, rotation, free form polygons etc), how to
deal with the Direct3D vs OpenGL issue etc.

The basic structure:

  • SDL video stays focused on setting up the display
    and implementing accelerated and software blits.

  • More advanced 2D rendering is left to add-on
    libraries that should support both OpenGL and
    Direct3D, and preferably also implement software
    rendering.

  • 3D is handled by means of the applications
    directly using OpenGL and/or Direct3D. (Direct3D
    for large user base with minimal effort, OpenGL for
    portability, both for maximizing the user base.)

  • A nice and clean portable 3D API that runs
    everywhere might be another nice project, that can
    be implemented in pretty much the same way as an
    advanced 2D add-on library, as long as SDL allows
    add-on libs to access both OpenGL and Direct3D.

It seems like using Direct3D together with SDL is entirely doable with
SDL 1.2 already, so I forsee no major issues there. So, I think we
could in fact have the Advanced3D add-on lib work with SDL 1.2 as
well as SDL 1.3/2.0 with little extra work.

As to the API and feature set, I’m thinking OpenGL minus all things
strictly 3D related. Matrix based transformations? I dunno… Nice
and handy (if you know your way around the maths, at least), but
maybe overkill for 2D graphics in general? Anyway, something like
this:


/* Primitives for A2D_Begin() */
typedef enum
{
A2D_POINTS,
A2D_LINES,
A2D_LINE_LOOP,
A2D_LINE_STRIP,
A2D_TRIANGLES,
A2D_TRIANGLE_STRIP,
A2D_TRIANGLE_FAN,
A2D_QUADS,
A2D_QUAD_STRIP,
A2D_POLYGON
} A2D_Primitives;

/* Modes for A2D_FilterMode() */
typedef enum
{
A2D_NEAREST,
A2D_NEAREST_MIPMAP,
A2D_LINEAR,
A2D_LINEAR_MIPMAP,
A2D_CUBIC,
A2D_CUBIC_MIPMAP
} A2D_FilterModes;

/* Modes for A2D_BlendMode() /
typedef enum
{
A2D_OPAQUE, /
Opaque rendering /
A2D_MASK, /
Copy if src alpha > 0 /
A2D_SRCALPHA, /
Source alpha blending /
A2D_DSTALPHA, /
Destination alpha blending /
A2D_ADD, /
Additive blending /
A2D_SUBTRACT, /
Subtractive blending /
A2D_MODULATE /
Modulation (multiplication) */
} A2D_BlendModes;

/*

  • Select target surface for subsequent rendering.
    */
    void A2D_Target(SDL_Surface *target);

/*

  • Select texture for subsequent rendering.
  • Pass 0 for ‘texid’ to disable texturing, for
  • same results as using an opaque white texture.
    */
    void A2D_Texture(SDL_TextureID texid);

/*

  • Set texture filtering mode.
    */
    void A2D_FilterMode(A2D_FilterModes fm);

/*

  • Set rendering blend function.
    */
    void A2D_BlendMode(A2D_BlendModes mode);

/* Rendering functions */
void A2D_Begin(A2D_Primitives prim);
void A2D_Vertex(float x, float y);
void A2D_TexCoord(float x, float y);
void A2D_ColorRGB(Uint8 r, Uint8 g, Uint8 b);
void A2D_ColorRGBA(Uint8 r, Uint8 g, Uint8 b, Uint8 a);
void A2D_End(void);

/*

  • Ensure that changes to the current target surface are
  • made visible.
    */
    void A2D_Update(void);

/*

  • Quickly fill the current target surface with the
  • specified color.
    */
    void A2D_Clear(float r, float g, float b, float a);

I really liked it up to this point. I really hate to see colors
specified both as Uint8 and float in one API. First off is the problem
of buffers with more or less than 8 bits/channel. Then there is the
recurrent problem of what exactly a value of 255 means. When people get
it right a color value of 255 means 255/255 == 1.0 But, so often people
don’t get that right and 255 means 255/256 (shift instead of divide) !=
1.0. Is it possible to stick with just one way of specifying colors?

Bob PendletonOn Tue, 2006-08-29 at 22:44 +0200, David Olofson wrote:

//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 --’


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


±-------------------------------------+

[…]

void A2D_Clear(float r, float g, float b, float a);

I really liked it up to this point. I really hate to see colors
specified both as Uint8 and float in one API.

Sorry, that wasn’t intentional. :smiley:

First off is the problem of buffers with more or less than 8
bits/channel. Then there is the recurrent problem of what exactly a
value of 255 means. When people get it right a color value of 255
means 255/255 == 1.0 But, so often people don’t get that right and
255 means 255/256 (shift instead of divide) != 1.0. Is it possible
to stick with just one way of specifying colors?

Well, I had floats everywhere first, but somehow I got inspired by the
SDL API, and decided to switch to Uint8. (But I forgot to "fix"
A2D_Clear(), obviously.)

Anyway, I think there are only two reasons to use ‘Uint8’ rather than
’float’: Argument size, and saving some cycles by avoiding FP to
integer conversions. The former is usually irrelevant as compilers
often pass ‘Uint8’ arguments as ‘int’ anyway. In fact, both reasons
are probably irrelevant, considering what kind of hardware and
polycount we’re targetting here. (Machines with 3D accelerators, and
"probably not nearly as many as in an AAA 3D game.")

//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 --'On Wednesday 30 August 2006 22:53, Bob Pendleton wrote: