Per-surface alpha and hardware surfaces?

Here is a simple and short little Win32 program that loads an 800 x 600 background image and draws another image on top (movable using the mouse.) Then I use SetAlpha on the surface that I move with the mouse to fade it in and out.

My question is: Is per-surface alpha supposed to work when using hardware surfaces? (or maybe it is related to double-buffering? - not sure.) Why doesn’t the dSurface show? Yes I could convert all of my surfaces to per-alpha surfaces (and that works fine) but I’d rather not have to go that far.

The problem is that the call to: SDL_SetAlpha(dSurface, SDL_SRCALPHA, alpha); makes it so that the 2nd image (dSurface) doesn’t show. When this line is removed, everything is fine.

#include “sdl.h”
#include “sdl_image.h”

SDL_Surface* mainSurface;
SDL_Event event;

int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32,
SDL_SWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF);

SDL_Surface* backSurface1 = IMG_Load(“back.png”);// load an 800 x 600 image
SDL_Surface* backSurface = SDL_DisplayFormat(backSurface1);
SDL_FreeSurface(backSurface1);

/ / load a 300 x270 image. The transparent color is RGB 255, 0, 221
SDL_Surface* dSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dSurface = SDL_DisplayFormat(dSurface1);
SDL_FreeSurface(dSurface1);

SDL_SetColorKey(dSurface, SDL_SRCCOLORKEY,
SDL_MapRGB(mainSurface->format, 255, 0, 221));

int alpha = 0;
int alphaAdjust = 2;
SDL_Rect rect;
rect.x = 0;
rect.y = 100;
rect.w = 300;
rect.h = 270;

while (true)
{
SDL_PollEvent(&event);
if (event.type == SDL_KEYDOWN)
break;
if (event.type == SDL_MOUSEMOTION)
{
rect.x = event.motion.x;
rect.y = event.motion.y;
if (rect.x < 0) rect.x = 0;
if (rect.y < 0) rect.y = 0;
if (rect.x > 500) rect.x = 500;
if (rect.y > 330) rect.y = 330;
}

    // blit the background to the screen surface and then update the screen
    SDL_FillRect(mainSurface, NULL, SDL_MapRGB(mainSurface->format, 0, 0, 0));  
    SDL_BlitSurface(backSurface, NULL, mainSurface, NULL);
    SDL_SetAlpha(dSurface, SDL_SRCALPHA, alpha); 
    SDL_BlitSurface(dSurface, NULL, mainSurface, &rect);
    SDL_UpdateRect(mainSurface, 0, 0, mainSurface->w, mainSurface->h); 
    SDL_Flip(mainSurface); 

    alpha += alphaAdjust;
    if (alpha < 0) 
    {
         alpha = 0;
         alphaAdjust = 2;
    }
    if (alpha > 255) 
    {
         alpha = 255;
         alphaAdjust = -2;
    }
}

SDL_FreeSurface(mainSurface);
SDL_FreeSurface(backSurface);
SDL_Quit();
return(0);

}

Thanks,
– Warren Schwader

The basic rule of thumb is… don’t use alpha and 2D hardware surfaces.
With almost all of the current drivers, the alpha blending has to be done
in software, which means that each pixel needs to be read over the bus,
modified, and written back out over the bus. This is the slowest operation
you can do. :slight_smile:

You’ll get better results by either using OpenGL or by using software surfaces.

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

Here is a simple and short little Win32 program that loads an 800 x 600
background image and draws another image on top (movable using the mouse.)
Then I use SetAlpha on the surface that I move with the mouse to fade it in
and out.

My question is: Is per-surface alpha supposed to work when using hardware
surfaces? (or maybe it is related to double-buffering? - not sure.) Why
doesn’t the dSurface show? Yes I could convert all of my surfaces to
per-alpha surfaces (and that works fine) but I’d rather not have to go that
far.

The problem is that the call to: SDL_SetAlpha(dSurface, SDL_SRCALPHA,
alpha); makes it so that the 2nd image (dSurface) doesn’t show. When this
line is removed, everything is fine.

