Direct pixel access under windows

Hi.

I am developing a SDL game and implemented your getpixel() and putpixel()
algorithm for making smooth texture transitions. Under GNU/Linux this works
great, but under windows the program dies. This happens only in fullscreen
mode with SDL_DOUBLEBUF and SDL_HWSURFACE. At first, I thought my graphics
card (Mobile Intel GMA 915) or the graphics driver were the problem, but
then various other people tested my program and got the same results (all in
all, we tested on Windows 2000 Prof. (SP4), Windows XP Prof. (w and w/o
SP2) and with a Mobile Intel GMA 915, GeForce TI 4200 and GeForce 6600 GT).
I also tested versions 1.2.7 and 1.2.9 of SDL.

Considering these tests, either I made a mistake inside the code, or the
problem may be SDL’s fault. Or are there some restrictions using direct
pixel access under windows?

table of flag combinations:

^ flags ^ crashes ^
| SDL_FULLSCREEN|SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | x |
| SDL_FULLSCREEN|SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | x |
| SDL_FULLSCREEN|SDL_HWSURFACE| SDL_ANYFORMAT | x |
| SDL_FULLSCREEN|SDL_SWSURFACE| SDL_ANYFORMAT | |
| SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | |

For better understanding, I made the following example program:—

#include <SDL/SDL.h>
#include
#include
using namespace std;

SDL_Surface *screen;

//! return pixel value
/*!
return the pixel value of the surface at the specified coordinate
note: the surface must be locked before calling this!

this function is copied and pasted from sdldoc.pdf
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;

/* here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp)
{
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 )p;
default:
return 0; /
shouldn’t happen, but avoids warnings */
}
}

//! set pixel value
/*!
set the pixel at the specified coordinates to the specified value

this function is copied and pasted from sdldoc.pdf
*/
void putpixel(SDL_Surface surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/
here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}

//! main()
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
cerr << "couldn’t initialize SDL: "
<< SDL_GetError() << endl;
exit(1);
}
atexit(SDL_Quit);

screen = SDL_SetVideoMode(800, 600, 0,
SDL_FULLSCREEN|SDL_HWSURFACE|
SDL_DOUBLEBUF|SDL_ANYFORMAT);
if (!screen) {
cerr << "couldn’t set video mode: "
<< SDL_GetError() << endl;
exit(1);
}

/* load bitmap */
SDL_Surface bitmap = SDL_LoadBMP(“bitmap.bmp”);
if (!bitmap) {
cerr << "couldn’t load “bitmap.bmp”: "
<< SDL_GetError() << endl;
exit(1);
}
/
remove pink */
SDL_SetColorKey(bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(
bitmap->format, 255, 0, 255));
SDL_BlitSurface(bitmap, 0, screen, 0);
SDL_FreeSurface(bitmap);
SDL_Flip(screen);

//Uint32 yellow = SDL_MapRGB(screen->format, 255, 255, 0);
/* at this position there should be a colored pixel */
Uint32 yellow = getpixel(screen, 35, 60);

if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
cerr << "Can’t lock screen: " << SDL_GetError() << endl;
return 1;
}
}

/* draw some pixels to the screen */
putpixel(screen, 50, 50, yellow);
putpixel(screen, 75, 75, yellow);
putpixel(screen, 150, 150, yellow);
putpixel(screen, 200, 100, yellow);

if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}

SDL_Flip(screen);

// wait 3 seconds
clock_t endwait;
endwait = clock() + 3 * CLK_TCK;
while (clock() < endwait);

return 0;
}


(You need a “bitmap.bmp” for this program to work, as it will get the color
of the pixel to draw from this image. Therefore you should have some colored
bitmap to see the drawn pixels at your screen.)

As you might guess, the program doesn’t crash when specifying the color of
the pixel to be drawn with SDL_MapRGB(), rather than getting it per
getpixel() from the surface. But in my game, which is much more complex, the
game crashes nevertheless. So the problem should not be problem inside
getpixel().


