Pixels and harware surfaces

“Thad Phetteplace” wrote

I am experiencing a strange problem with accessing an offscreen
hardware surface under SDL with DirectX. I am loading an image
into a surface and then creating a new surface using
SDL_DisplayFormat. Unfortunately, the pixels member of the
new surface is not set; it is a null pointer. The actual screen
surface has the pixels member set, and the the original image
surface (before calling SDL_DisplayFormat) has a pixels pointer,
but not the surface returned by SDL_Display Format.

hello thad. there is a good reason behind all this.
when surfaces are placed in video memory, it is not safe
to access the pixels directly without telling the rest
of the system to not mess with it. to do this you use the
SDL_LockSurface and SDL_UnlockSurface to claim access to
the surface pixel data. you can always call the SDL_MUSTLOCK
macro to determine if a surface must be locked before pixel
access, but recently SDL was changed so that surfaces
requiring a lock have their pixel data set to NULL.

I do NOT have this problem when running my app in a window…
only in fullscreen under Windows/DirectX. I also do not
have any problems running under linux (fbcon and X work fine).

this is because SDL only uses directx hardware surfaces when
running full screen. otherwise SDL is using regular software
surfaces and there are no restrictions on accessing the
surface pixel data.

also, note that it is perfectly safe to lock and unlock a
normal software surface. so, perhaps the best method is to
always lock any surface before accessing the pixels. then
your program will work under all conditions.

also, beside just SDL_HWSURFACE, there are other things
that can require a surface to be locked before access.
(like SDL_RLEACCEL)

I am experiencing a strange problem with accessing an offscreen
hardware surface under SDL with DirectX. I am loading an image
into a surface and then creating a new surface using
SDL_DisplayFormat. Unfortunately, the pixels member of the
new surface is not set; it is a null pointer. The actual screen
surface has the pixels member set, and the the original image
surface (before calling SDL_DisplayFormat) has a pixels pointer,
but not the surface returned by SDL_Display Format. Is this
a bug or is it by design? Hardware accellerated blits from the
surface work fine, but I also need to access individual pixels
within the surface to do some custom transformations on some
blits.

I do NOT have this problem when running my app in a window…
only in fullscreen under Windows/DirectX. I also do not
have any problems running under linux (fbcon and X work fine).

I’ve tried it on several different Windows boxes… 98/NT/2000
and it does the same thing on all of them regardless of OS or
video card.

Does anyone have a suggestion? Am I missing something
obvious here?

Thanks in advance,

Thad

Does anyone have a suggestion? Am I missing something
obvious here?

This is easy. You need to lock the surface before accessing the pixels
and unlock it when you’re done, before you perform the blit. Keep in mind
that writing to video memory directly is very slow.

See ya,
-Sam Lantinga, Lead Programmer, Loki Entertainment Software

Does anyone have a suggestion? Am I missing something
obvious here?

This is easy. You need to lock the surface before accessing the pixels
and unlock it when you’re done, before you perform the blit. Keep in mind
that writing to video memory directly is very slow.

Doh! (slamming hand into forhead) The crazy thing is, I was remembering
to lock the on-screen surface… but I totally forgot to lock the
surface I was copying from. Thanks a bunch Sam.

And yes, directly accessing video memory is slow… but I only do
it for a few small special effects. It hasn’t noticeably impacted
my frame rate yet.

Later,

Thad

Thad Phetteplace wrote:

I am experiencing a strange problem with accessing an offscreen
hardware surface under SDL with DirectX. I am loading an image
into a surface and then creating a new surface using
SDL_DisplayFormat. Unfortunately, the pixels member of the
new surface is not set; it is a null pointer. The actual screen
surface has the pixels member set, and the the original image
surface (before calling SDL_DisplayFormat) has a pixels pointer,
but not the surface returned by SDL_Display Format. Is this
a bug or is it by design? Hardware accellerated blits from the
surface work fine, but I also need to access individual pixels
within the surface to do some custom transformations on some
blits.

I do NOT have this problem when running my app in a window…
only in fullscreen under Windows/DirectX. I also do not
have any problems running under linux (fbcon and X work fine).

I’ve tried it on several different Windows boxes… 98/NT/2000
and it does the same thing on all of them regardless of OS or
video card.

Does anyone have a suggestion? Am I missing something
obvious here?

Thanks in advance,

Thad

Are you locking the surface before trying to molest it?–
SmokeSerpent <@Benjamin_Moos>
“The purpose of writing is to inflate weak ideas, obscure pure reasoning,
and inhibit clarity. With a little practice, writing can be an
intimidating and impenetrable fog!” – Calvin