Proper way to duplicate a SDL_Texture

Hello all,
I’ve recently been porting my stuff to SDL2 and I still have doubts about Textures (but I will leave this to another post).

My question is: how do you “properly” copy a SDL_Texture?
With Sourfaces you just blit one into another, clipping the way you want. With Textures (from what I have understood) you have to define your target Texture with SDL_TEXTUREACCESS_TARGET, then bind it to a new SDL_Renderer(which has to be bound to a window) and the you can user SDL_RenderCopy() to copy the contents. It seems to me an incredible amount of work.

For instance, in an “oldstyle” 2D game. Previously in 1.2 I had a struct form my animated sprites that had a Surface as sprite sheet and another as sprite “face”. At every animation tick I would blit the current frame from the sheet into the face, modify it as needed (color mods, alpha mods, etc) and then redender it to the screen. Now I have to change my approach (or, I have to call SDL_CreateTextureFromSurface() every frame, which is bad).

What am I missing?

Thanks!------------------------
Fabio.

FabioF wrote:

Hello all,
I’ve recently been porting my stuff to SDL2 and I still have doubts about Textures (but I will leave this to another post).

My question is: how do you “properly” copy a SDL_Texture?
With Sourfaces you just blit one into another, clipping the way you want. With Textures (from what I have understood) you have to define your target Texture with SDL_TEXTUREACCESS_TARGET, then bind it to a new SDL_Renderer(which has to be bound to a window) and the you can user SDL_RenderCopy() to copy the contents. It seems to me an incredible amount of work.

For instance, in an “oldstyle” 2D game. Previously in 1.2 I had a struct form my animated sprites that had a Surface as sprite sheet and another as sprite “face”. At every animation tick I would blit the current frame from the sheet into the face, modify it as needed (color mods, alpha mods, etc) and then redender it to the screen. Now I have to change my approach (or, I have to call SDL_CreateTextureFromSurface() every frame, which is bad).

What am I missing?

Thanks!

Why do you need to create a copy to apply the color/alpha mods to?

  1. Load your spritesheet into a texture.
  2. Set alpha and color mods using the SetTextureAlphaMod() and SetTextureColorMod() functions.
  3. Do a RenderCopy() to the display.
  4. Do the RenderPresent() to actually show it.

The mods will be applied during the render operation. If some other tweakage is required, you should be able to do it via a second RenderCopy() (for instance, rendering a light fog over your sprite(s)) before you do the RenderPresent().

This way, all of the work will be done in the video card’s memory, and by the GPU, rather than in main memory and by the CPU. Unless you’re using a seriously flaky video driver (cough open source ati driver cough) this will be much faster than doing things the old way…

My question is: how do you “properly” copy a SDL_Texture?
With Sourfaces you just blit one into another, clipping the way you

There are a few ways, and they aren’t great.

  • You can set the second texture to be a render target, and
    SDL_RenderCopy() the first texture to it. This will fail on systems that
    don’t support render targets (which is really really rare…we’re
    talking about old Android devices, mostly).
  • You can draw to the renderer, and SDL_RenderReadPixels() into a memory
    buffer, then create a texture from that. This is really slow, and works
    without render targets, but it works fine if you just need to do it once
    at startup or whatever.
  • You can take the original source pixels you created a texture from and
    create two textures from it. If you created the texture as
    SDL_TEXTUREACCESS_STREAMING, SDL keeps a copy of the pixels in RAM, so
    you can lock the texture and read those pixels back if you have no other
    option (but: we’re keeping a second copy of the texture in RAM, so, uh,
    don’t do this).

There isn’t any SDL function to say “make a second copy of this
texture,” because if you aren’t modifying the texture, there’s really no
sense in having two copies of it…just draw from the first texture in
both cases. If you just need a second copy because you want to change
the color or whatever, you can often fake this with various settings to
the texture.

–ryan.

Thanks to you both for your solutions.

I don’t want to be polemic or anything, but I’m really missing the point about the creation of a new separate entity for surfaces. I mean, I get it Textures are in video memory and are handled by the GPU so they’re faster and they get scaling, and rotations, and so on. But wasn’t it better to extend SDL_Surface instead of creating another separate structure?

