Rewrite input system for hot-plugging

2009/9/8 Mason Wheeler <@Mason_Wheeler>:

Or I
suppose you could rewrite malloc/new to zero the dynamic memory it
allocates before returning.

that would be calloc ( http://www.cppreference.com/wiki/c/mem/calloc )

Yeah. Shame that doesn’t work for objects. (Or is there a cnew operator
I’ve never heard of?)

Objects, on the other hand, tend to be very small. It’s not very common
to see one with an instance size over 200 bytes. (Especially if you don’t
go allocating other large objects or arrays as value types within your
object.)

And then you have arrays of objects… or objects allocated and freed
in a loop (generally bad programming, but still pretty common).

I just tested it. Best not to worry about possible performance impacts
unless they’re real bottlenecks, right? So I wrote a quick Delphi app
(Delphi’s object model zeroes out its memory as part of the construction
process) to test a real-world scenario: create a bunch of sprite objects
to populate a game map with, using the same sprite class as I use in
my game engine. I ran a loop through 1 million iterations and had it
report a timestamp before and after.

Total time: 203 miliseconds. Instance size: 132 bytes. (132 MB total)
Most sprites I’ve ever actually instantiated at once under real-world
conditions? A few thousand.

Granted, this is an overpowered premium gaming rig by Alienware, but
results on less powerful systems, such as my last laptop, don’t vary
by all that much. Zeroing a contiguous block of memory, especially
one measured in bytes as opposed to K or MB, is a highly efficient
operation. You can do it 4 bytes at a time, or even faster with SIMD
tricks. The performance hit is negligible enough that you’re not likely
to ever actually notice it.

raises an eyebrow OK, let’s take the program I work on at work. Serious
app. Around 3.5M lines of code. One COM object to work with an external
DLL. One comm subsystem that handles connections with a handful of
middle-tier app servers. Maybe a few dozen synchronization objects, and
of course a few thousand Windows handles for all the GUI stuff, user input,
and a little bit of file handling. And hundreds of thousands of objects that
get allocated in process memory. The middle-tier servers look a lot like
that, too. A bit more comm stuff, a whole lot less GUI, but a similar
overall distribution. And I don’t think there are very many apps that don’t
look like that.

Not many programs make it to 3.5 million lines of code… In a
smaller program, I expect a much larger proportion of code and memory
would be devoted to GUI, I/O, networking and system calls, or whatever
libraries it’s using. It would also vary greatly by the type of
program you’re writing.

Well, the editor for the game engine I’m working on currently weighs in at
around 200k lines of code total. Much less GUI than the enterprise-level app
at work, (about 10 forms instead of a few hundred), no networking (yet), a
fair amount of file handling, including a plugin system, and an SDL interface
to display the graphics. And thousands of objects and arrays.

I can really only see external resources becoming a significant fraction of
total resources if you scale it way down to trivial apps. Windows
Calculator, for example, which has a fairly involved GUI in Scientific mode
but almost no need for state.>----- Original Message ----

From: Kenneth Bull
Subject: Re: [SDL] Rewrite input system for hot-plugging

Kenneth Bull wrote:

2009/9/8 Rainer Deyke :

How is left-shifting a pixel by an image an intuitive operation?

Is left shifting an output stream by a string any better?

Streaming an image to a pixel is no better than left-shifting a pixel by
an image. Both are nonsensical operations.–
Rainer Deyke - rainerd at eldwood.com

2009/9/8 Rainer Deyke :

Kenneth Bull wrote:

?You can
have a general surface class which handles pixel format just like
SDL_Surface does now, but that doesn’t have to be the only surface
class available.

In which case you’re sacrificing simplicity.

Not really. Inheriting from a class does not automatically complicate
the parent class. It’s exactly the same whether you inherit from it
or not.

?A 32-bit or 8-bit surface class could run much
faster when setting or retrieving pixel values or converting colors to
pixel data than a more general class would.

This is better handled by a wrapper class than by inheritance, IMO.

Only if you’re using the existing SDL_Surface structure, which at
present handles none of this itself anyway, so you’d need a wrapper
even for the usual case (which brings inheritance back in to get your
wrappers working together). There is no point in using a wrapper on a
C++ class you can actually edit.

?It also allows formats
which can’t be represented using the standard pixel format, like
anything with less than 8-bits per pixel or that uses a color system
other than RGB.

Fundamentally, SDL needs to be able to understand the pixel format in
order to use it.

And defining the members of that class gives SDL that ability.

Having jpeg and png surfaces would allow you to trade time when
actually displaying the image for lower load time and memory
consumption.

If you display the image even once, you lose any speed gains you made.

The advantage then is that you don’t have one big delay when loading
all your images at once. It’s spread out instead. If you normally
have processor time to spare, but you want you program up and running
quickly, then this will help. Depending on what you’re doing that
memory consumption bit can be a pretty big advantage too.

As I said though, this isn’t something you’ll want in all cases all the time.

For multiple pixels, you could use something like this:

uint32_t data = surface.format.FormatColor(Color(1.0, 0.0, 0.0));
Pixel pixel(surface, x, y);

then, to set a pixel:
pixel = data;

‘a = b’ should not have any side effects beyond setting local variable
’a’ equal to ‘b’. ?’*pixel = data;’, maybe.

*thing = data is two operations, *this and intermediate_object = data. pixel is already in the intermediate_object set.
Remember surface(x, y) = Color(1.0, 0.0, 0.0);? Here’s what
operator(x, y) would look like:

class Surface {
public:
//…
Pixel operator()(x, y);
ConstPixel operator()(x, y) const;
Region operator()(x, y, w, h);
ConstRegion operator()(x, y, w, h) const;
//…
};

Pixel Surface::operator()(x, y) {
return Pixel(*this, x, y);
}

//…

(where ConstPixel and ConstRegion are Pixel and Region without any of
the output methods/operators).

If you really want to be picky, you could have no public constructor
for Pixel, define Surface as a friend class to Pixel, then use
Pixel& pixel = surface(x, y);
instead of
Pixel pixel(surface, x, y);

So keep the signal/slot library separate from the rest so other
libraries can use it without depending on SDL.
(like this one for example: ?http://sourceforge.net/projects/signalslot/ )

I like the Boost signal/slot library, but I don’t want SDL to use that
either. ?The input dispatch mechanism should be left up to the application.

Example: it’s not unusual for games to implement mini-games that use
their own input schemes. ?This is simple enough to implement using SDL:

void run_mini_game() {
?// Local event loop here.
}

void main_game() {
?for (;:wink: { // Main event loop.
? ?//…
? ?if (cond) run_mini_game();
? ?//…
?}
}

Now, if you use a na?ve signal/slot system, you will have to unregister
all of your event handlers at the start of the mini game and reregister
them at the end. ?If you do your own event dispatching, you can simply
choose not to dispatch events from inside the mini game to the outer game.

I’ve put together an input system like this before (using wrappers
around SDL). The solution to that particular problem is to have
several dispatcher objects which pull events from the same queue. So,
to switch to your mini game input or back, you just switch
dispatchers. If you have certain events which stay the same, then you
chain from one dispatcher to another.

Like this:

Input::Dispatcher* currentDispatcher = 0;

Input::Instance input;
Input::Dispatcher commonDispatcher(input);
Input::Dispatcher mainDispatcher(input);

Adapter1_0Input::Keyboard::Key
escapeKeyPressed(commonDispatcher.KeyPressed, Input::keyboard::EscapeKey);
escapeKeyPressed.connect(handler, &MyHandler::quit);

mainDispatcher.bind(commonDispatcher);

// connect slots for mainDispatcher
//…

currentDispatcher = &mainDispatcher;

while (handler.running) {
currentDispatcher.Wait(); // or .Poll()
}

I’m sure you can figure it out from there.

2009/9/9 Rainer Deyke :

Streaming an image to a pixel is no better than left-shifting a pixel by
an image. ?Both are nonsensical operations.

So call it Position instead of Pixel. While it is generally
recommended that overloaded operators do some equivalent to their
usual operation, it’s not required.

2009/9/9 Kenneth Bull <@Kenneth_Bull>:

?while (handler.running) ?{
? ?currentDispatcher.Wait(); // or .Poll()
?}

-> not .
that’s twice in one day…

2009/9/8 Mason Wheeler :>>----- Original Message ----

Or I
suppose you could rewrite malloc/new to zero the dynamic memory it
allocates before returning.

that would be calloc ( http://www.cppreference.com/wiki/c/mem/calloc )

Yeah. ?Shame that doesn’t work for objects. ?(Or is there a cnew operator
I’ve never heard of?)

new calls the object’s constructor. If that’s not good enough, you
can make a custom allocator to zero the memory (
http://www.cplusplus.com/reference/std/memory/allocator/ ).

Kenneth Bull wrote:

2009/9/8 Mason Wheeler :

Or I
suppose you could rewrite malloc/new to zero the dynamic memory it
allocates before returning.

that would be calloc ( http://www.cppreference.com/wiki/c/mem/calloc )

Yeah. Shame that doesn’t work for objects. (Or is there a cnew operator
I’ve never heard of?)

new calls the object’s constructor. If that’s not good enough, you
can make a custom allocator to zero the memory (
http://www.cplusplus.com/reference/std/memory/allocator/ ).

Don’t forget that like other operators in C++, you can overload ::new().
Before calling an objects constructor, ::new allocates sizeof(object)
bytes. Overloading ::new is a great way to handle out of memory
conditions (assuming you have reason and a strategy) and is also a great
way to over allocate so that you can track memory over/under writes,
reference counting, etc.

Of course once you overload the global new, you’ll want to overload the
global delete.

Also, if you don’t care to handle all uses of operator new, you can
overload new as a virtual function in a base class and then inherit from
that class in order to focus a special new/delete pair for a specific
set of data types.>>> ----- Original Message ----

2009/9/9 CWC :

Don’t forget that like other operators in C++, you can overload ::new().
Before calling an objects constructor, ::new allocates sizeof(object) bytes.
Overloading ::new is a great way to handle out of memory conditions
(assuming you have reason and a strategy) and is also a great way to over
allocate so that you can track memory over/under writes, reference counting,
etc.

you might want to look into set_new_handler (
http://www.cplusplus.com/reference/std/new/set_new_handler/ ), which
sets the function called when new fails.

I believe you can also do something like this (bad form though…):

#include

//…

uint8_t* tmp_pointer = new uint8_t[sizeof(Object)];
Object* obj_pointer = new (tmp_pointer) Object(arg);

The first new calls the default constructor for uint8_t on each byte
of memory it allocates, which sets each byte to 0.
The second calls the constructor for the object itself on the memory
already allocated by the first one.
Of course, this is insane and only conceivably useful for broken
classes you can’t fix for some reason.

Kenneth Bull wrote:

2009/9/8 Rainer Deyke :

In which case you’re sacrificing simplicity.

Not really. Inheriting from a class does not automatically complicate
the parent class. It’s exactly the same whether you inherit from it
or not.

Not true, but beside the point anyway. By including a class hierarchy
instead of a single class in SDL, you are complicating SDL.

This is better handled by a wrapper class than by inheritance, IMO.

Only if you’re using the existing SDL_Surface structure, which at
present handles none of this itself anyway, so you’d need a wrapper
even for the usual case (which brings inheritance back in to get your
wrappers working together). There is no point in using a wrapper on a
C++ class you can actually edit.

This is better handled by a wrapper class at the application framework
level
, separate from SDL. And without virtual functions.

And there is actually a very good reason for writing wrapper classes
even if you have the source to the original class. Each class should
have exactly one responsibility. If you have a complex task, it is
better to factor the functionality into two (or more classes), with the
high-level class using the low-level class.

Fundamentally, SDL needs to be able to understand the pixel format in
order to use it.

And defining the members of that class gives SDL that ability.

Blitting between N fundamentally different pixel formats requires N^2
different blitters. This is not a simple problem, either within SDL or
as a layer above SDL.

Within SDL, if you really want special pixel formats, it’s best to
extend the pixel format type so that all surfaces can use that pixel
format instead of writing a new surface class. Composition beats
inheritance.

Above SDL, the most sensible thing to do is to write a new image class
with a function that converts the image to a surface in a format that
SDL does support.

If you display the image even once, you lose any speed gains you made.

The advantage then is that you don’t have one big delay when loading
all your images at once. It’s spread out instead. If you normally
have processor time to spare, but you want you program up and running
quickly, then this will help. Depending on what you’re doing that
memory consumption bit can be a pretty big advantage too.

So, don’t load all your resources up front. And free them when you are
done with them. You should be doing that anyway.

Again, this is high-level functionality, logically separate from the
low-level surface which represents an image already loaded and decompressed.

‘a = b’ should not have any side effects beyond setting local variable
’a’ equal to ‘b’. ‘*pixel = data;’, maybe.

*thing = data is two operations, *this and intermediate_object = data. pixel is already in the intermediate_object set.
Remember surface(x, y) = Color(1.0, 0.0, 0.0);?

You are horribly overcomplicating things here.

Color c = surface(x, y);
surface(x, y) = c;
Color *pixel = &surface(x, y);
*pixel = c;

Ideally, ‘Color’ should be a plain integer type (such as uint32_t), but
that requires a specific bit depth for the surface and doesn’t work at
all for 24 bit surfaces. Which is why I feel that type-safe pixel
access should be moved to wrapper classes that can assume a specific bit
depth.

I’ve put together an input system like this before (using wrappers
around SDL). The solution to that particular problem is to have
several dispatcher objects which pull events from the same queue.

Yeah, there are all kinds of possible solutions. They belong in your
application framework, not in SDL.

Ideally, I want to restrict knowledge of SDL to the lowest levels of the
framework. That way my framework can switch between SDL and something
else (SFML?) with relative ease.–
Rainer Deyke - rainerd at eldwood.com

Kenneth Bull wrote:

2009/9/9 Rainer Deyke :

Streaming an image to a pixel is no better than left-shifting a pixel by
an image. Both are nonsensical operations.

So call it Position instead of Pixel. While it is generally
recommended that overloaded operators do some equivalent to their
usual operation, it’s not required.

It’s also not required that a function called ‘print_instructions’ does
anything of the sort, but it’s still exceedingly bad style to use that
name for a function that calculates square roots.–
Rainer Deyke - rainerd at eldwood.com

Kenneth Bull wrote:

2009/9/9 CWC <@charlesw>:

Don’t forget that like other operators in C++, you can overload ::new().
Before calling an objects constructor, ::new allocates sizeof(object) bytes.
Overloading ::new is a great way to handle out of memory conditions
(assuming you have reason and a strategy) and is also a great way to over
allocate so that you can track memory over/under writes, reference counting,
etc.

you might want to look into set_new_handler (
http://www.cplusplus.com/reference/std/new/set_new_handler/ ), which
sets the function called when new fails.

That is interesting, but if you have created your own new operator, then
you have total control over it’s action in case of failure. In other
words, ::new() contains it’s own handler and therefore only fails to
return under the conditions that you define. (Also, you’re free to use
calloc for all allocations therefore giving you the previously discussed
situation where all allocations are explicitly zeroed before construction).

I believe you can also do something like this (bad form though…):

#include

//…

uint8_t* tmp_pointer = new uint8_t[sizeof(Object)];
Object* obj_pointer = new (tmp_pointer) Object(arg);

The first new calls the default constructor for uint8_t on each byte
of memory it allocates, which sets each byte to 0.
The second calls the constructor for the object itself on the memory
already allocated by the first one.
Of course, this is insane and only conceivably useful for broken
classes you can’t fix for some reason.

There’s always more than one way to skin a cat, our job as programmers
is to find the best one(s) for our circumstances.

2009/9/9 Rainer Deyke :

And there is actually a very good reason for writing wrapper classes
even if you have the source to the original class. ?Each class should
have exactly one responsibility. ?If you have a complex task, it is
better to factor the functionality into two (or more classes), with the
high-level class using the low-level class.

That isn’t really a wrapper class…
By that definition just almost every class ever made would be a
wrapper around int.

Anyway, if you really don’t like inheritance, complain to
comp.lang.c++, not SDL.

Blitting between N fundamentally different pixel formats requires N^2
different blitters. ?This is not a simple problem, either within SDL or
as a layer above SDL.

Or, you could use a single intermediate format and define blits to and
from that format.

Within SDL, if you really want special pixel formats, it’s best to
extend the pixel format type so that all surfaces can use that pixel
format instead of writing a new surface class. ?Composition beats
inheritance.

You can only extend the SDL_PixelFormat within the source of SDL
itself, and tracking down all the different functions you need to
modify to make sure it still works would be a pretty big task in
itself. If you wanted to extend it from a seperate library or within
a user program, it would have to be a class so you could subclass it.
Making it a class also keeps everything in one place so that, if you
do need to change it, everything is there in one place.

So, don’t load all your resources up front. ?And free them when you are
done with them. ?You should be doing that anyway.

disk access is generally much more expensive then CPU cycles.

Again, this is high-level functionality, logically separate from the
low-level surface which represents an image already loaded and decompressed.

And again, this is also useful to avoid loss when dealing with lossy
compression algorithms, which is something that would require support
from SDL.

You are horribly overcomplicating things here.

Color c = surface(x, y);
surface(x, y) = c;
Color *pixel = &surface(x, y);
*pixel = c;

Ideally, ‘Color’ should be a plain integer type (such as uint32_t), but
that requires a specific bit depth for the surface and doesn’t work at
all for 24 bit surfaces. ?Which is why I feel that type-safe pixel
access should be moved to wrapper classes that can assume a specific bit
depth.

Ideally, Color would be the same type for all surfaces. What you’re
suggesting would work for either 8, 16 or 32-bit surfaces (but only
one of those, not all three, and only with specific bit masks). To
get it to work for all surfaces, you do indeed need a wrapper, and an
additional pixel buffer, and some method to detect and write changes
in the additional buffer to the actual surface. This means at least
double the memory, a lot more processor time and lag between writing a
pixel and the pixel actually showing up on the surface. That is,
unless you only want to support 1 pixel format.

Yeah, there are all kinds of possible solutions. ?They belong in your
application framework, not in SDL.

Ideally, I want to restrict knowledge of SDL to the lowest levels of the
framework. ?That way my framework can switch between SDL and something
else (SFML?) with relative ease.

How many frameworks, toolkits and widgets do you plan on stacking on
top of each other?
A wrapper around a wrapper around an API is at least one too many wrappers.

SDL already wraps direct3d, directdraw, opengl, vgl, fbcons, nanox, x11, …
Under what possible conditions would your program need to be
compatible with both simultaneously?
Once you’ve developed your framework, and discover someone else’s
framework that catches your interest, are you going to make another
framework so you can switch between those too?
There is a limit to how far you can take this and still blit a sprite
in under 5 minutes…

Kenneth Bull wrote:

Anyway, if you really don’t like inheritance, complain to
comp.lang.c++, not SDL.

I like inheritance. I don’t like the misuse of inheritance for problems
that could be better solved using composition.

Blitting between N fundamentally different pixel formats requires N^2
different blitters. This is not a simple problem, either within SDL or
as a layer above SDL.

Or, you could use a single intermediate format and define blits to and
from that format.

Format conversions are expensive!

If you want to go that route, you’re better off caching the
immediate-format surfaces so they can be reused. You’re also better off
separating high-level surfaces (which can have any pixel format you
want) from low-level surfaces (which are in a common format). Let’s
call the high-level surfaces “images” and put them in user land while
the low-level surfaces remain in SDL land.

Incidentally, I’m very glad that SDL is not limited to a single pixel
format. Imagine that SDL was limited to 32bpp (which seems like the
most sensible format):

  • Rendering to non-32bpp devices would require significantly more
    memory bandwidth on the system side, plus an expensive conversion.
  • There would be no way to set the palette on 8bpp devices.
    And I’m saying this even though my own image class is restricted to 32bpp.

So, don’t load all your resources up front. And free them when you are
done with them. You should be doing that anyway.

disk access is generally much more expensive then CPU cycles.

Actually decompression is often more expensive than disk access,
especially if you use a good compression algorithm. But you can always
cache compressed images in RAM if you want to. Or you can let your disk
cache do it for you. Same difference.

Again, this is high-level functionality, logically separate from the
low-level surface which represents an image already loaded and decompressed.

And again, this is also useful to avoid loss when dealing with lossy
compression algorithms, which is something that would require support
from SDL.

SDL does not support blitting to/from compressed formats. If you write
your own blitter, you might as well not bother with SDL.

Ideally, I want to restrict knowledge of SDL to the lowest levels of the
framework. That way my framework can switch between SDL and something
else (SFML?) with relative ease.

How many frameworks, toolkits and widgets do you plan on stacking on
top of each other?
A wrapper around a wrapper around an API is at least one too many wrappers.

I have my own graphics layer, which can use SDL, OpenGL (through SDL),
or Direct3D as back-end. This layer implements several features that
are difficult to achieve in SDL directly, such as color transformations
on blits.

Above that is my graphics context, which keeps track of cumulative
transformations. I can, for example, create a rotated or flipped
context and render to that in order to flip or rotate everything on the
screen.

Above that are my high-level graphics routines for drawing things like
text. I managed to abstract most of the text rendering so that it can
render into arbitrary 2D arrays anywhere in memory.

Above /that/ are my gui libraries, followed by my game libraries,
followed by my actual games.

None of the layers completely hide the layer below it, but all add
significant functionality. The entire system is highly efficient. The
weakest link in the chain is SDL.

SDL already wraps direct3d, directdraw, opengl, vgl, fbcons, nanox, x11, …
Under what possible conditions would your program need to be
compatible with both simultaneously?

SDL supports a wide range of platforms, but it has a number of problems,
both in terms of features and in terms of performance. I’m not planning
on dropping support for SDL in the near future, but at the same time I
don’t want to be tied too closely to SDL either.

Once you’ve developed your framework, and discover someone else’s
framework that catches your interest, are you going to make another
framework so you can switch between those too?

I only use 3rd party libraries if they solve some problem for me. If I
already have my own framework, then I have no more need for a 3rd party
with similar functionality.–
Rainer Deyke - rainerd at eldwood.com

2009/9/9 Rainer Deyke :

Kenneth Bull wrote:

Blitting between N fundamentally different pixel formats requires N^2
different blitters. ?This is not a simple problem, either within SDL or
as a layer above SDL.

Or, you could use a single intermediate format and define blits to and
from that format.

Format conversions are expensive!

Some, yes, depending on how you do it. Also, keep in mind that you
can have a blitter that supports more than one simple format (a
single blitter could easily support all possible conversions between
bitmapped RGB formats compatible with the current SDL_PixelFormat).

If you want to go that route, you’re better off caching the
immediate-format surfaces so they can be reused. ?You’re also better off
separating high-level surfaces (which can have any pixel format you
want) from low-level surfaces (which are in a common format). ?Let’s
call the high-level surfaces “images” and put them in user land while
the low-level surfaces remain in SDL land.

that would be what SDL_DisplayFormat is for.

Incidentally, I’m very glad that SDL is not limited to a single pixel
format. ?Imagine that SDL was limited to 32bpp (which seems like the
most sensible format):
?- Rendering to non-32bpp devices would require significantly more
memory bandwidth on the system side, plus an expensive conversion.
?- There would be no way to set the palette on 8bpp devices.
And I’m saying this even though my own image class is restricted to 32bpp.

I’ve rarely had to deal with anything other than 32-bpp myself (at
least on modern platforms), but you’re right, I wouldn’t want to give
up support for those other formats either. I’d actually like to see
support for 1-bpp (monochrome) and 16-bpp paletted formats, as well as
grey-scale and grey-scale + alpha.

Actually decompression is often more expensive than disk access,
especially if you use a good compression algorithm. ?But you can always
cache compressed images in RAM if you want to. ?Or you can let your disk
cache do it for you. ?Same difference.

That depends on your definition of “good”. Most compression
algorithms focus on high compression rate, but also, low memory and
CPU during decompression. It’s compression which is most time
consuming. Decompressing simple compression schemes, like most RLE
compression, can actually run faster than just moving around
uncompressed data.

SDL does not support blitting to/from compressed formats. ?If you write
your own blitter, you might as well not bother with SDL.

It does actually, but only one format. SDL does have RLE compressed
sprites. That’s where the SDL_RLEACCEL flag comes from in
SDL_video.h.

But really, the answer is to make SDL easier to extend, or to add the
features you want to the library itself. SDL is open source and the
developers actually do accept worthwhile patches from the community.
It is not one big opaque immovable object where if something doesn’t
seem to work the way you want you say “oh well” and look elsewhere.
You can see how it works, you can change how it works, and you can
make it do new things.

I have my own graphics layer, which can use SDL, OpenGL (through SDL),
or Direct3D as back-end. ?This layer implements several features that
are difficult to achieve in SDL directly, such as color transformations
on blits.

Again, write a patch and you can add this to SDL itself.

Above that is my graphics context, which keeps track of cumulative
transformations. ?I can, for example, create a rotated or flipped
context and render to that in order to flip or rotate everything on the
screen.

This is a very nice feature to have, but it could also be implemented
as a transformation matrix in a surface class or drawing function.
You could, in fact, make a Filter class subclassed from Surface (or
SurfaceBase, or whatever) so that it acts like a surface itself, but
passes any reads or writes through to an actual surface after applying
whatever transformations you’re using. Filter classes could then
stack to apply multiple effects, or you could define operators to
combine transformation matrices for use in a single Filter. The
advantage is that using a surface with a filter and using one without
works exactly the same way, so it’s much simpler to add or remove a
filter without changing half your code.

Above that are my high-level graphics routines for drawing things like
text. ?I managed to abstract most of the text rendering so that it can
render into arbitrary 2D arrays anywhere in memory.

That’s nice, but not necessarily useful. What are you going to do
with text other than display it or write it to an image file?

My own occasional delusion is making a library and data format which
can handle samples with any number of channels of various mixed types
in any number of dimensions. The idea is to use one library for
manipulation of sound, images, video, voxels, animated voxels, text,
abstract data, or any combination. Of course such a library would
probably suck at all of the above, and nothing else would handle the
files it produces.

Adding a data channel to png on the other hand, makes much more sense.

Above /that/ are my gui libraries, followed by my game libraries,
followed by my actual games.

None of the layers completely hide the layer below it, but all add
significant functionality. ?The entire system is highly efficient. ?The
weakest link in the chain is SDL.

SDL already wraps direct3d, directdraw, opengl, vgl, fbcons, nanox, x11, …
Under what possible conditions would your program need to be
compatible with both simultaneously?

SDL supports a wide range of platforms, but it has a number of problems,
both in terms of features and in terms of performance. ?I’m not planning
on dropping support for SDL in the near future, but at the same time I
don’t want to be tied too closely to SDL either.

So stop working around it and fix it.

Once you’ve developed your framework, and discover someone else’s
framework that catches your interest, are you going to make another
framework so you can switch between those too?

I only use 3rd party libraries if they solve some problem for me. ?If I
already have my own framework, then I have no more need for a 3rd party
with similar functionality.

Good, but keep in mind that if you have something which is generally
useful, it can be generally useful to someone else too. You can
always release your own library (barring NDAs, etc), or contribute
parts of your code to existing libraries.

Kenneth Bull wrote:

The one reason I can see for keeping C++ out of libraries is that the
C++ standard doesn’t define an ABI like C does.
Specifically, the manner in which C++ classes are stored varies wildly
from one compiler to the next, or even different version of the same
compiler.

Yup.

This isn’t really a big deal though since, on Windows, you can just
include the library with your program, and on linux, you generally use
the same compiler to compile just about everything.

What about on other platforms? Furthermore can you guarantee that every
platform has a sane C++ compiler? If you’ve ever had to work on a
project where one of the targets is VC6 you’ll appreciate this point ;).
Now you’ve got a C++ ABI, how do you do bindings for other languages?
Wrap the C++ API in a C API in a (e.g.) Python API?

The relative merits and demerits of C++ as a language (as this thread
appears to have degenerated into) are all very interesting, but not so
important in the grand scheme of things. The practicalities of using the
library on the other hand are important, in my opinion… and C++ based
libraries are not very practical.

2009/9/9 Tim Angus :

What about on other platforms? Furthermore can you guarantee that every
platform has a sane C++ compiler? If you’ve ever had to work on a project
where one of the targets is VC6 you’ll appreciate this point ;). Now you’ve
got a C++ ABI, how do you do bindings for other languages? Wrap the C++ API
in a C API in a (e.g.) Python API?

gcc works on just about everything, so far as I can tell. And again,
I need to stress that I’m not talking about replacing the C API, but
rather adding a C++ API alongside it.

The relative merits and demerits of C++ as a language (as this thread
appears to have degenerated into) are all very interesting, but not so
important in the grand scheme of things. The practicalities of using the
library on the other hand are important, in my opinion… and C++ based
libraries are not very practical.

C is more portable, but C++ isn’t all that bad either. I’m talking
nice compatible well written C++ code, not TR1 or whatever. C++ is
practical, not necessarily as a system DLL, but staticly linked, or
shared on a system with a standard C++ compiler.

Kenneth Bull wrote:

And again, I need to stress that I’m not talking about replacing the
C API, but rather adding a C++ API alongside it.

Ah OK, in that case there is no problem; your proposed C++ API is
just-another-language-binding and none of the advantages of the C
API/library are lost. There are already a few C++ wrappers in various
states, by the way.

Kenneth Bull wrote:

2009/9/9 Rainer Deyke :

Format conversions are expensive!

Some, yes, depending on how you do it.

All, always. Even if the format conversion itself is free, you still
end up with an extra blit.

Also, keep in mind that you
can have a blitter that supports more than one simple format (a
single blitter could easily support all possible conversions between
bitmapped RGB formats compatible with the current SDL_PixelFormat).

That’s not the way SDL currently works, and for good reason. For
optimal performance, you need different blitters for different bit
depths, different blitters for different color masks within a bit depth,
different blitters for different options (i.e. color key or not, alpha
or not, special handling of 50% alpha, etc.), different blitters for
different hardware (SSE, MMX, etc.).

But really, the answer is to make SDL easier to extend, or to add the
features you want to the library itself. SDL is open source and the
developers actually do accept worthwhile patches from the community.
It is not one big opaque immovable object where if something doesn’t
seem to work the way you want you say “oh well” and look elsewhere.
You can see how it works, you can change how it works, and you can
make it do new things.

SDL is (meant to be) a simple hardware abstraction layer, not a
comprehensive framework for all graphics programming.

I have my own graphics layer, which can use SDL, OpenGL (through SDL),
or Direct3D as back-end. This layer implements several features that
are difficult to achieve in SDL directly, such as color transformations
on blits.

Again, write a patch and you can add this to SDL itself.

I don’t want this functionality in SDL. My graphics layer makes some
rather specific cost/benefit trade-offs that aren’t universally
applicable. Sometimes they aren’t even applicable in my own programs,
in which case I tweak, fork, or replace my graphics layer.

Above that is my graphics context, which keeps track of cumulative
transformations. I can, for example, create a rotated or flipped
context and render to that in order to flip or rotate everything on the
screen.

This is a very nice feature to have, but it could also be implemented
as a transformation matrix in a surface class or drawing function.

I don’t even want this functionality to be part of my graphics layer,
let alone SDL. It’s a separate layer. I can (and sometimes do) use my
graphics layer without this additional layer.

You could, in fact, make a Filter class subclassed from Surface (or
SurfaceBase, or whatever) so that it acts like a surface itself, but
passes any reads or writes through to an actual surface after applying
whatever transformations you’re using. Filter classes could then
stack to apply multiple effects, or you could define operators to
combine transformation matrices for use in a single Filter. The
advantage is that using a surface with a filter and using one without
works exactly the same way, so it’s much simpler to add or remove a
filter without changing half your code.

The whole point of my design is that the exact same function that
renders a scene upright in full color can render the same scene in
grayscale upside-down just by passing in a different graphics context.
There is no need for filters as you describe them.

One key element of my design is that transforms are “flattened”. You
can apply dozens of spatial transforms and color transforms to a single
graphics context, but this is all reduced to a single arbitrary spatial
transform and a single color transform which are then handed off to the
blitter.

Above that are my high-level graphics routines for drawing things like
text. I managed to abstract most of the text rendering so that it can
render into arbitrary 2D arrays anywhere in memory.

That’s nice, but not necessarily useful. What are you going to do
with text other than display it or write it to an image file?

Pass it off to a different graphics API. My graphics layer (described
above) is designed for 2D. What if I want to display text in a 3D
OpenGL application?

SDL supports a wide range of platforms, but it has a number of problems,
both in terms of features and in terms of performance. I’m not planning
on dropping support for SDL in the near future, but at the same time I
don’t want to be tied too closely to SDL either.

So stop working around it and fix it.

I’m not really in any position to fix (for example) Unicode input in
SDL. My own understanding of the issues involved is rather superficial,
and I’m not familiar with any of the low-level APIs involved.

I only use 3rd party libraries if they solve some problem for me. If I
already have my own framework, then I have no more need for a 3rd party
with similar functionality.

Good, but keep in mind that if you have something which is generally
useful, it can be generally useful to someone else too. You can
always release your own library (barring NDAs, etc), or contribute
parts of your code to existing libraries.

My framework is in a constant state of flux. I might release the
low-level layers if they ever stabilize.–
Rainer Deyke - rainerd at eldwood.com

Yeah, that’s pretty nice :slight_smile:
I think RAII is an intuitive addition to OOP and it’s a shame that
more languages don’t have the constructs to support it.

Jonny DOn Tue, Sep 8, 2009 at 4:12 PM, Donny Viszneki <donny.viszneki at gmail.com> wrote:

The scoped lock is an incontrovertible victory IMHO


http://codebad.com/

In scientific applications, I would not be happy waiting for my
several gigabyte (or potentially much larger) arrays to fill with
zeros…

Jonny DOn Tue, Sep 8, 2009 at 11:58 PM, Mason Wheeler wrote:

Granted, this is an overpowered premium gaming rig by Alienware, but
results on less powerful systems, such as my last laptop, don’t vary
by all that much. ?Zeroing a contiguous block of memory, especially
one measured in bytes as opposed to K or MB, is a highly efficient
operation. ?You can do it 4 bytes at a time, or even faster with SIMD
tricks. ?The performance hit is negligible enough that you’re not likely
to ever actually notice it.