Pixels getting set to NULL

After an SDL_BlitSurface the pixels pointer gets set to 0 (or NULL) making the future use of the surface to cause an exception. Under what circumstances will SDL_BlitSurface destroy a surface’s pointer to its pixels?

I am building a Dialog. In order to make things efficient, I blit all of the Dialog components to the Dialog’s surface once (and then only again if they change state) so that the dialog can be blitted to the screen as a single image.

I can’t post a lot of code since it is built into many parts of the program, but here are various snipets:

// I create the Dialog’s surface this way:
SDL_PixelFormat* f = screenSurface->format;
SDL_Surface* aSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 300, 270,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);

// then I blit a background image and various Dialog Items to “aSurface”.
// Each of these Dialog Items has its own ColorKey Set like this:
bool SetColorKey(SDL_Surface surface, Color& color)
{
Uint32 col = SDL_MapRGB(surface->format, color.R(), color.G(), color.B());
return (SDL_SetColorKey(surface, SDL_SRCCOLORKEY | SDL_RLEACCEL, col) == 0);
}

Next I call UpdateRect() on the dialog surface
Then I set the ColorKey for the Dialog’s surface using the same function above
(so that dialogs can be odd shapes.)

The first time I go to Blit the surface, it’s pixels valiable points to data
then after calling the following function, pixels in aSurface is set to 0 (or NULL)

SDL_BlitSurface(aSurface, rectSrc, screenSurface, rectDst);

Anyone know the reason?
Thanks,
Warren Schwader

hey Warren, im going off of really really vague memory so i hope someone else steps in or it sparks someone elses memory.

take what i say with an implied “i think” before each sentence (;

if you have a hardware surface, you have to lock it each frame, draw to it then unlock it so it can be drawn to the screen. part of this locking/unlocking is that pixels is set to null til you lock the surface, then pixels points to your region of memory. when you unlock it gets set back to null. if you dont un lock, your program will freeze up because virtualy everything else on your entire computer will be waiting for the video memory to be unlocked before proceeding.

thats once way.

another way would be if it was a full screen app and lost focus. when it loses focus, all the surfaces are destroyed so you have to detect when this happens and do nothing (wait) til you detect that you have regained focus. then you have to remake your surfaces (reload your art and crap…phooey).

thats the other way i know of, there might be more.

hope im not leading you astray too much :P----- Original Message -----
From: Warren Schwader
To: sdl at libsdl.org
Sent: Saturday, December 06, 2003 9:20 PM
Subject: [SDL] pixels getting set to NULL

After an SDL_BlitSurface the pixels pointer gets set to 0 (or NULL) making the future use of the surface to cause an exception. Under what circumstances will SDL_BlitSurface destroy a surface’s pointer to its pixels?

I am building a Dialog. In order to make things efficient, I blit all of the Dialog components to the Dialog’s surface once (and then only again if they change state) so that the dialog can be blitted to the screen as a single image.

I can’t post a lot of code since it is built into many parts of the program, but here are various snipets:

// I create the Dialog’s surface this way:
SDL_PixelFormat* f = screenSurface->format;
SDL_Surface* aSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 300, 270,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);

// then I blit a background image and various Dialog Items to “aSurface”.
// Each of these Dialog Items has its own ColorKey Set like this:
bool SetColorKey(SDL_Surface surface, Color& color)
{
Uint32 col = SDL_MapRGB(surface->format, color.R(), color.G(), color.B());
return (SDL_SetColorKey(surface, SDL_SRCCOLORKEY | SDL_RLEACCEL, col) == 0);
}

Next I call UpdateRect() on the dialog surface
Then I set the ColorKey for the Dialog’s surface using the same function above
(so that dialogs can be odd shapes.)

The first time I go to Blit the surface, it’s pixels valiable points to data
then after calling the following function, pixels in aSurface is set to 0 (or NULL)

SDL_BlitSurface(aSurface, rectSrc, screenSurface, rectDst);

Anyone know the reason?
Thanks,
Warren Schwader

Hi Alan, thanks for the reply. What you say is likely true, but in my case I amusing only software surfaces. I should have stated that. I should have also stated that I am using per surface alpha too. I can try to Lock the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the dialog’s surface then everything works OK but then I’d be stuck with square dialogs. Another interesting thing is when I change a dialog item on my non-square dialog, it makes the color keyed pixels appear in a color other than what would be there if the image wasn’t color keyed. Strange.

–Warren Schwader> ----- Original Message -----

From: Alan Wolfe
To: sdl at libsdl.org
Sent: Saturday, December 06, 2003 9:40 PM
Subject: Re: [SDL] pixels getting set to NULL

