SDL, OpenGL, texture conversion and speed

Greetings fellow SDL users/developers.

After a small vacation in SDL related programming (because of my
graduation for my Bachelor Degree, which I made btw) I’ve decided to
make me usefull and try to figure out some long standing problems. These
problems are related to SDL, OpenGL and most importantly, the speed
during texture conversion. It works but it is really slow.

Before people ask me code, please let me explain that I don’t have any
code to show (it’s based upon the testgl.c example from SDL 1.2.x). I do
hope that people from the SDL mailinglist can point me in the correct
direction.

Situation :

SDL_Display mainsurface (resolution : 320 x 240 at 16 bpp)
SDL_Display surface (resolution : 320 x 240 at 16 bpp)
SDL_Display src (resolution : w x h powered by at 32 bpp)

mainsurface is our screen/window which shows our output. surface is our
renderbuffer which has our pixels we want to render to our screen. src
is our buffer for the SDL (surface) -> OpenGL texture conversion ( using
SDL_BlitSurface(src, NULL, texture, NULL) ) which is then blitted to the
screen (mainsurface). This sollution works but it has one major
drawback, it’s slow since we are talking about converting two different
formats and normal SDL blitting is way faster (I’m talking about 30%
till 75% in some cases). As I stated before, this sollution was provided
from the testgl.c example but was changed to allow the constant changing
surface to be blitted to the screen.

What I want to do is optimize this but questions from the past didn’t
show a solid or working solution. I do know that other people had issues
with this situation and I was hoping that these people may have a
working solution.

I know this is little information and I will show some code. But
theoraticle information is appreciated :slight_smile:

With kind regards,

Niels Wagenaar

Only having skimmed over your email, please correct me if I’m wrong in
summarizing that the real difficulty here is mutating the contents of
an OpenGL texture.

I’ve been trying my hand at creating 3D accelerated texture-based
special effects, which use the 3D rendering hardware to alter the
contents of a texture map, thus avoiding having to send texture data
over the BUS all the time.

Perhaps you could use this idea to solve your problem as well?

  • Donny Viszneki

nwagenaar at digitaldynamics.nl wrote:

Greetings fellow SDL users/developers.

After a small vacation in SDL related programming (because of my
graduation for my Bachelor Degree, which I made btw) I’ve decided to
make me usefull and try to figure out some long standing problems. These
problems are related to SDL, OpenGL and most importantly, the speed
during texture conversion. It works but it is really slow.

Before people ask me code, please let me explain that I don’t have any
code to show (it’s based upon the testgl.c example from SDL 1.2.x). I do
hope that people from the SDL mailinglist can point me in the correct
direction.

Situation :

SDL_Display mainsurface (resolution : 320 x 240 at 16 bpp)
SDL_Display surface (resolution : 320 x 240 at 16 bpp)
SDL_Display src (resolution : w x h powered by at 32 bpp)

mainsurface is our screen/window which shows our output. surface is our
renderbuffer which has our pixels we want to render to our screen. src
is our buffer for the SDL (surface) -> OpenGL texture conversion ( using
SDL_BlitSurface(src, NULL, texture, NULL) ) which is then blitted to the
screen (mainsurface). This sollution works but it has one major
drawback, it’s slow since we are talking about converting two different
formats and normal SDL blitting is way faster (I’m talking about 30%
till 75% in some cases). As I stated before, this sollution was provided
from the testgl.c example but was changed to allow the constant changing
surface to be blitted to the screen.

What you’re trying to do is not very clear to me. It seems you’re trying
to render to an SDL_surface and then use this surface to create an
OpenGL texture ? If so, here my bit of advice :