I don’t think you can use color keying and alpha transparency at the same
time. You’ve got to pick one or the other, as far as I know.

-Sean RidenourOn Sunday 14 December 2003 7:22 pm, Warren Schwader wrote:

#include “sdl.h”
#include “sdl_image.h”

SDL_Surface* mainSurface;
SDL_Event event;

int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32,
SDL_SWSURFACE | SDL_FULLSCREEN | SDL_DOUBLEBUF);

SDL_Surface* backSurface1 = IMG_Load(“back.png”);// load an 800 x 600
image SDL_Surface* backSurface = SDL_DisplayFormat(backSurface1);
SDL_FreeSurface(backSurface1);

/ / load a 300 x270 image. The transparent color is RGB 255, 0, 221
SDL_Surface* dSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dSurface = SDL_DisplayFormat(dSurface1);
SDL_FreeSurface(dSurface1);

SDL_SetColorKey(dSurface, SDL_SRCCOLORKEY,
SDL_MapRGB(mainSurface->format, 255, 0, 221));

int alpha = 0;
int alphaAdjust = 2;
SDL_Rect rect;
rect.x = 0;
rect.y = 100;
rect.w = 300;
rect.h = 270;

while (true)
{
SDL_PollEvent(&event);
if (event.type == SDL_KEYDOWN)
break;
if (event.type == SDL_MOUSEMOTION)
{
rect.x = event.motion.x;
rect.y = event.motion.y;
if (rect.x < 0) rect.x = 0;
if (rect.y < 0) rect.y = 0;
if (rect.x > 500) rect.x = 500;
if (rect.y > 330) rect.y = 330;
}

    // blit the background to the screen surface and then update the

screen SDL_FillRect(mainSurface, NULL, SDL_MapRGB(mainSurface->format, 0,
0, 0)); SDL_BlitSurface(backSurface, NULL, mainSurface, NULL);
SDL_SetAlpha(dSurface, SDL_SRCALPHA, alpha);
SDL_BlitSurface(dSurface, NULL, mainSurface, &rect);
SDL_UpdateRect(mainSurface, 0, 0, mainSurface->w, mainSurface->h);
SDL_Flip(mainSurface);

    alpha += alphaAdjust;
    if (alpha < 0)
    {
         alpha = 0;
         alphaAdjust = 2;
    }
    if (alpha > 255)
    {
         alpha = 255;
         alphaAdjust = -2;
    }
}

SDL_FreeSurface(mainSurface);
SDL_FreeSurface(backSurface);
SDL_Quit();
return(0);

}

Thanks,
– Warren Schwader

I’m pretty sure you can combine colorkeying and alpha, at least it’s
possible on my system (Mac OSX 10.3.1, SDL 1.2.6)

I have simplified the code to be simpler and more readable. The image
used is available from http://digital-10k.com/temp/dialogimage.png
It seems that for some systems, this code does not display an image if
the SDL_SetAlpha call isn’t removed. Does this ring a bell with anyone
as to why?

#include “sdl.h”
#include “sdl_image.h”

int main(int argc, char* argv[])
{
SDL_Surface *mainSurface;
SDL_Event event;
int alpha = 0;
SDL_Surface *foreground, *temp;

 SDL_Init(SDL_INIT_EVERYTHING);
 mainSurface = SDL_SetVideoMode(800, 600, 16, SDL_HWSURFACE | 

SDL_FULLSCREEN | SDL_DOUBLEBUF);

 temp = IMG_Load("dialogimage.png");
 foreground = SDL_DisplayFormat(temp);
 SDL_FreeSurface(temp);

 SDL_SetColorKey(foreground, SDL_SRCCOLORKEY, 

SDL_MapRGB(mainSurface->format, 255, 0, 221));

 while (1){
     while(SDL_PollEvent(&event)){ if (event.type == SDL_KEYDOWN){ 

SDL_Quit(); return(0); } }

     SDL_FillRect(mainSurface, NULL, SDL_MapRGB(mainSurface->format, 

0,0,0));
//when the following line is uncommented, no image displays
SDL_SetAlpha(foreground, SDL_SRCALPHA, alpha);
SDL_BlitSurface(foreground, NULL, mainSurface, NULL);

     SDL_Flip(mainSurface);

     alpha += 2;
     alpha %= 255;
 }

}On Dec 15, 2003, at 7:58 PM, Sean Ridenour wrote:

