Using the same palette in multiple surfaces

Hi!

I have a game which generates small animations by changing the palette
of the tiles. For performance reasons it would be optimal, if only one
palette has to be changed.

So, is it possible to use one palette structure in multiple surfaces?

Thanks,
Christian

Hi!

I have a game which generates small animations by changing the palette of the tiles. For performance reasons it >would be optimal, if only one palette has to be changed.

So, is it possible to use one palette structure in multiple surfaces?

Thanks,
Christian

Yeah, if you’re careful. The palettes are accessed through a pointer
in the Pixel Format. Change this on all the new surfaces you create to
the palette of the first surface.

IMPORTANT NOTE:
SDL doesn’t expect you to be doing something like this. When it frees
the first surface, it frees the pixel format, which frees the palette.
In order to prevent a handful of memory corruption issues, you need a
workaround like this:

  1. Create a pointer list of some sort. If you’re using C++, an STL
    queue would work well for this purpose. If not, use something else.
    It needs to keep track of an arbitrary number of pointers and how many
    it currently has in the list.
  2. Each time you swap the palette of one SDL_Surface out for another
    one, place the original palette pointer for that image on the list.
  3. Each time you free an SDL_Surface, before the actual SDL_FreeSurface
    call, replace its palette with the first one from the list, and remove
    that pointer from the list. It doesn’t have to be the same one the
    surface started out with; it just needs a unique palette when you free
    it. (And all the palettes need to get freed or they’ll leak.)

Note: I haven’t tested any of this. I’m just writing doing this all
off the top of my head. It may not work, but it should get you pretty
close.>----- Original Message ----

From: Christian Meyer
Subject: [SDL] Using the same palette in multiple surfaces

Maybe not. Seems to me if he’s using C++, he has probably encapsulated
SDL surfaces with a class. A class member variable can keep the
pointer handy. Less CPU and memory usage, and much cleaner code!On Sat, Dec 13, 2008 at 8:50 AM, Mason Wheeler wrote:

  1. Create a pointer list of some sort. If you’re using C++, an STL
    queue would work well for this purpose. If not, use something else.
    It needs to keep track of an arbitrary number of pointers and how many
    it currently has in the list.


http://codebad.com/

I have a game which generates small animations by changing the palette of
the tiles. For performance reasons it would be optimal, if only one palette
has to be changed.

Changing a single logical palette used by many surfaces won’t really
improve performance all that much (you’ll still need to redraw
everything, because the logical palettes are processed at blit time).

If you change the physical palette (of which there’s just one), then
you’ll affect everything and you don’t need to redraw anything (if you
use a real paletted mode, it will just change colours, if not, SDL
will take care of emulating it for you).On Sat, Dec 13, 2008 at 5:57 AM, Christian Meyer wrote:


http://pphaneuf.livejournal.com/

Donny Viszneki schrieb:> On Sat, Dec 13, 2008 at 8:50 AM, Mason Wheeler wrote:

  1. Create a pointer list of some sort. If you’re using C++, an STL
    queue would work well for this purpose. If not, use something else.
    It needs to keep track of an arbitrary number of pointers and how many
    it currently has in the list.

Maybe not. Seems to me if he’s using C++, he has probably encapsulated
SDL surfaces with a class. A class member variable can keep the
pointer handy. Less CPU and memory usage, and much cleaner code!

Yes an encapsulating class already exists. But simply exchanging the
pointer to the palette does not work. SDL stores internally some sort of
colormapping, so the palette change has no effect. I believe it is
stored in the struct ‘map’ in the surface, which is inaccessible. With
calling SDL_SetColors for each surface, the animations work. But I have
a large amount of small tiles, so the way “copy palette from surface,
change the palette, copy it back to the surface via SDL_SetColors” has a
noticeable effect on the frame rate.

Anyone an idea how to solve this?