hey Warren, im going off of really really vague memory so i hope someone else steps in or it sparks someone elses memory.

take what i say with an implied “i think” before each sentence (;

if you have a hardware surface, you have to lock it each frame, draw to it then unlock it so it can be drawn to the screen. part of this locking/unlocking is that pixels is set to null til you lock the surface, then pixels points to your region of memory. when you unlock it gets set back to null. if you dont un lock, your program will freeze up because virtualy everything else on your entire computer will be waiting for the video memory to be unlocked before proceeding.

thats once way.

another way would be if it was a full screen app and lost focus. when it loses focus, all the surfaces are destroyed so you have to detect when this happens and do nothing (wait) til you detect that you have regained focus. then you have to remake your surfaces (reload your art and crap…phooey).

thats the other way i know of, there might be more.

hope im not leading you astray too much :stuck_out_tongue:
----- Original Message -----
From: Warren Schwader
To: sdl at libsdl.org
Sent: Saturday, December 06, 2003 9:20 PM
Subject: [SDL] pixels getting set to NULL

After an SDL_BlitSurface the pixels pointer gets set to 0 (or NULL) making the future use of the surface to cause an exception.  Under what circumstances will SDL_BlitSurface destroy a surface's pointer to its pixels?

I am building a Dialog.  In order to make things efficient, I blit all of the Dialog components to the Dialog's surface once (and then only again if they change state) so that the dialog can be blitted to the screen as a single image.

I can't post a lot of code since it is built into many parts of the program, but here are various snipets:

// I create the Dialog's surface this way:
SDL_PixelFormat* f  = screenSurface->format;
SDL_Surface* aSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 300, 270, 
                                            f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);

// then I blit a background image and various Dialog Items to "aSurface".  
// Each of these Dialog Items has its own ColorKey Set like this:
bool SetColorKey(SDL_Surface surface, Color& color) 
{
     Uint32 col = SDL_MapRGB(surface->format, color.R(), color.G(), color.B());
     return (SDL_SetColorKey(surface, SDL_SRCCOLORKEY | SDL_RLEACCEL, col) == 0);
}

Next I call UpdateRect() on the dialog surface
Then I set the ColorKey for the Dialog's surface using the same function above
     (so that dialogs can be odd shapes.)

The first time I go to Blit the surface, it's pixels valiable points to data
then after calling the following function, pixels in aSurface is set to 0 (or NULL)

SDL_BlitSurface(aSurface, rectSrc, screenSurface, rectDst);


Anyone know the reason?
Thanks,
Warren Schwader

Hi Alan, thanks for the reply. What you say is likely true, but in my case I amusing only software surfaces. I should have stated that. I should have also stated that I am using per surface alpha too. I can try to Lock the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the dialog’s surface then everything works OK but then I’d be stuck with square dialogs. Another interesting thing is when I change a dialog item on my non-square dialog, it makes the color keyed pixels appear in a color other than what would be there if the image wasn’t color keyed. Strange.

You always need to use the SDL_MUSTLOCK() macro to see whether you need to
lock the surface before using it. If the pixels are NULL, that’s a good clue. :slight_smile:

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

after you create the surface have you checked the flags to make sure you got sw and not hw?----- Original Message -----
From: Warren Schwader
To: sdl at libsdl.org
Sent: Saturday, December 06, 2003 10:12 PM
Subject: Re: [SDL] pixels getting set to NULL

Hi Alan, thanks for the reply. What you say is likely true, but in my case I amusing only software surfaces. I should have stated that. I should have also stated that I am using per surface alpha too. I can try to Lock the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the dialog’s surface then everything works OK but then I’d be stuck with square dialogs. Another interesting thing is when I change a dialog item on my non-square dialog, it makes the color keyed pixels appear in a color other than what would be there if the image wasn’t color keyed. Strange.

–Warren Schwader

----- Original Message -----
From: Alan Wolfe
To: sdl at libsdl.org
Sent: Saturday, December 06, 2003 9:40 PM
Subject: Re: [SDL] pixels getting set to NULL

hey Warren, im going off of really really vague memory so i hope someone else steps in or it sparks someone elses memory.

