Changing alpha-masks

Hello everybody,

I encounter a problem with transparencies, using libSDL-1.2.9.

I want to alter the alpha-mask of a surface to change according to the position of another surface blitted on the first one.
Unfortunately I got no transparency, i.e. the colorkey is displayed as an opaque color.

some (pseudo)code to get the idea :

SDL_Surface *screen, *tmp, *cover_surface, *peep_hole;
SDL_Rect pos;

tmp = SDL_CreateRGBSurface(…);
cover_surface = SDL_DisplayFormatAlpha(tmp);
SDL_SetColorKey(cover_surface, SDL_SRCCOLORKEY, GREEN); /GREEN defined as SDL_MapRGB(…) - macro/
SDL_FreeSurface(tmp);

peep_hole = get_circle(rad, GREEN); /surface with a GREEN circle and transparent rest, formatted same way as display/

while(!abortion_criterion){

  /*draw covering surface with something to peep through*/
  SDL_FillRect(cover_surface, NULL, BLACK); 
  pos.x += x_increment;
  pos.y += y_increment;
  SDL_BlitSurface(peep_hole, NULL, cover_surface, &pos);

 /*draw something to peep at and cover it*/   
 SDL_BlitSurface(some_image, NULL, screen, NULL);
 SDL_BlitSurface(cover_surface, NULL, screen, NULL);
 ....
 wait_for_some_time();

}

So this code results in a green circle moving on a black surface =(.
Hopefully someone can help me with this …
Thanks,

Stefan Gulan______________________________________________________________

Verschicken Sie romantische, coole und witzige Bilder per SMS!
Jetzt bei WEB.DE FreeMail: http://f.web.de/?mc=021193

Stefan Gulan wrote:

I encounter a problem with transparencies, using libSDL-1.2.9.
I want to alter the alpha-mask of a surface to change according
to the position of another surface blitted on the first one.
Unfortunately I got no transparency, i.e. the colorkey is
displayed as an opaque color.

cover_surface = SDL_DisplayFormatAlpha(tmp);
SDL_SetColorKey(cover_surface, SDL_SRCCOLORKEY, GREEN); /GREEN defined
as SDL_MapRGB(…) - macro
/

I posted here about a bug in SDL 32bpp RGBA->RGB colorkey blits about a
month ago. I am guessing that your ‘screen’ surface is 32bpp RGB, so see if
it works when ‘screen’ is 16bpp.

But in your case, and in general, you do not need an alpha surface to do
colorkey blits, so you can avoid the bug easily. Make your ‘cover_surface’–
cover_surface = SDL_DisplayFormat(tmp);
and your troubles just might go away.

Also, make sure your GREEN does not go through a 32bpp->16bpp->32bpp
transformation when you are creating your peep_hole and blitting it to
cover_surface, since depending on SDL version and platform, it may not come
out equal to cover_surface colorkey. This will be apparent when your
’screen’ is 16bpp, i.e. SDL_DisplayFormatAlpha() always returns a 32bpp
surface, and if your screen is 16bpp, your GREEN will go through above
32->16->32 xform, assuming, of course, that GREEN ==
SDL_MapRGB(cover_surface->format, 0, 255, 0).

If GREEN == SDL_MapRGB(screen, 0, 255, 0), and screen is 16bpp (and so
peep_hole is 16bpp as well), then your code is simply wrong, because the
green value must be different for peep_hole and cover_surface.

-Alex.

But in your case, and in general, you do not need an alpha surface to do
colorkey blits, so you can avoid the bug easily. Make your ‘cover_surface’

cover_surface = SDL_DisplayFormat(tmp);
and your troubles just might go away.

Yes, they did - however this only works when i’m using ‘normal’ SDL - as opposed to
glSDL, which i want to use for performance issues. The latter produces 32-bit surfaces with alpha
anyway (i think), so the problem might be similar.

Thank you a lot,

Stefan______________________________________________________________

Verschicken Sie romantische, coole und witzige Bilder per SMS!
Jetzt bei WEB.DE FreeMail: http://f.web.de/?mc=021193

Stefan Gulan wrote:

Make your 'cover_surface’
cover_surface = SDL_DisplayFormat(tmp); and your troubles
just might go away.

Yes, they did - however this only works when i’m using 'normal’
SDL - as opposed to glSDL, which i want to use for performance
issues. The latter produces 32-bit surfaces with alpha anyway
(i think), so the problem might be similar.

Keep in mind that SDL_DisplayFormat() will return a 16bpp surface if your
SDL video surface is 16bpp, while SDL_DisplayFormatAlpha() will always
return a 32bpp surface (correct me if I am wrong). The fact that changing to
cover_surface = SDL_DisplayFormat(tmp);
fixed the problem might still mean that your GREEN constant is wrong for one
of the surfaces, assuming that you are running in 16bpp mode. You should
never use the same GREEN for two surfaces that may have different formats
(and they will have different formats, technically, if one has alpha and the
other does not).

There is a reliable way to avoid the bug I mentioned even with alpha
surfaces, but it’s tricky and greatly depends on whether or not both of your
peep_hole and cover_surface have an alpha channel.

-Alex.

So SDL_DisplayFormatAlpha() doesn’t give the alpha-mask/shift of the dislplay surface
but the format of the display surf. plus an alpha-mask ?

You should never use the same GREEN for two surfaces that may have different formats

Probably that’s about what I did - although I don’t quite understand, where the surface formats differ,
since the surfaces were both created a la

tmp =  SDL_CreateRGBSurface(SDL_HWSURFACE, screen->w, screen->h,
    screen->format->BitsPerPixel, 
    screen->format->Rmask, 
    screen->format->Gmask,
    screen->format->Bmask,
    screen->format->Amask);

now tmp->format should be about the same as screen->format, or so i thought. Then I did

SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, GREEN);
cover_surface = SDL_DisplayFormat(tmp); /*like you said, without alpha*/