The same source as a cpp file:

For win pre-builds, look at:

Where is the message loop?

Also, this “spin lock” while (clock() < endwait); is bad practice. There is
an SDL delay function.

Matthew

I am developing a SDL game and implemented your getpixel() and putpixel()> algorithm for making smooth texture transitions. Under GNU/Linux this

works
great, but under windows the program dies. This happens only in fullscreen
mode with SDL_DOUBLEBUF and SDL_HWSURFACE. At first, I thought my graphics
card (Mobile Intel GMA 915) or the graphics driver were the problem, but
then various other people tested my program and got the same results (all
in
all, we tested on Windows 2000 Prof. (SP4), Windows XP Prof. (w and w/o
SP2) and with a Mobile Intel GMA 915, GeForce TI 4200 and GeForce 6600
GT).
I also tested versions 1.2.7 and 1.2.9 of SDL.

Considering these tests, either I made a mistake inside the code, or the
problem may be SDL’s fault. Or are there some restrictions using direct
pixel access under windows?

This is only an example to get a better overview of the used code. The
real program has a message loop, as well as real SDL delays. See
http://choerbaert.org/wiki/bert:downloads. My problem is the direct pixel
access, nothing else.

Alexander HeinleinOn Fri, Mar 17, 2006 at 03:21:33PM -0500, Matt J wrote:

Where is the message loop?

Also, this “spin lock” while (clock() < endwait); is bad practice. There is
an SDL delay function.

Matthew

I am developing a SDL game and implemented your getpixel() and putpixel()

algorithm for making smooth texture transitions. Under GNU/Linux this
works
great, but under windows the program dies. This happens only in fullscreen
mode with SDL_DOUBLEBUF and SDL_HWSURFACE. At first, I thought my graphics
card (Mobile Intel GMA 915) or the graphics driver were the problem, but
then various other people tested my program and got the same results (all
in
all, we tested on Windows 2000 Prof. (SP4), Windows XP Prof. (w and w/o
SP2) and with a Mobile Intel GMA 915, GeForce TI 4200 and GeForce 6600
GT).
I also tested versions 1.2.7 and 1.2.9 of SDL.

Considering these tests, either I made a mistake inside the code, or the
problem may be SDL’s fault. Or are there some restrictions using direct
pixel access under windows?


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

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060317/a7bab1b1/attachment.pgp

Hi.

I am developing a SDL game and implemented your getpixel() and
putpixel() algorithm for making smooth texture transitions. Under
GNU/Linux this works great, but under windows the program dies. This
happens only in fullscreen mode with SDL_DOUBLEBUF and SDL_HWSURFACE.
At first, I thought my graphics card (Mobile Intel GMA 915) or the
graphics driver were the problem, but then various other people
tested my program and got the same results (all in all, we tested on
Windows 2000 Prof. (SP4), Windows XP Prof. (w and w/o SP2) and with a
Mobile Intel GMA 915, GeForce TI 4200 and GeForce 6600 GT). I also
tested versions 1.2.7 and 1.2.9 of SDL.

Considering these tests, either I made a mistake inside the code, or
the problem may be SDL’s fault. Or are there some restrictions using
direct pixel access under windows?

table of flag combinations:

^ flags ^ crashes
^

| SDL_FULLSCREEN|SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | x
| | SDL_FULLSCREEN|SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | x
| | SDL_FULLSCREEN|SDL_HWSURFACE| SDL_ANYFORMAT | x
| | SDL_FULLSCREEN|SDL_SWSURFACE| SDL_ANYFORMAT |
| | SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | |

For better understanding, I made the following example program:


#include <SDL/SDL.h>
#include
#include
using namespace std;

SDL_Surface *screen;