take what i say with an implied "i think" before each sentence (;

if you have a hardware surface, you have to lock it each frame, draw to it then unlock it so it can be drawn to the screen.  part of this locking/unlocking is that pixels is set to null til you lock the surface, then pixels points to your region of memory.  when you unlock it gets set back to null.  if you dont un lock, your program will freeze up because virtualy everything else on your entire computer will be waiting for the video memory to be unlocked before proceeding.

thats once way.

another way would be if it was a full screen app and lost focus.  when it loses focus, all the surfaces are destroyed so you have to detect when this happens and do nothing (wait) til you detect that you have regained focus.  then you have to remake your surfaces (reload your art and crap...phooey).

thats the other way i know of, there might be more.

hope im not leading you astray too much :P
  ----- Original Message ----- 
  From: Warren Schwader 
  To: sdl at libsdl.org 
  Sent: Saturday, December 06, 2003 9:20 PM
  Subject: [SDL] pixels getting set to NULL


  After an SDL_BlitSurface the pixels pointer gets set to 0 (or NULL) making the future use of the surface to cause an exception.  Under what circumstances will SDL_BlitSurface destroy a surface's pointer to its pixels?

  I am building a Dialog.  In order to make things efficient, I blit all of the Dialog components to the Dialog's surface once (and then only again if they change state) so that the dialog can be blitted to the screen as a single image.

  I can't post a lot of code since it is built into many parts of the program, but here are various snipets:

  // I create the Dialog's surface this way:
  SDL_PixelFormat* f  = screenSurface->format;
  SDL_Surface* aSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, 300, 270, 
                                              f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask, f->Amask);

  // then I blit a background image and various Dialog Items to "aSurface".  
  // Each of these Dialog Items has its own ColorKey Set like this:
  bool SetColorKey(SDL_Surface surface, Color& color) 
  {
       Uint32 col = SDL_MapRGB(surface->format, color.R(), color.G(), color.B());
       return (SDL_SetColorKey(surface, SDL_SRCCOLORKEY | SDL_RLEACCEL, col) == 0);
  }

  Next I call UpdateRect() on the dialog surface
  Then I set the ColorKey for the Dialog's surface using the same function above
       (so that dialogs can be odd shapes.)

  The first time I go to Blit the surface, it's pixels valiable points to data
  then after calling the following function, pixels in aSurface is set to 0 (or NULL)

  SDL_BlitSurface(aSurface, rectSrc, screenSurface, rectDst);


  Anyone know the reason?
  Thanks,
  Warren Schwader

Sam and Alan,

Despite the advice and possible reasons, I cannot seem to correct this
problem.
So I decided to write the most concise program that I could that
demonstrated the problem.
Can you give it the once over please and see if you can tell what I’m doing
wrong?
Here is the code (VC++5 Win2000) that produces it in a simple main function:

Please try these two things:
#1 run it as it is. An access violation occurs because dialogSurface’s
pixels
is set to 0 when trying to draw “doneImageSurface” the 2nd time
#2 change “amask” to “f->Amask” when creating “dialogSurface”
(SDL_CreateRGBSurface)
and run again. This time the pixels are fine but the color key of the
dialogSurface doesn’t work

//--------------------------------------------------------------------------------------------------
#include “sdl.h”
#include “sdl_image.h”
#include <memory.h>

SDL_Surface* mainSurface;
SDL_Event event;

int main(int argc, char* argv[])
{
// initialize and create the main surface
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);

// load a non-rectanglular image. The pixel at 0, 0 will become the
ColorKey
// my image was 300 wide by 270 tall.
// Make sure the transparent part of the image is not black so you can see
it when drawn.
SDL_Surface* dialogImageSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dialogImageSurface = SDL_DisplayFormat(dialogImageSurface1);
SDL_FreeSurface(dialogImageSurface1);

// load a button image to display on the dialog surface.
// The pixel at 0, 0 will become the ColorKey for the button
SDL_Surface* doneImageSurface1 = IMG_Load(“done.png”);
SDL_Surface* doneImageSurface = SDL_DisplayFormat(doneImageSurface1);
SDL_FreeSurface(doneImageSurface1);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_LockSurface(doneImageSurface);
Uint32 doneColor = 0;
memcpy(&doneColor, (char*)doneImageSurface->pixels,
doneImageSurface->format->BytesPerPixel);
SDL_SetColorKey(doneImageSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL,
doneColor);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_UnlockSurface(doneImageSurface);

// create an RGB surface for the dialog
SDL_PixelFormat* f = mainSurface->format;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 amask = 0x000000ff;
#else
Uint32 amask = 0xff000000;
#endif
SDL_Surface* dialogSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
dialogImageSurface->w, dialogImageSurface->h,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask,
amask); // f->Amask);

// pre-draw the dialog once so it can be blitted faster later than if we
// blitted the dialog image and all the buttons and text every time it
needed repainting
SDL_BlitSurface(dialogImageSurface, NULL, dialogSurface, NULL);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