which gave expected results with SDL, but not glSDL, while

cover_surface = SDL_DisplayFormat(tmp);
SDL_SetColorKey(cover_surface, SDL_SRCCOLORKEY, GREEN);

gave expected results with both.

Thanks again,

Stefan______________________________________________________________

Verschicken Sie romantische, coole und witzige Bilder per SMS!
Jetzt bei WEB.DE FreeMail: http://f.web.de/?mc=021193

So SDL_DisplayFormatAlpha() doesn’t give the alpha-mask/shift of the dislplay surface
but the format of the display surf. plus an alpha-mask ?

Correct.

You should never use the same GREEN for two surfaces that may have different formats

Probably that’s about what I did - although I don’t quite understand, where the surface formats differ,
since the surfaces were both created a la

tmp = SDL_CreateRGBSurface(SDL_HWSURFACE, screen->w, screen->h,
screen->format->BitsPerPixel,
screen->format->Rmask,
screen->format->Gmask,
screen->format->Bmask,
screen->format->Amask);

now tmp->format should be about the same as screen->format, or so i thought.

At this point, they are the same. However, as you say, “then you did…”

SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, GREEN);
cover_surface = SDL_DisplayFormat(tmp); /like you said, without alpha/

Now you set the tmp colorkey to the appropriate value for the tmp
surface, but then changed the format of the surface without changing
the colorkey. This only works when SDL_DisplayFormat didn’t actually
change anything.

which gave expected results with SDL, but not glSDL, while

cover_surface = SDL_DisplayFormat(tmp);
SDL_SetColorKey(cover_surface, SDL_SRCCOLORKEY, GREEN);

Here you’re setting the colorkey after changing the format, which works.

gave expected results with both.

Thanks again,

Stefan

– JoshOn 12/7/05, Stefan Gulan <stefan.gulan at web.de> wrote:

Stefan Gulan wrote:

So SDL_DisplayFormatAlpha() doesn’t give the alpha-mask/shift of
the dislplay surface but the format of the display surf. plus
an alpha-mask ?

Neither, actually. SDL_DisplayFormatAlpha() does this -->

  • This function takes a surface and copies it to a new surface of the
  • pixel format and colors of the video framebuffer (if possible),
  • suitable for fast alpha blitting onto the display surface.

That “if possible” makes the difference. In reality, it is only "possible"
when the video framebuffer is in 24bpp or 32bpp mode, or at least, that is
the current implementation. Currently, the returned surface is always 32bpp,
and the reason for such is suitability “for fast alpha blitting onto the
display surface”, because there are no other fast blitters present.
SDL_DisplayFormatAlpha() tries to arrange the RGB channels in the same order
as the display surface has them to make blits faster.

Unfortunately, I do not know a whole lot about glSDL to help you otherwise.

So SDL_DisplayFormatAlpha() doesn’t give the alpha-mask/shift of the
dislplay surface but the format of the display surf. plus an alpha-mask
?

Joshua Oreman wrote:

Correct.

Ahh, I misunderstood the question. Everything I said about it holds plus
Joshua is correct -->

  • The new surface will always have an alpha channel.

No matter whether your display surface has an alpha channel or not, the one
returned by SDL_DisplayFormatAlpha() will always have an alpha channel.

-Alex.On 12/7/05, Stefan Gulan <stefan.gulan at web.de> wrote: