Pixel level access to a HW surface

Hi there,

I wrote this function to fade a surface, or a region inside a surface.
My problem is that in this function, I make pixel-level access to the
surface. If the surface is a Software surface, the functions runs really
fast, but if the surface is a Hardware surface, the function takes so
much time that I can only redraw 1-2 fps in a 640x480 surface… Is this
normal? Should I make a copy of the surface to a SW surface before
accesing it at pixel level?
Any suggestion will be wellcome!!
thanks you in advance!

I include here the source code of that function (the important part of
the function are the two nested FORs at the end of it):

void surface_fader(SDL_Surface *surface,float r_factor,float
g_factor,float b_factor,SDL_Rect *r)
{
SDL_Rect r2;
int i,x,y,offs;
Uint8 rtable[256],gtable[256],btable[256];
Uint8 *pixels;

if (r==0) {
    r2.x=0;
    r2.y=0;
    r2.w=surface->w;
    r2.h=surface->h;
    r=&r2;
} /* if */

if (surface->format->BytesPerPixel!=4) return;

for(i=0;i<256;i++) {
    rtable[i]=(Uint8)(i*r_factor);
    gtable[i]=(Uint8)(i*g_factor);
    btable[i]=(Uint8)(i*b_factor);
} /* for */

SDL_LockSurface(surface);
pixels = (Uint8 *)(surface->pixels);

for(y=r->y;y<r->y+r->h && y<surface->h;y++) {
    for(x=r->x,offs=y*surface->pitch+r->x*4;x<r->x+r->w && 

xw;x++,offs+=4) {
pixels[offs+ROFFSET]=rtable[pixels[offs+ROFFSET]];
pixels[offs+GOFFSET]=gtable[pixels[offs+GOFFSET]];
pixels[offs+BOFFSET]=btable[pixels[offs+BOFFSET]];
} /* for /
} /
for */

SDL_UnlockSurface(surface);

} /* surface_fader */

The constants are defined in a header file, I include here the relevant
part of that header file:


#if SDL_BYTEORDER == SDL_BIG_ENDIAN
// PPC values:
#define AMASK 0xff000000
#define BMASK 0x000000ff
#define GMASK 0x0000ff00
#define RMASK 0x00ff0000
#define AOFFSET 0
#define BOFFSET 3
#define GOFFSET 2
#define ROFFSET 1

#else
// Intel values:
#define AMASK 0xff000000
#define BMASK 0x000000ff
#define GMASK 0x0000ff00
#define RMASK 0x00ff0000
#define AOFFSET 3
#define BOFFSET 0
#define GOFFSET 1
#define ROFFSET 2

#endif

Yes, normal, take a look at the faq,
http://www.libsdl.org/faq.php?action=listentries&category=2> ----- Original Message -----

From: santi.ontanon@terra.es (Santi Ontanon)
To:
Sent: Tuesday, July 22, 2003 1:59 PM
Subject: [SDL] pixel level access to a HW surface

Hi there,

I wrote this function to fade a surface, or a region inside a surface.
My problem is that in this function, I make pixel-level access to the
surface. If the surface is a Software surface, the functions runs really
fast, but if the surface is a Hardware surface, the function takes so
much time that I can only redraw 1-2 fps in a 640x480 surface… Is this
normal? Should I make a copy of the surface to a SW surface before
accesing it at pixel level?
Any suggestion will be wellcome!!
thanks you in advance!

I include here the source code of that function (the important part of
the function are the two nested FORs at the end of it):

void surface_fader(SDL_Surface *surface,float r_factor,float
g_factor,float b_factor,SDL_Rect *r)
{
SDL_Rect r2;
int i,x,y,offs;
Uint8 rtable[256],gtable[256],btable[256];
Uint8 *pixels;

if (r==0) {
    r2.x=0;
    r2.y=0;
    r2.w=surface->w;
    r2.h=surface->h;
    r=&r2;
} /* if */

if (surface->format->BytesPerPixel!=4) return;

for(i=0;i<256;i++) {
    rtable[i]=(Uint8)(i*r_factor);
    gtable[i]=(Uint8)(i*g_factor);
    btable[i]=(Uint8)(i*b_factor);
} /* for */

SDL_LockSurface(surface);
pixels = (Uint8 *)(surface->pixels);

for(y=r->y;y<r->y+r->h && y<surface->h;y++) {
    for(x=r->x,offs=y*surface->pitch+r->x*4;x<r->x+r->w &&

xw;x++,offs+=4) {
pixels[offs+ROFFSET]=rtable[pixels[offs+ROFFSET]];
pixels[offs+GOFFSET]=gtable[pixels[offs+GOFFSET]];
pixels[offs+BOFFSET]=btable[pixels[offs+BOFFSET]];
} /* for /
} /
for */

SDL_UnlockSurface(surface);

} /* surface_fader */

The constants are defined in a header file, I include here the relevant
part of that header file:


#if SDL_BYTEORDER == SDL_BIG_ENDIAN
// PPC values:
#define AMASK 0xff000000
#define BMASK 0x000000ff
#define GMASK 0x0000ff00
#define RMASK 0x00ff0000
#define AOFFSET 0
#define BOFFSET 3
#define GOFFSET 2
#define ROFFSET 1

#else
// Intel values:
#define AMASK 0xff000000
#define BMASK 0x000000ff
#define GMASK 0x0000ff00
#define RMASK 0x00ff0000
#define AOFFSET 3
#define BOFFSET 0
#define GOFFSET 1
#define ROFFSET 2

#endif


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

Santi Onta??n wrote:

Hi there,

I wrote this function to fade a surface, or a region inside a surface.
My problem is that in this function, I make pixel-level access to the
surface. If the surface is a Software surface, the functions runs
really fast, but if the surface is a Hardware surface, the function
takes so much time that I can only redraw 1-2 fps in a 640x480
surface… Is this normal? Should I make a copy of the surface to a SW
surface before accesing it at pixel level?
Any suggestion will be wellcome!!
thanks you in advance!

I include here the source code of that function (the important part of
the function are the two nested FORs at the end of it):

Yes, this is normal.
When you access an hardware surface you are going through the graphic bus,
and that is a VERY slow operation if you are accessing pixel by pixel.

The best soluction to fade a surface is to use alpha-blending.

Let’s say that you want to do a ‘fade to black’. Then create a black
surface with
the same dimension of your target surface. Start blitting the surface fully
transparent, and decrease the transparency between blits until you reach 0.

This way you will fade to black much quicker.

You could use this soluction for other types of fading.–
Paulo Pinto

Paulo Pinto wrote:

Yes, this is normal.
When you access an hardware surface you are going through the graphic
bus,
and that is a VERY slow operation if you are accessing pixel by pixel.

The best soluction to fade a surface is to use alpha-blending.

Let’s say that you want to do a ‘fade to black’. Then create a black
surface with
the same dimension of your target surface. Start blitting the surface
fully
transparent, and decrease the transparency between blits until you
reach 0.

This way you will fade to black much quicker.

You could use this soluction for other types of fading.


Paulo Pinto

In fact I’ve just posted this function for simplicity, but I’ve 3
different functions that apply different pixel-level effects to
surfaces. I know that blending can be done with the alpha channel. But
the other effects can’t. So may be I will include a test at the
beginning of the function, and if the surface is a HW one, I will make a
SF copy of it, then pixel-level-access it, and then copy the result into
the HW sfc again.

thanks for the explanations!!