// reads the pixel at 0, 0 and use that color as the color key for the
dialogSurface
// so that we can have dialogs of non-rectanglular shape
if (SDL_MUSTLOCK(dialogSurface)) SDL_LockSurface(dialogSurface);
Uint32 color = 0;
memcpy(&color, (char*)dialogSurface->pixels,
dialogSurface->format->BytesPerPixel);
SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
if (SDL_MUSTLOCK(dialogSurface)) SDL_UnlockSurface(dialogSurface);

SDL_Rect rect;
rect.x = 100;
rect.y = 100;
rect.w = doneImageSurface->w;
rect.h = doneImageSurface->h;
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

// finally blit the dialog surface to the mainSurface
if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// next, assume the user moused over a dialog button so we want to draw the
button again
// onto the dialogSurface (not the mainSurface)
// THIS IS WHERE PIXELS IS SET TO 0 FOR dialogSurface
void* dialogPixels = dialogSurface->pixels; // pixels is 0 here
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect); // access
violation
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// wait for a command to close the app
while (true)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
}
SDL_Quit();
return(0);
}
//--------------------------------------------------------------------------

Thanks,
Warren Schwader

----- Original Message -----
From: slouken@devolution.com (Sam Lantinga)
To:
Sent: Sunday, December 07, 2003 11:03 AM
Subject: Re: [SDL] pixels getting set to NULL

Hi Alan, thanks for the reply. What you say is likely true, but in my
case I amusing only software surfaces. I should have stated that. I should
have also stated that I am using per surface alpha too. I can try to Lock
the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the
dialog’s surface then everything works OK but then I’d be stuck with square
dialogs. Another interesting thing is when I change a dialog item on my
non-square dialog, it makes the color keyed pixels appear in a color other
than what would be there if the image wasn’t color keyed. Strange.

You always need to use the SDL_MUSTLOCK() macro to see whether you need to
lock the surface before using it. If the pixels are NULL, that’s a good
clue. :slight_smile:

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


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

I should have also stated that I am using SDL 1.2.5 and SDL_image 1.2.3.
And I should have also freed the surfaces that I created before quitting but
didn’t.
–Warren Schwader> ----- Original Message -----

From: @Warren_Schwader (Warren Schwader)
To:
Sent: Tuesday, December 09, 2003 2:19 AM
Subject: Re: [SDL] pixels getting set to NULL

Sam and Alan,

Despite the advice and possible reasons, I cannot seem to correct this
problem.
So I decided to write the most concise program that I could that
demonstrated the problem.
Can you give it the once over please and see if you can tell what I’m
doing
wrong?
Here is the code (VC++5 Win2000) that produces it in a simple main
function:

Please try these two things:
#1 run it as it is. An access violation occurs because dialogSurface’s
pixels
is set to 0 when trying to draw “doneImageSurface” the 2nd time
#2 change “amask” to “f->Amask” when creating “dialogSurface”
(SDL_CreateRGBSurface)
and run again. This time the pixels are fine but the color key of
the
dialogSurface doesn’t work

//--------------------------------------------------------------------------


#include “sdl.h”
#include “sdl_image.h”
#include <memory.h>

SDL_Surface* mainSurface;
SDL_Event event;

int main(int argc, char* argv[])
{
// initialize and create the main surface
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);

// load a non-rectanglular image. The pixel at 0, 0 will become the
ColorKey
// my image was 300 wide by 270 tall.
// Make sure the transparent part of the image is not black so you can see
it when drawn.
SDL_Surface* dialogImageSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dialogImageSurface = SDL_DisplayFormat(dialogImageSurface1);
SDL_FreeSurface(dialogImageSurface1);

// load a button image to display on the dialog surface.
// The pixel at 0, 0 will become the ColorKey for the button
SDL_Surface* doneImageSurface1 = IMG_Load(“done.png”);
SDL_Surface* doneImageSurface = SDL_DisplayFormat(doneImageSurface1);
SDL_FreeSurface(doneImageSurface1);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_LockSurface(doneImageSurface);
Uint32 doneColor = 0;
memcpy(&doneColor, (char*)doneImageSurface->pixels,
doneImageSurface->format->BytesPerPixel);
SDL_SetColorKey(doneImageSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL,
doneColor);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_UnlockSurface(doneImageSurface);

// create an RGB surface for the dialog
SDL_PixelFormat* f = mainSurface->format;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 amask = 0x000000ff;
#else
Uint32 amask = 0xff000000;
#endif
SDL_Surface* dialogSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
dialogImageSurface->w, dialogImageSurface->h,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask,
amask); // f->Amask);