Yes an encapsulating class already exists. But simply exchanging the pointer
to the palette does not work. SDL stores internally some sort of
colormapping, so the palette change has no effect. I believe it is stored in
the struct ‘map’ in the surface, which is inaccessible. With calling
SDL_SetColors for each surface, the animations work. But I have a large
amount of small tiles, so the way “copy palette from surface, change the
palette, copy it back to the surface via SDL_SetColors” has a noticeable
effect on the frame rate.

Anyone an idea how to solve this?

Yes, read what Pierre had to say!On Mon, Dec 15, 2008 at 3:10 PM, Christian Meyer wrote:

On Sat, Dec 13, 2008 at 11:02 AM, Pierre Phaneuf wrote:

If you change the physical palette (of which there’s just one), then
you’ll affect everything and you don’t need to redraw anything (if you
use a real paletted mode, it will just change colours, if not, SDL
will take care of emulating it for you).

What this means is: you need to make sure your display is actually in
8-bit palette mode, and then change the display palette, as opposed to
changing the palettes of the surfaces corresponding to your
images/animations. Individual surfaces can have palettes, as Pierre
pointed out, only to provide a means of blitting an 8-bit
palette-having surface to another surface, where the palette is used
to translate colors between the source and destination surface.

Here is what SDL_video.h has to say about the SDL_HWPALETTE flag which
you can pass to SDL_SetVideoMode()

  • If SDL_HWPALETTE is set in ‘flags’, the SDL library will guarantee
  • that the colors set by SDL_SetColors() will be the colors you get.
  • Otherwise, in 8-bit mode, SDL_SetColors() may not be able to set all
  • of the colors exactly the way they are requested, and you should look
  • at the video surface structure to determine the actual palette.
  • If SDL cannot guarantee that the colors you request can be set,
  • i.e. if the colormap is shared, then the video surface may be created
  • under emulation in system memory, overriding the SDL_HWSURFACE flag.

And here’s what it says about SDL_SetPalette()

/*

  • Sets a portion of the colormap for a given 8-bit surface.
  • ‘flags’ is one or both of:
  • SDL_LOGPAL – set logical palette, which controls how blits are mapped
  •            to/from the surface,
    
  • SDL_PHYSPAL – set physical palette, which controls how pixels look on
  •            the screen
    
  • Only screens have physical palettes. Separate change of physical/logical
  • palettes is only possible if the screen has SDL_HWPALETTE set.
  • The return value is 1 if all colours could be set as requested, and 0
  • otherwise.
  • SDL_SetColors() is equivalent to calling this function with
  • flags = (SDL_LOGPAL|SDL_PHYSPAL).
    

*/
extern DECLSPEC int SDLCALL SDL_SetPalette(SDL_Surface *surface, int flags,
SDL_Color *colors, int firstcolor,
int ncolors);

So to get the kind of highly efficiency palette-based animations that
you seek on the screen, you should probably add SDL_HWSURFACE |
SDL_FULLSCREEN | SDL_HWPALETTE to SDL_SetVideoMode(), and then use
SDL_SetPalette() with SDL_PHYSPAL in the flags argument.

Remember to share your work if you want!


http://codebad.com/

Den Mon, 15 Dec 2008 17:58:41 -0500
skrev “Donny Viszneki” <donny.viszneki at gmail.com>:> On Mon, Dec 15, 2008 at 3:10 PM, Christian Meyer wrote:

Anyone an idea how to solve this?

Yes, read what Pierre had to say!

Another option, if you can’t/won’t have an 8-bit screen for some
reason, is to just make a big surface with the same palette as the
tiles, and blit all the little tiles to that, remembering the offset
of each tile. (You could do this at startup, or when packaging, etc.)
Then you use the big surface as the source for all the tiles when
blitting, with different offsets for different tiles. Since it’s just
one surface there’s just one palette to change.

  • Gerry

I have a game which generates small animations by changing the palette
of the tiles. For performance reasons it would be optimal, if only one
palette has to be changed.

So, is it possible to use one palette structure in multiple surfaces?

Yes, in SDL 1.3 you can do:
SDL_SetSurfacePalette(surface, palette);

See ya!
-Sam Lantinga, Lead Software Engineer, Blizzard Entertainment