First, I don’t understand why you need three buffers. OpenGL 1.2+
support texture uploading for most pixel formats. In this case you can
upload the texture directly from the original buffer by specifying the
correct pixel format (read the glTexImage2D manpage, it describes these
formats). Try to use the glTexSubImage2D call instead of the
glTexImage2D call when possible if you don’t fill your texture with data
(for example when you have to pad the size to the next power of 2), some
OpenGL drivers can take adantage of this (some others upload the full
texture again). You can also use glPixelStore to upload only the
relevant part of a surface to a texture without having to do any copying.

As a rule of thumb, the less data you need for your texture, the faster
the upload. For example, if you only use 8bpp, try to make use of
paletted textures. If you can afford using 15/16bpp instead of 24bpp,
that’s fine too. Also, ATI cards benefit a lot from the reversed BGR
pixel format when doing texture uploads. Nvidia cards are more tolerant,
performance wise, to the pixel format you use.

In an emulator I’m working on, I’ve implemented OpenGL scaling of the
display, and 8bpp display with a paletted texture is faster than using
SDL with a software surface under X11. So using a texture for uploads
can be a win from a performance viewpoint if you’re careful.

(btw I’m currently rewriting the SDL OpenGL-scaling backend to support
different texture formats, and thus avoid copying data around).

Stephane

-----Oorspronkelijk bericht-----
Van: smirk [mailto:smirk at thebuicksix.com]
Verzonden: dinsdag 3 augustus 2004 20:13
Aan: sdl
Onderwerp: Re: [SDL] SDL, OpenGL, texture conversion and speed.

Hello Donny,

Only having skimmed over your email, please correct me if I’m
wrong in
summarizing that the real difficulty here is mutating the contents of
an OpenGL texture.

No not really. The mutating/converting of a SDL_Display to a texture
goes without problems. But because of the difference in formats, the
convertion takes a long time ( 16 bpp (the pixel data) -> 32 bpp
(the display for converting to an OpenGL texture) -> 16 bpp (screen).

What I seek is an optimized way to convert a SDL_Display from a
particular format to a texture without the speed issue I now have.

I’ve been trying my hand at creating 3D accelerated texture-based
special effects, which use the 3D rendering hardware to alter the
contents of a texture map, thus avoiding having to send texture data
over the BUS all the time.

Sorry but this information was not optimized for input. It’s only for
2D graphics (hence the SDL_Display) and to be precise, for a project
I’m working on (Virtual Jaguar/SDL ->
http://www.icculus.org/virtualjaguar).

Perhaps you could use this idea to solve your problem as well?

I think it’s to far fetched as how you state it :slight_smile:

  • Donny Viszneki

Regards,

Niels Wagenaar

-----Oorspronkelijk bericht-----
Van: stephane.marchesin [mailto:stephane.marchesin at wanadoo.fr]
Verzonden: dinsdag 3 augustus 2004 20:22
Aan: sdl
Onderwerp: Re: [SDL] SDL, OpenGL, texture conversion and speed.

– SNIP –

What you’re trying to do is not very clear to me. It seems
you’re trying
to render to an SDL_surface and then use this surface to create an
OpenGL texture ? If so, here my bit of advice :

In short (and to anwser the next portion of your text) I have the
following :

Currently the Virtual Jaguar/SDL project has an OpenGL "engine"
so that people can enjoy accelerated 2D blitting. But the problem
resides in how it’s implented (based upon the testgl.c example)
since it needs a conversion from a 16 bpp buffer to a 32 bpp
SDL_Display which is then converted to an OpenGL texture and
blitted to the main SDL_Display.

In fact, I use two displays in normal SDL blitting. For SDL/OpenGL
blitting I need the 3rd SDL_Display so that I can convert the 16 bpp
SDL_Display to a 32 bpp display which is then converted to an OpenGL
texture (and then blitted to the screen).

SDL_Display mainsurface is my primary display surface and is infact
the screen/window which the user sees. SDL_Display surface is my
buffer where the emulator pumps it’s graphical data. In normal SDL
blitting mode I just do a SDL_BlitSurface so that the graphical
data from surface is blitted onto the screen (=mainsurface).

For the use of OpenGL I have made a (temporary) SDL_Display called
texture (and not src as I wrote earlier) which has a 32 bpp so that
I can use the following code:

void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int
texturetype)
{

// convert color-indexed surface to RGB texture
// src = display and contains VJ's graphical data.
// dst = maindisplay and is our main window.
// texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
// #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
//	0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
// #else
//	0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
// #endif
// where w and h is the powered by two width and height of
// display (our graphical buffer).
//
SDL_BlitSurface(src, NULL, texture, NULL);

// Texturemap complete texture to surface so we have free scaling 
// and antialiasing 
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
	GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);

glBegin(GL_TRIANGLE_STRIP);
	glTexCoord2f(texcoord[0], texcoord[1]); glVertex3i(0, 0, 0);
	glTexCoord2f(texcoord[2], texcoord[1]); glVertex3i(dst->w, 0, 

0);
glTexCoord2f(texcoord[0], texcoord[3]); glVertex3i(0, dst->h,
0);
glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w,
dst->h, 0);
glEnd();