// pre-draw the dialog once so it can be blitted faster later than if we
// blitted the dialog image and all the buttons and text every time it
needed repainting
SDL_BlitSurface(dialogImageSurface, NULL, dialogSurface, NULL);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

// reads the pixel at 0, 0 and use that color as the color key for the
dialogSurface
// so that we can have dialogs of non-rectanglular shape
if (SDL_MUSTLOCK(dialogSurface)) SDL_LockSurface(dialogSurface);
Uint32 color = 0;
memcpy(&color, (char*)dialogSurface->pixels,
dialogSurface->format->BytesPerPixel);
SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
if (SDL_MUSTLOCK(dialogSurface)) SDL_UnlockSurface(dialogSurface);

SDL_Rect rect;
rect.x = 100;
rect.y = 100;
rect.w = doneImageSurface->w;
rect.h = doneImageSurface->h;
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

// finally blit the dialog surface to the mainSurface
if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// next, assume the user moused over a dialog button so we want to draw
the
button again
// onto the dialogSurface (not the mainSurface)
// THIS IS WHERE PIXELS IS SET TO 0 FOR dialogSurface
void* dialogPixels = dialogSurface->pixels; // pixels is 0 here
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect); // access
violation
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// wait for a command to close the app
while (true)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
}
SDL_Quit();
return(0);
}

//--------------------------------------------------------------------------


Thanks,
Warren Schwader

----- Original Message -----
From: “Sam Lantinga”
To:
Sent: Sunday, December 07, 2003 11:03 AM
Subject: Re: [SDL] pixels getting set to NULL

Hi Alan, thanks for the reply. What you say is likely true, but in my
case I amusing only software surfaces. I should have stated that. I
should
have also stated that I am using per surface alpha too. I can try to Lock
the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the
dialog’s surface then everything works OK but then I’d be stuck with
square
dialogs. Another interesting thing is when I change a dialog item on my
non-square dialog, it makes the color keyed pixels appear in a color other
than what would be there if the image wasn’t color keyed. Strange.

You always need to use the SDL_MUSTLOCK() macro to see whether you need
to

lock the surface before using it. If the pixels are NULL, that’s a good
clue. :slight_smile:

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


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


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

ok I understand now why the color key doesn’t get used when there is per
pixel alpha (my #2 item), but more imporant than that is still why the null
pointer when passing amask = 0 in SDL_CreateRGBSurface?
Note that I think the code should have used f->Amask for my #1 item. Sorry
for the confusion.
–Warren Schwader> ----- Original Message -----

From: @Warren_Schwader (Warren Schwader)
To:
Sent: Tuesday, December 09, 2003 2:19 AM
Subject: Re: [SDL] pixels getting set to NULL

Sam and Alan,

Despite the advice and possible reasons, I cannot seem to correct this
problem.
So I decided to write the most concise program that I could that
demonstrated the problem.
Can you give it the once over please and see if you can tell what I’m
doing
wrong?
Here is the code (VC++5 Win2000) that produces it in a simple main
function:

Please try these two things:
#1 run it as it is. An access violation occurs because dialogSurface’s
pixels
is set to 0 when trying to draw “doneImageSurface” the 2nd time
#2 change “amask” to “f->Amask” when creating “dialogSurface”
(SDL_CreateRGBSurface)
and run again. This time the pixels are fine but the color key of
the
dialogSurface doesn’t work

//--------------------------------------------------------------------------


#include “sdl.h”
#include “sdl_image.h”
#include <memory.h>

SDL_Surface* mainSurface;
SDL_Event event;

int main(int argc, char* argv[])
{
// initialize and create the main surface
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);

// load a non-rectanglular image. The pixel at 0, 0 will become the
ColorKey
// my image was 300 wide by 270 tall.
// Make sure the transparent part of the image is not black so you can see
it when drawn.
SDL_Surface* dialogImageSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dialogImageSurface = SDL_DisplayFormat(dialogImageSurface1);
SDL_FreeSurface(dialogImageSurface1);

// load a button image to display on the dialog surface.
// The pixel at 0, 0 will become the ColorKey for the button
SDL_Surface* doneImageSurface1 = IMG_Load(“done.png”);
SDL_Surface* doneImageSurface = SDL_DisplayFormat(doneImageSurface1);
SDL_FreeSurface(doneImageSurface1);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_LockSurface(doneImageSurface);
Uint32 doneColor = 0;
memcpy(&doneColor, (char*)doneImageSurface->pixels,
doneImageSurface->format->BytesPerPixel);
SDL_SetColorKey(doneImageSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL,
doneColor);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_UnlockSurface(doneImageSurface);

// create an RGB surface for the dialog
SDL_PixelFormat* f = mainSurface->format;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 amask = 0x000000ff;
#else
Uint32 amask = 0xff000000;
#endif
SDL_Surface* dialogSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
dialogImageSurface->w, dialogImageSurface->h,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask,
amask); // f->Amask);