//! return pixel value
/*!
return the pixel value of the surface at the specified coordinate
note: the surface must be locked before calling this!

this function is copied and pasted from sdldoc.pdf
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;

/* here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp)
{
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 )p;
default:
return 0; /
shouldn’t happen, but avoids
warnings */ }
}

//! set pixel value
/*!
set the pixel at the specified coordinates to the specified value

this function is copied and pasted from sdldoc.pdf
*/
void putpixel(SDL_Surface surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/
here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}

//! main()
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
cerr << "couldn’t initialize SDL: "
<< SDL_GetError() << endl;
exit(1);
}
atexit(SDL_Quit);

screen = SDL_SetVideoMode(800, 600, 0,
SDL_FULLSCREEN|SDL_HWSURFACE|
SDL_DOUBLEBUF|SDL_ANYFORMAT);
if (!screen) {
cerr << "couldn’t set video mode: "
<< SDL_GetError() << endl;
exit(1);
}

/* load bitmap */
SDL_Surface bitmap = SDL_LoadBMP(“bitmap.bmp”);
if (!bitmap) {
cerr << "couldn’t load “bitmap.bmp”: "
<< SDL_GetError() << endl;
exit(1);
}
/
remove pink */
SDL_SetColorKey(bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(
bitmap->format, 255, 0,
255)); SDL_BlitSurface(bitmap, 0, screen, 0);
SDL_FreeSurface(bitmap);
SDL_Flip(screen);

//Uint32 yellow = SDL_MapRGB(screen->format, 255, 255, 0);
/* at this position there should be a colored pixel */

You should lock the surface before you can read from it.

Uint32 yellow = getpixel(screen, 35, 60);

if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
cerr << "Can’t lock screen: " << SDL_GetError() << endl;
return 1;
}
}

/* draw some pixels to the screen */
putpixel(screen, 50, 50, yellow);
putpixel(screen, 75, 75, yellow);
putpixel(screen, 150, 150, yellow);
putpixel(screen, 200, 100, yellow);

if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}

SDL_Flip(screen);

// wait 3 seconds
clock_t endwait;
endwait = clock() + 3 * CLK_TCK;
while (clock() < endwait);

return 0;
}


(You need a “bitmap.bmp” for this program to work, as it will get the
color of the pixel to draw from this image. Therefore you should have
some colored bitmap to see the drawn pixels at your screen.)

As you might guess, the program doesn’t crash when specifying the
color of the pixel to be drawn with SDL_MapRGB(), rather than getting
it per getpixel() from the surface. But in my game, which is much
more complex, the game crashes nevertheless. So the problem should
not be problem inside getpixel().

It is not. It’s the fact that you have to lock if you are reading from
the surface as well as if you are writing to it.On Friday 17 March 2006 21:50, alexander.heinlein at web.de wrote:


The same source as a cpp file:

For win pre-builds, look at:

Yeah. Although locking the surface in the example program to late was only
an unintended mistake (in my real program the surface gets locked at the
correct time), this is nevertheless the solution. As I looked again on my
code, I saw that I locked the wrong surface (probably because I changed the
code several times and accessed a different surface than originally
intended). Now, locking the correct surface, it works. Strangely I didn’t
notice that, because under GNU/Linux there was no need to lock the surface
for direct access.

Thanks a lot!

Alexander Heinlein
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060317/b595d610/attachment.pgpOn Fri, Mar 17, 2006 at 10:41:54PM +0200, Sami N??t?nen wrote:

On Friday 17 March 2006 21:50, @alexander.heinlein_a wrote:

Hi.

I am developing a SDL game and implemented your getpixel() and
putpixel() algorithm for making smooth texture transitions. Under
GNU/Linux this works great, but under windows the program dies. This
happens only in fullscreen mode with SDL_DOUBLEBUF and SDL_HWSURFACE.
At first, I thought my graphics card (Mobile Intel GMA 915) or the
graphics driver were the problem, but then various other people
tested my program and got the same results (all in all, we tested on
Windows 2000 Prof. (SP4), Windows XP Prof. (w and w/o SP2) and with a
Mobile Intel GMA 915, GeForce TI 4200 and GeForce 6600 GT). I also
tested versions 1.2.7 and 1.2.9 of SDL.