SDL_GL_SwapBuffers();    

}

I hope that the above code is somewhat simpler to understand what
I mean. The convertion from the 16 bpp display to the 32 bpp texture
takes a very long time because of format differences.

I hope it’s possible to somehow make this convertion go away or do
a enhanced conversion. While it works, it has one drawback. It’s
much slower then normal SDL blitting while OpenGL should be faster
since it’s accelerated (tested on Linux, Win32 and MacOS X).

First, I don’t understand why you need three buffers. OpenGL 1.2+
support texture uploading for most pixel formats. In this
case you can
upload the texture directly from the original buffer by
specifying the
correct pixel format (read the glTexImage2D manpage, it
describes these
formats). Try to use the glTexSubImage2D call instead of the
glTexImage2D call when possible if you don’t fill your
texture with data
(for example when you have to pad the size to the next power
of 2), some
OpenGL drivers can take adantage of this (some others upload the full
texture again). You can also use glPixelStore to upload only the
relevant part of a surface to a texture without having to do
any copying.

In fact I use two (2) buffers. display (the Virtual Jaguar graphical
buffer) and texture (for converting display to an OpenGL convertable
texture).

As a rule of thumb, the less data you need for your texture,
the faster
the upload. For example, if you only use 8bpp, try to make use of
paletted textures. If you can afford using 15/16bpp instead of 24bpp,
that’s fine too. Also, ATI cards benefit a lot from the reversed BGR
pixel format when doing texture uploads. Nvidia cards are
more tolerant,
performance wise, to the pixel format you use.

From what I understood, OpenGL only allows 32 bpp textures and there
for I need to convert display to 32 bpp. But as I stated, this is slow.
From what I understand, you’re saying that OpenGL textures can be 16 bpp
but needs to be “converted” so that OpenGL can understand this?

In an emulator I’m working on, I’ve implemented OpenGL scaling of the
display, and 8bpp display with a paletted texture is faster
than using
SDL with a software surface under X11. So using a texture for uploads
can be a win from a performance viewpoint if you’re careful.

The project I’m talking about is Virtual Jaguar/SDL. A portable Atari
Jaguar emulator which was ported from Visual C++/asm/DirectX (with
omplete
french commentary) to standard GNU C/C++ and SDL :slight_smile: If you could share
some sources, I would be gratefull!

(btw I’m currently rewriting the SDL OpenGL-scaling backend
to support
different texture formats, and thus avoid copying data around).

I’m very interested in this information! You can contact me privately
if you don’t want to share this information to the world :wink:

Stephane

Regards,

Niels Wagenaar

nwagenaar at digitaldynamics.nl wrote:
[…]

I hope that the above code is somewhat simpler to understand what
I mean. The convertion from the 16 bpp display to the 32 bpp texture
takes a very long time because of format differences.