// pre-draw the dialog once so it can be blitted faster later than if we
// blitted the dialog image and all the buttons and text every time it
needed repainting
SDL_BlitSurface(dialogImageSurface, NULL, dialogSurface, NULL);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

// reads the pixel at 0, 0 and use that color as the color key for the
dialogSurface
// so that we can have dialogs of non-rectanglular shape
if (SDL_MUSTLOCK(dialogSurface)) SDL_LockSurface(dialogSurface);
Uint32 color = 0;
memcpy(&color, (char*)dialogSurface->pixels,
dialogSurface->format->BytesPerPixel);
SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
if (SDL_MUSTLOCK(dialogSurface)) SDL_UnlockSurface(dialogSurface);

SDL_Rect rect;
rect.x = 100;
rect.y = 100;
rect.w = doneImageSurface->w;
rect.h = doneImageSurface->h;
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

// finally blit the dialog surface to the mainSurface
if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// next, assume the user moused over a dialog button so we want to draw
the
button again
// onto the dialogSurface (not the mainSurface)
// THIS IS WHERE PIXELS IS SET TO 0 FOR dialogSurface
void* dialogPixels = dialogSurface->pixels; // pixels is 0 here
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect); // access
violation
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w, dialogSurface->h);

if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// wait for a command to close the app
while (true)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
}
SDL_Quit();
return(0);
}

//--------------------------------------------------------------------------


Thanks,
Warren Schwader

----- Original Message -----
From: “Sam Lantinga”
To:
Sent: Sunday, December 07, 2003 11:03 AM
Subject: Re: [SDL] pixels getting set to NULL

Hi Alan, thanks for the reply. What you say is likely true, but in my
case I amusing only software surfaces. I should have stated that. I
should
have also stated that I am using per surface alpha too. I can try to Lock
the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the
dialog’s surface then everything works OK but then I’d be stuck with
square
dialogs. Another interesting thing is when I change a dialog item on my
non-square dialog, it makes the color keyed pixels appear in a color other
than what would be there if the image wasn’t color keyed. Strange.

You always need to use the SDL_MUSTLOCK() macro to see whether you need
to

lock the surface before using it. If the pixels are NULL, that’s a good
clue. :slight_smile:

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


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


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

OK, Sorry for the recent floods of emails, but for those interested I think
I fixed my problem,
If I use SDL_RLEACCEL when I create the doneImageSurface (one of the dialog
items) then I get the null pixels pointer after blitting the dialog surface
to the main surface. I can still use RLE on the dialog surface though which
is good.

I guess the only thing still that I need explained is why this is so?
–Warren Schwader> ----- Original Message -----

From: @Warren_Schwader (Warren Schwader)
To:
Sent: Tuesday, December 09, 2003 3:38 AM
Subject: Re: [SDL] pixels getting set to NULL