Considering these tests, either I made a mistake inside the code, or
the problem may be SDL’s fault. Or are there some restrictions using
direct pixel access under windows?

table of flag combinations:

^ flags ^ crashes
^

| SDL_FULLSCREEN|SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | x
| | SDL_FULLSCREEN|SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | x
| | SDL_FULLSCREEN|SDL_HWSURFACE| SDL_ANYFORMAT | x
| | SDL_FULLSCREEN|SDL_SWSURFACE| SDL_ANYFORMAT |
| | SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_ANYFORMAT | |

For better understanding, I made the following example program:


#include <SDL/SDL.h>
#include
#include
using namespace std;

SDL_Surface *screen;

//! return pixel value
/*!
return the pixel value of the surface at the specified coordinate
note: the surface must be locked before calling this!

this function is copied and pasted from sdldoc.pdf
*/
Uint32 getpixel(SDL_Surface *surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;

/* here p is the address to the pixel we want to retrieve */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp)
{
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 )p;
default:
return 0; /
shouldn’t happen, but avoids
warnings */ }
}

//! set pixel value
/*!
set the pixel at the specified coordinates to the specified value

this function is copied and pasted from sdldoc.pdf
*/
void putpixel(SDL_Surface surface, int x, int y, Uint32 pixel)
{
int bpp = surface->format->BytesPerPixel;
/
here p is the address to the pixel we want to set */
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

switch(bpp)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}

//! main()
int main(int argc, char *argv[])
{
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
cerr << "couldn’t initialize SDL: "
<< SDL_GetError() << endl;
exit(1);
}
atexit(SDL_Quit);

screen = SDL_SetVideoMode(800, 600, 0,
SDL_FULLSCREEN|SDL_HWSURFACE|
SDL_DOUBLEBUF|SDL_ANYFORMAT);
if (!screen) {
cerr << "couldn’t set video mode: "
<< SDL_GetError() << endl;
exit(1);
}

/* load bitmap */
SDL_Surface bitmap = SDL_LoadBMP(“bitmap.bmp”);
if (!bitmap) {
cerr << "couldn’t load “bitmap.bmp”: "
<< SDL_GetError() << endl;
exit(1);
}
/
remove pink */
SDL_SetColorKey(bitmap, SDL_SRCCOLORKEY, SDL_MapRGB(
bitmap->format, 255, 0,
255)); SDL_BlitSurface(bitmap, 0, screen, 0);
SDL_FreeSurface(bitmap);
SDL_Flip(screen);

//Uint32 yellow = SDL_MapRGB(screen->format, 255, 255, 0);
/* at this position there should be a colored pixel */

You should lock the surface before you can read from it.

Uint32 yellow = getpixel(screen, 35, 60);

if ( SDL_MUSTLOCK(screen) ) {
if ( SDL_LockSurface(screen) < 0 ) {
cerr << "Can’t lock screen: " << SDL_GetError() << endl;
return 1;
}
}

/* draw some pixels to the screen */
putpixel(screen, 50, 50, yellow);
putpixel(screen, 75, 75, yellow);
putpixel(screen, 150, 150, yellow);
putpixel(screen, 200, 100, yellow);

if ( SDL_MUSTLOCK(screen) ) {
SDL_UnlockSurface(screen);
}

SDL_Flip(screen);

// wait 3 seconds
clock_t endwait;
endwait = clock() + 3 * CLK_TCK;
while (clock() < endwait);

return 0;
}


(You need a “bitmap.bmp” for this program to work, as it will get the
color of the pixel to draw from this image. Therefore you should have
some colored bitmap to see the drawn pixels at your screen.)