Well, most of the time is usually spent uploading the texture. Format
conversion usually comes second (but that depends on the format).

I hope it’s possible to somehow make this convertion go away or do
a enhanced conversion. While it works, it has one drawback. It’s
much slower then normal SDL blitting while OpenGL should be faster
since it’s accelerated (tested on Linux, Win32 and MacOS X).

Again, because of texture uploading, OpenGL isn’t always faster. It was
faster for me at 8bpp (the texture is 512512, the maximal amstrad
resolution is 384
272, which is the size we have to upload). It might
also be faster for a 320x240 picture, but don’t count on it, you’d
better count on scaling quality and such (advanced effects and such…).

First, I don’t understand why you need three buffers. OpenGL 1.2+
support texture uploading for most pixel formats. In this
case you can
upload the texture directly from the original buffer by
specifying the
correct pixel format (read the glTexImage2D manpage, it
describes these
formats). Try to use the glTexSubImage2D call instead of the
glTexImage2D call when possible if you don’t fill your
texture with data
(for example when you have to pad the size to the next power
of 2), some
OpenGL drivers can take adantage of this (some others upload the full
texture again). You can also use glPixelStore to upload only the
relevant part of a surface to a texture without having to do
any copying.

In fact I use two (2) buffers. display (the Virtual Jaguar graphical
buffer) and texture (for converting display to an OpenGL convertable
texture).

Ok, with the right format, you can probably dump “texture” and upload
from “buffer” directly.

As a rule of thumb, the less data you need for your texture,
the faster
the upload. For example, if you only use 8bpp, try to make use of
paletted textures. If you can afford using 15/16bpp instead of 24bpp,
that’s fine too. Also, ATI cards benefit a lot from the reversed BGR
pixel format when doing texture uploads. Nvidia cards are
more tolerant,
performance wise, to the pixel format you use.

From what I understood, OpenGL only allows 32 bpp textures and there
for I need to convert display to 32 bpp. But as I stated, this is slow.

Good news for you ! The internalFormat for glTex(Sub)Image2D can be
GL_RGB5 for example.

From what I understand, you’re saying that OpenGL textures can be 16 bpp
but needs to be “converted” so that OpenGL can understand this?

No, my point is : don’t convert. Choose a bpp, work with this bpp, feed
this bpp to OpenGL, asking it to use that exact bpp for the
internalformat as well. No conversion should take place with most
drivers. Also try to keep this bpp as small as possible.

In an emulator I’m working on, I’ve implemented OpenGL scaling of the
display, and 8bpp display with a paletted texture is faster
than using
SDL with a software surface under X11. So using a texture for uploads
can be a win from a performance viewpoint if you’re careful.

The project I’m talking about is Virtual Jaguar/SDL. A portable Atari
Jaguar emulator which was ported from Visual C++/asm/DirectX (with
omplete
french commentary) to standard GNU C/C++ and SDL :slight_smile: If you could share
some sources, I would be gratefull!

The emulator is the Amstrad CPC emulator Caprice32.
Here’s the emulator patch (it’s not yet into cvs until I sort out some
C++ function casting difficulties) :
http://icps.u-strasbg.fr/~marchesin/perso/cpc/capricegl2.patch
Here’s the cvs you can apply it to (but reading the patch should be
enough) :

(btw I’m currently rewriting the SDL OpenGL-scaling backend
to support
different texture formats, and thus avoid copying data around).

I’m very interested in this information! You can contact me privately
if you don’t want to share this information to the world :wink:

No, such important information should not be kept hidden, the world has
to know ! :slight_smile:
Here’s the old version :
http://icps.u-strasbg.fr/~marchesin/sdl/sdl_glscale.patch

I’ll finish the new version one of these days, but my OpenGL driver is
broken ATM so I can’t test/fix it (but I know for sure it doesn’t work
right).

(come on, french commentary isn’t that bad :slight_smile:
Stephane