ok I understand now why the color key doesn’t get used when there is per
pixel alpha (my #2 item), but more imporant than that is still why the
null
pointer when passing amask = 0 in SDL_CreateRGBSurface?
Note that I think the code should have used f->Amask for my #1 item.
Sorry
for the confusion.
–Warren Schwader

----- Original Message -----
From: “Warren Schwader” <@Warren_Schwader>
To:
Sent: Tuesday, December 09, 2003 2:19 AM
Subject: Re: [SDL] pixels getting set to NULL

Sam and Alan,

Despite the advice and possible reasons, I cannot seem to correct this
problem.
So I decided to write the most concise program that I could that
demonstrated the problem.
Can you give it the once over please and see if you can tell what I’m
doing
wrong?
Here is the code (VC++5 Win2000) that produces it in a simple main
function:

Please try these two things:
#1 run it as it is. An access violation occurs because dialogSurface’s
pixels
is set to 0 when trying to draw “doneImageSurface” the 2nd time
#2 change “amask” to “f->Amask” when creating “dialogSurface”
(SDL_CreateRGBSurface)
and run again. This time the pixels are fine but the color key of
the
dialogSurface doesn’t work

//--------------------------------------------------------------------------


#include “sdl.h”
#include “sdl_image.h”
#include <memory.h>

SDL_Surface* mainSurface;
SDL_Event event;

int main(int argc, char* argv[])
{
// initialize and create the main surface
SDL_Init(SDL_INIT_EVERYTHING);
mainSurface = SDL_SetVideoMode(800, 600, 32, SDL_SWSURFACE);

// load a non-rectanglular image. The pixel at 0, 0 will become the
ColorKey
// my image was 300 wide by 270 tall.
// Make sure the transparent part of the image is not black so you can
see

it when drawn.
SDL_Surface* dialogImageSurface1 = IMG_Load(“dialogimage.png”);
SDL_Surface* dialogImageSurface =
SDL_DisplayFormat(dialogImageSurface1);

SDL_FreeSurface(dialogImageSurface1);

// load a button image to display on the dialog surface.
// The pixel at 0, 0 will become the ColorKey for the button
SDL_Surface* doneImageSurface1 = IMG_Load(“done.png”);
SDL_Surface* doneImageSurface = SDL_DisplayFormat(doneImageSurface1);
SDL_FreeSurface(doneImageSurface1);
if (SDL_MUSTLOCK(doneImageSurface)) SDL_LockSurface(doneImageSurface);
Uint32 doneColor = 0;
memcpy(&doneColor, (char*)doneImageSurface->pixels,
doneImageSurface->format->BytesPerPixel);
SDL_SetColorKey(doneImageSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL,
doneColor);
if (SDL_MUSTLOCK(doneImageSurface))
SDL_UnlockSurface(doneImageSurface);

// create an RGB surface for the dialog
SDL_PixelFormat* f = mainSurface->format;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
Uint32 amask = 0x000000ff;
#else
Uint32 amask = 0xff000000;
#endif
SDL_Surface* dialogSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,
dialogImageSurface->w, dialogImageSurface->h,
f->BitsPerPixel, f->Rmask, f->Gmask, f->Bmask,
amask); // f->Amask);

// pre-draw the dialog once so it can be blitted faster later than if we
// blitted the dialog image and all the buttons and text every time it
needed repainting
SDL_BlitSurface(dialogImageSurface, NULL, dialogSurface, NULL);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w,
dialogSurface->h);

// reads the pixel at 0, 0 and use that color as the color key for the
dialogSurface
// so that we can have dialogs of non-rectanglular shape
if (SDL_MUSTLOCK(dialogSurface)) SDL_LockSurface(dialogSurface);
Uint32 color = 0;
memcpy(&color, (char*)dialogSurface->pixels,
dialogSurface->format->BytesPerPixel);
SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY | SDL_RLEACCEL, color);
if (SDL_MUSTLOCK(dialogSurface)) SDL_UnlockSurface(dialogSurface);

SDL_Rect rect;
rect.x = 100;
rect.y = 100;
rect.w = doneImageSurface->w;
rect.h = doneImageSurface->h;
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect);
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w,
dialogSurface->h);

// finally blit the dialog surface to the mainSurface
if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// next, assume the user moused over a dialog button so we want to draw
the
button again
// onto the dialogSurface (not the mainSurface)
// THIS IS WHERE PIXELS IS SET TO 0 FOR dialogSurface
void* dialogPixels = dialogSurface->pixels; // pixels is 0 here
SDL_BlitSurface(doneImageSurface, NULL, dialogSurface, &rect); //
access

violation
SDL_UpdateRect(dialogSurface, 0, 0, dialogSurface->w,
dialogSurface->h);

if (SDL_MUSTLOCK(mainSurface)) SDL_LockSurface(mainSurface);
SDL_BlitSurface(dialogSurface, NULL, mainSurface, NULL);
SDL_UpdateRect(mainSurface, 0, 0, 800, 600);
if (SDL_MUSTLOCK(mainSurface)) SDL_UnlockSurface(mainSurface);

// wait for a command to close the app
while (true)
{
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
}
SDL_Quit();
return(0);
}

//--------------------------------------------------------------------------


Thanks,
Warren Schwader

----- Original Message -----
From: “Sam Lantinga”
To:
Sent: Sunday, December 07, 2003 11:03 AM
Subject: Re: [SDL] pixels getting set to NULL

Hi Alan, thanks for the reply. What you say is likely true, but in
my

case I amusing only software surfaces. I should have stated that. I
should
have also stated that I am using per surface alpha too. I can try to
Lock

the sw surface and see what effect it has.

The interesting thing is that if I don’t set the color key on the
dialog’s surface then everything works OK but then I’d be stuck with
square
dialogs. Another interesting thing is when I change a dialog item on my
non-square dialog, it makes the color keyed pixels appear in a color
other