As you might guess, the program doesn’t crash when specifying the
color of the pixel to be drawn with SDL_MapRGB(), rather than getting
it per getpixel() from the surface. But in my game, which is much
more complex, the game crashes nevertheless. So the problem should
not be problem inside getpixel().

It is not. It’s the fact that you have to lock if you are reading from
the surface as well as if you are writing to it.


The same source as a cpp file:

For win pre-builds, look at:


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

alexander.heinlein at web.de wrote:

Strangely I didn’t notice that, because under
GNU/Linux there was no need to lock the surface for direct access.

most likly becaus you didn’t got a HW surface on linux in the first
place. SW surfaces do not need locking.

clemens

Yes, according to SDL_VideoInfo thats correct. Are there any reasons for not
getting a HW surface? Direct rendering etc. is available, so thats not the
problem.

Alexander Heinlein
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060317/fd24ebf8/attachment.pgpOn Fri, Mar 17, 2006 at 10:32:17PM +0100, Clemens Kirchgatterer wrote:

@alexander.heinlein_a wrote:

Strangely I didn’t notice that, because under
GNU/Linux there was no need to lock the surface for direct access.

most likly becaus you didn’t got a HW surface on linux in the first
place. SW surfaces do not need locking.

clemens

Direct rendering applies to OpenGL only. The plain X11 target does not
support 2D hardware surfaces because there’s not really such a thing
under X11, unless you count one of the following extensions:

There’s DGA, but DGA is an ugly hack that’s rarely used nowadays.
Though I think SDL still has a target for it, if you have it compiled
in you just have to implicitly ask for it (ie. SDL_VIDEODRIVER=dga,
IIRC). Of course you’ll probably need superuser rights because it
needs to read/write directly to /dev/mem (yuck!), and it’s
fullscreen-only.

There’s also Xv, but it’s really only useful for video overlays. The
proprietary nvidia driver does provide an RGB overlay though, and
Xmame can use it if available (and the performance results are pretty
good I might add), but I don’t think SDL supports it.

And finally, as mentionned many times here, the best way to get fast
2D hardware rendering under X11 is OpenGL. ;)On 3/17/06, alexander.heinlein at web.de <alexander.heinlein at web.de> wrote:

Yes, according to SDL_VideoInfo thats correct. Are there any reasons for not
getting a HW surface? Direct rendering etc. is available, so thats not the
problem.

  • SR

I had the same problem some time ago. I used the getPixel from SGE. When
I put the getPixel() into a LockScreen()/UnlockScreen()-pair, the
crashes weren’t anymore.

Regards,
Thomas Omilian

Okay, I will try this. Thanks.
-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 191 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20060318/44036379/attachment.pgpOn Fri, Mar 17, 2006 at 06:59:13PM -0500, Simon Roby wrote:

On 3/17/06, @alexander.heinlein_a <@alexander.heinlein_a> wrote:

Yes, according to SDL_VideoInfo thats correct. Are there any reasons for not
getting a HW surface? Direct rendering etc. is available, so thats not the
problem.

Direct rendering applies to OpenGL only. The plain X11 target does not
support 2D hardware surfaces because there’s not really such a thing
under X11, unless you count one of the following extensions:

There’s DGA, but DGA is an ugly hack that’s rarely used nowadays.
Though I think SDL still has a target for it, if you have it compiled
in you just have to implicitly ask for it (ie. SDL_VIDEODRIVER=dga,
IIRC). Of course you’ll probably need superuser rights because it
needs to read/write directly to /dev/mem (yuck!), and it’s
fullscreen-only.

There’s also Xv, but it’s really only useful for video overlays. The
proprietary nvidia driver does provide an RGB overlay though, and
Xmame can use it if available (and the performance results are pretty
good I might add), but I don’t think SDL supports it.

And finally, as mentionned many times here, the best way to get fast
2D hardware rendering under X11 is OpenGL. :wink: