The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
Possible bug with copying textures to render targets? How do
Ivan Rubinson
Guest

Objective:

Create a copy of a texture.


Method:

Create a new texture with SDL_CreateTexture, given parameters that are queried from the other texture.

Set render target to new texture.

Perform an SDL_RenderCopy from the other texture.


Expected behaviour:

Both textures are of the same size, with the same content.



Actual behaviour:

The new texture is the size of the renderer (it seems).

Code:

Uint32 fmt;
int acs;

int w;
int h;

SDL_QueryTexture(original, &fmt, &acs, &w, &w);

SDL_Texture* copy_texture = SDL_CreateTexture(renderer, fmt, acs, w, h);

SDL_Texture* original_target = SDL_GetRenderTarget(renderer);

SDL_SetRenderTarget(renderer, copy_texture);

SDL_RenderCopy(renderer, original, nullptr, nullptr);

SDL_SetRenderTarget(renderer, original_target);

SDL_Rect dst;
dst.x = 0;
dst.y = 0;

dst.w = 128;
dst.h = 16;

SDL_RenderCopy(renderer, copy_texture, nullptr, &dst);
SDL_RenderPresent(renderer);


Maybe something's fubar with the texture access flags. In which case, I have no idea how to make exact copies of textures.
lorin


Joined: 27 Dec 2010
Posts: 17
Hi,
I suppose you have to use SDL_TEXTUREACCESS_TARGET as access flag in SDL_CreateTexture function.

Code:

SDL_CreateTexture(renderer, fmt, SDL_TEXTUREACCESS_TARGET, w, h);
Possible bug with copying textures to render targets? How do
Ivan Rubinson
Guest

Yeah, I realize. However, this means that the new texture is not an exact copy.



On Fri, Apr 18, 2014 at 7:15 PM, lorin wrote:
Quote:
Hi,
I suppose you have to use SDL_TEXTUREACCESS_TARGET as access flag in SDL_CreateTexture function.




Code:


SDL_CreateTexture(renderer, fmt, SDL_TEXTUREACCESS_TARGET, w, h);







I'm SDL newbie


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

lorin


Joined: 27 Dec 2010
Posts: 17
I do not think copying of Textures is a good idea at all. They are (as far as I know) stored somewhere on GPU memory. They are designed to fast rendering, but not to access or change.
You always can set access flag SDL_TEXTUREACCESS_STREAMING to texture. In that case pixels data are stored at RAM memory ( AFAIK ) and you can easily edit it by SDL_LockTexture and SDL_UnlockTexture.

On the other hand, I would recomend to create new Texture from SDL_Surface or whatever you load your graphics data from.

PS: I think there is a way how to copy texture.
SDL_QueryTexture - get info about original texture
SDL_CreateTexture - with flag TARGET (call it target texture)
SDL_SetRenderTarget - set it to target texture
SDL_RenderCopy - Render original to target texture
SDL_SetRenderTarget - reset it to default
SDL_RenderReadPixels - Read pixels from target texture
SDL_CreateTexture - Create copy of texture with pixels data from ReadPixels
Possible bug with copying textures to render targets? How do
Ivan Rubinson
Guest

Why read pixels from the target texture in the end?
Also, you can't give SDL_CreateTexture a pixels pointer. Maybe you mean SDL_UpdateTexture?

Why do a render copy if later you do an SDL_UpdateTexture?



I had some issues figuring out what "pitch" is and how to get it. Turns out that you use SDL_LockTexture for that. Also, you get the pixels the same way.

So no need for renderer hacks with targets and reads. A bit counter-intiuitive though.


It still doesn't work though:
    Uint32 other_format;
    int other_access;
    int other_w;
    int other_h;
    SDL_QueryTexture(other, &other_format, &other_access, &other_w, &other_h);
          
    SDL_Texture* texture  = SDL_CreateTexture(renderer, other_format, other_access, other_w, other_h);
   
    int* other_pixels;
    int  other_pitch;
    SDL_LockTexture(other, nullptr, (void**)&other_pixels, &other_pitch);
    int* pixels;
    int  pitch;
    SDL_LockTexture(texture, nullptr, (void**)&pixels, &pitch);
    for (int i = 0; i < pitch * other_h; ++i)
    {
        pixels[i] = other_pixels[i];
    }
    SDL_UnlockTexture(texture);
    SDL_UnlockTexture(other);


On Sun, Apr 20, 2014 at 7:18 PM, lorin wrote:
Quote:
I do not think copying of Textures is a good idea at all. They are (as far as I know) stored somewhere on GPU memory. They are designed to fast rendering, but not to access or change.
You always can set access flag SDL_TEXTUREACCESS_STREAMING to texture. In that case pixels data are stored at RAM memory ( AFAIK ) and you can easily edit it by SDL_LockTexture and SDL_UnlockTexture.

On the other hand, I would recomend to create new Texture from SDL_Surface or whatever you load your graphics data from.

PS: I think there is a way how to copy texture.
SDL_QueryTexture - get info about original texture
SDL_CreateTexture - with flag TARGET (call it target texture)
SDL_SetRenderTarget - set it to target texture
SDL_RenderCopy - Render original to target texture
SDL_SetRenderTarget - reset it to default
SDL_RenderReadPixels - Read pixels from target texture
SDL_CreateTexture - Create copy of texture with pixels data from ReadPixels



I'm SDL newbie


_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

lorin


Joined: 27 Dec 2010
Posts: 17
I ment something like this by pseudocode posted last time. It is working, however returned texture is 180 degrees rotated. Smile
Nathaniel J Fries


Joined: 30 Mar 2010
Posts: 444
Only reason I can see to copy a texture is renderer change.
Possible bug with copying textures to render targets? How do
Jonas Kulla
Guest

2014-04-20 18:18 GMT+02:00 lorin:
Quote:
I do not think copying of Textures is a good idea at all. They are (as far as I know) stored somewhere on GPU memory. They are designed to fast rendering, but not to access or change.
You always can set access flag SDL_TEXTUREACCESS_STREAMING to texture. In that case pixels data are stored at RAM memory ( AFAIK ) and you can easily edit it by SDL_LockTexture and SDL_UnlockTexture. 





'SDL_Lock/UnlockTexture' is an abstraction of what one would call
"mapping GPU memory into client space"; you're still (supposedly) writing directly to
video ram. In the D3D backend, this translates to an actual implementation call which
I think does this mapping (I don't know too much about D3D though), whereas for the
GL backends, this feature is just emulated, ie. SDL gives you a pointer to a dumb
buffer allocated in RAM, and upon the Unlock call just UpdateTexture's the whole
thing back into the native texture object.
This is why you cannot expect the pointer returned by LockTexture to contain any
data representative of what's actually in the texture (the documentation will tell you
the same).


Here's more on the D3D part (which SDL's locking is based on):
[url=http://msdn.microsoft.com/en-us/library/windows/desktop/bb205913(v=vs.85).aspx]http://msdn.microsoft.com/en-us/library/windows/desktop/bb205913(v=vs.85).aspx[/url]

[url=http://msdn.microsoft.com/en-us/library/windows/desktop/bb172231(v=vs.85).aspx]http://msdn.microsoft.com/en-us/library/windows/desktop/bb172231(v=vs.85).aspx[/url]