than what would be there if the image wasn’t color keyed. Strange.

You always need to use the SDL_MUSTLOCK() macro to see whether you
need
to

lock the surface before using it. If the pixels are NULL, that’s a
good

clue. :slight_smile:

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


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


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


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

Hi,On Tuesday 09 December 2003 12:43 pm, Warren Schwader wrote:

OK, Sorry for the recent floods of emails, but for those interested I
think I fixed my problem,
If I use SDL_RLEACCEL when I create the doneImageSurface (one of the dialog
items) then I get the null pixels pointer after blitting the dialog surface
to the main surface. I can still use RLE on the dialog surface though
which is good.

I guess the only thing still that I need explained is why this is so?
–Warren Schwader

In a nut-shell, dialogSurface->pixels isn’t guaranteed to be valid except
when you are inside a Lock<->Unlock block:

SDL_LockSurface(dialogSurface);
// dialogSurface->pixels valid inside here
SDL_UnlockSurface(dialogSurface);
// dialogSurface->pixels no longer valid

RLE surfaces are a good example of why this is so. When you do this:

SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY|SDL_RLEACCEL, color);

the memory representing the pixels is compresed into a series of runs of
non-transparent pixels, which take up less space and are faster to render.
The original pixel memory is freed.

When you lock an RLE surface, you are requesting access to the original pixels
that no longer exist. SDL_LockSurface() knows this and kindly regenerates the
original surface for you from the RLE version, fills in dialogSurface->pixels
with a pointer to this temporary surface, and lets you fiddle with the
pixels.

When you call SDL_UnlockSurface() you are indicating that you have finished
fiddling and SDL_UnlockSurface() RLE encodes the modified pixels, destroys
the temporary surface, and sets dialogSurface->pixels to NULL to prevent
accidents(!).

Some hardware-surface systems e.g. DirectX are capable of copying surface data
between system memory and video memory transparently using the same
Lock/Unlock trick.

Hope that helps,

cheers,
John.
PS calling SDL_SetColorKey() or SDL_BlitSurface() whilst a surface is locked
(as you seem to) is a bad idea - see the docs.

Hi John, Thanks for the excellent explanation and tips. I could have swore
that I tried Locking and unlocking the dialog surface and pixels were still
null, but perhaps something else wasn’t quite right for that test.
I did what you suggested to the test code that I previously posted and it
worked. Thanks again!
–Warren Schwader> ----- Original Message -----

From: john@johnnypops.demon.co.uk (John Popplewell)
To:
Sent: Tuesday, December 09, 2003 1:57 PM
Subject: Re: [SDL] pixels getting set to NULL

Hi,

On Tuesday 09 December 2003 12:43 pm, Warren Schwader wrote:

OK, Sorry for the recent floods of emails, but for those interested I
think I fixed my problem,
If I use SDL_RLEACCEL when I create the doneImageSurface (one of the
dialog

items) then I get the null pixels pointer after blitting the dialog
surface

to the main surface. I can still use RLE on the dialog surface though
which is good.

I guess the only thing still that I need explained is why this is so?
–Warren Schwader

In a nut-shell, dialogSurface->pixels isn’t guaranteed to be valid
except
when you are inside a Lock<->Unlock block:

SDL_LockSurface(dialogSurface);
// dialogSurface->pixels valid inside here
SDL_UnlockSurface(dialogSurface);
// dialogSurface->pixels no longer valid

RLE surfaces are a good example of why this is so. When you do this:

SDL_SetColorKey(dialogSurface, SDL_SRCCOLORKEY|SDL_RLEACCEL, color);

the memory representing the pixels is compresed into a series of runs of
non-transparent pixels, which take up less space and are faster to render.
The original pixel memory is freed.

When you lock an RLE surface, you are requesting access to the original
pixels
that no longer exist. SDL_LockSurface() knows this and kindly regenerates
the
original surface for you from the RLE version, fills in
dialogSurface->pixels
with a pointer to this temporary surface, and lets you fiddle with the
pixels.

When you call SDL_UnlockSurface() you are indicating that you have
finished
fiddling and SDL_UnlockSurface() RLE encodes the modified pixels, destroys
the temporary surface, and sets dialogSurface->pixels to NULL to prevent
accidents(!).

Some hardware-surface systems e.g. DirectX are capable of copying surface
data
between system memory and video memory transparently using the same
Lock/Unlock trick.

Hope that helps,

cheers,
John.
PS calling SDL_SetColorKey() or SDL_BlitSurface() whilst a surface is
locked
(as you seem to) is a bad idea - see the docs.


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