I don’t think you can use color keying and alpha transparency at the
same
time. You’ve got to pick one or the other, as far as I know.
-Sean Ridenour

Sam’s reply in this thread gave an indication, although it didn’t really
spell out as to why this particular example was failing.
It seems that no matter how slow the alpha blitting takes that the image
should still show and you get a crummy framerate. I moved the blits in
front of the animation loop so that they are only blitted to each buffer
once and the image was now visible.
Anyway, I guess I will try another approach. I am going to be preparing a
SW surface using dirty rects and alpha and then blitting that opaque SW
buffer to the screen (hopefully only updating the screen’s dirty rects) and
then hope that things are fast enough.

Sean, yes you definitely can use Color Keying and per-surface alpha.

Thanks for helping John and Sam
–Warren Schwader> ----- Original Message -----

From: phip@spymac.com (John Philip)
To:
Sent: Monday, December 15, 2003 5:35 PM
Subject: Re: [SDL] per-surface alpha and hardware surfaces?

On Dec 15, 2003, at 7:58 PM, Sean Ridenour wrote:

I don’t think you can use color keying and alpha transparency at the
same
time. You’ve got to pick one or the other, as far as I know.
-Sean Ridenour

I’m pretty sure you can combine colorkeying and alpha, at least it’s
possible on my system (Mac OSX 10.3.1, SDL 1.2.6)

I have simplified the code to be simpler and more readable. The image
used is available from http://digital-10k.com/temp/dialogimage.png
It seems that for some systems, this code does not display an image if
the SDL_SetAlpha call isn’t removed. Does this ring a bell with anyone
as to why?

#include “sdl.h”
#include “sdl_image.h”

int main(int argc, char* argv[])
{
SDL_Surface *mainSurface;
SDL_Event event;
int alpha = 0;
SDL_Surface *foreground, *temp;

 SDL_Init(SDL_INIT_EVERYTHING);
 mainSurface = SDL_SetVideoMode(800, 600, 16, SDL_HWSURFACE |

SDL_FULLSCREEN | SDL_DOUBLEBUF);

 temp = IMG_Load("dialogimage.png");
 foreground = SDL_DisplayFormat(temp);
 SDL_FreeSurface(temp);

 SDL_SetColorKey(foreground, SDL_SRCCOLORKEY,

SDL_MapRGB(mainSurface->format, 255, 0, 221));

 while (1){
     while(SDL_PollEvent(&event)){ if (event.type == SDL_KEYDOWN){

SDL_Quit(); return(0); } }

     SDL_FillRect(mainSurface, NULL, SDL_MapRGB(mainSurface->format,

0,0,0));
//when the following line is uncommented, no image displays
SDL_SetAlpha(foreground, SDL_SRCALPHA, alpha);
SDL_BlitSurface(foreground, NULL, mainSurface, NULL);

     SDL_Flip(mainSurface);

     alpha += 2;
     alpha %= 255;
 }

}


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

Warren Schwader wrote:

Here is a simple and short little Win32 program that loads an 800 x
600 background image and draws another image on top (movable using
the mouse.) Then I use SetAlpha on the surface that I move with the
mouse to fade it in and out.

If you want a surface to support per-surface alpha, call SDL_SetAlpha before
you call SDL_DisplayFormat.

My question is: Is per-surface alpha supposed to work when using
hardware surfaces?

As a rule, no alpha of any kind is hardware accelerated under SDL.–
Rainer Deyke - rainerd at eldwood.com - http://eldwood.com