Thanks,------------------------
Fabio.

2013/10/18 FabioF

**
Thanks to you both for your solutions.

I don’t want to be polemic or anything, but I’m really missing the point
about the creation of a new separate entity for surfaces. I mean, I get it
Textures are in video memory and are handled by the GPU so they’re faster
and they get scaling, and rotations, and so on. But wasn’t it better to
extend SDL_Surface instead of creating another separate structure?

How would you “extend” a struct that wraps a pixel array in RAM to include
something so fundamentally different as textures?
I think you’ll understand the distinction soon enough as you learn more
about graphics programming.

Jonas

A surface is basically a pixel buffer. A texture is pretty much just an
integer. You have no access to the pixels without loading it (the entire
texture) from the cpu to the GPU again. This process is slow. Basically a
surface is a texture when loaded onto the cpu. A texture is an integer
representing what the driver knows about what is on the gpu.On Oct 18, 2013 9:05 AM, “Jonas Kulla” wrote:

2013/10/18 FabioF

**
Thanks to you both for your solutions.

I don’t want to be polemic or anything, but I’m really missing the point
about the creation of a new separate entity for surfaces. I mean, I get it
Textures are in video memory and are handled by the GPU so they’re faster
and they get scaling, and rotations, and so on. But wasn’t it better to
extend SDL_Surface instead of creating another separate structure?

How would you “extend” a struct that wraps a pixel array in RAM to include
something so fundamentally different as textures?
I think you’ll understand the distinction soon enough as you learn more
about graphics programming.

Jonas


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

2013/10/18 Andre D

A surface is basically a pixel buffer. A texture is pretty much just an
integer. You have no access to the pixels without loading it (the entire
texture) from the cpu to the GPU again. This process is slow. Basically a
surface is a texture when loaded onto the cpu. A texture is an integer
representing what the driver knows about what is on the gpu.

The GLuint handle approach is just OpenGL’s convention, but yeah, you
basically don’t have direct memory access via a plain pointer
like you do with Surfaces. To be fair, you don’t have to download the
entire texture image to RAM to read single pixels of it (you could
attach an FBO to the texture and use glReadPixels with a 1x1 rect), but
it’s still bad because you’re stalling the entire render pipeline
for that. Writing single pixels is probably faster as you can render points
to the texture.

Jonas

I’m still wondering if you need multiple copies of a texture
(presumably to apply different effects and whatnot?) you do not
simply upload the texture twice (if changes are not frequent) or as a
streaming texture (if they are)?

Once you upload a texture and then free the surface, you don’t own
the pixels anymore. If you need the pixels, don’t throw them away.
Copying textures is not even always supported on renderer targets,
though it happens to work on any you’re likely to encounter. Old
versions of 3D subsystems couldn’t be counted on to do it, though.

JosephOn Thu, Oct 17, 2013 at 07:20:55AM +0000, FabioF wrote:

Hello all,
I’ve recently been porting my stuff to SDL2 and I still have doubts about Textures (but I will leave this to another post).

My question is: how do you “properly” copy a SDL_Texture?
With Sourfaces you just blit one into another, clipping the way you want. With Textures (from what I have understood) you have to define your target Texture with SDL_TEXTUREACCESS_TARGET, then bind it to a new SDL_Renderer(which has to be bound to a window) and the you can user SDL_RenderCopy() to copy the contents. It seems to me an incredible amount of work.

For instance, in an “oldstyle” 2D game. Previously in 1.2 I had a struct form my animated sprites that had a Surface as sprite sheet and another as sprite “face”. At every animation tick I would blit the current frame from the sheet into the face, modify it as needed (color mods, alpha mods, etc) and then redender it to the screen. Now I have to change my approach (or, I have to call SDL_CreateTextureFromSurface() every frame, which is bad).

What am I missing?

Thanks!


Fabio.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

Thanks Joseph, I solved it by doing what lloyd_b suggested.

It’s true I know very little of “proper” graphic programming, but I was just talking interface. Seemed more convenient to me to keep just one object, but I think I got what you all meant, Surfaces and Textures are similar in concept but very different under the trunk.

Thanks again,------------------------
Fabio.