SDL_Texture *screen = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888,
SDL_TEXTUREACCESS_TARGET, 800, 800);
I want to copy this screen
texture to another texture called temp
.
I tried the following code SDL_Texture *temp = screen;
but when I changed temp
, screen
was also changed since they point to the same memory address.
Is there any way to copy the texture without changing the source texture?
You can use the following:
SDL_Texture* DuplicateTexture(SDL_Texture* tex, SDL_Renderer* renderer) {
Uint32 format;
int w, h;
SDL_BlendMode blendmode;
SDL_Texture* renderTarget;
SDL_Texture* newTex;
// Get all properties from the texture we are duplicating
SDL_QueryTexture(tex, &format, NULL, &w, &h);
SDL_GetTextureBlendMode(tex, &blendmode);
// Save the current rendering target (will be NULL if it is the current window)
renderTarget = SDL_GetRenderTarget(renderer);
// Create a new texture with the same properties as the one we are duplicating
newTex = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, w, h);
// Set its blending mode and make it the render target
SDL_SetTextureBlendMode(newTex, SDL_BLENDMODE_NONE);
SDL_SetRenderTarget(renderer, newTex);
// Render the full original texture onto the new one
SDL_RenderCopy(renderer, tex, NULL, NULL);
// Change the blending mode of the new texture to the same as the original one
SDL_SetTextureBlendMode(newTex, blendmode);
// Restore the render target
SDL_SetRenderTarget(renderer, renderTarget);
// Return the new texture
return newTex;
}
Basically, this function creates a new texture with the same properties as the old one, and sets the new texture as the render target. Then it renders the old texture onto it, and sets the render target back to what it was.
Unfortunately, this is as close as you can get, and it features the following issue:
SDL_TEXTUREACCESS_TARGET
access mode. It is mandatory to be able to render other textures onto it, and at the time of writing, there are no way to change an SDL_Texture
's access mode after it has been created.SDL_RENDERER_TARGETTEXTURE
bit in the flags of your renderer's SDL_RendererInfo
to see if render targets are supported.An SDL_Texture
, according to the documentation (archive), is:
A structure that contains an efficient, driver-specific representation of pixel data.
Which basically means that these are NOT supposed to be messed with. Once you create an SDL_Texture
, either you render it, or you render things onto it. That's it.
On the other hand, check out the documentation for SDL_Surface
(archive):
A structure that contains a collection of pixels used in software blitting.
These ones are made to be messed with. They are handled by software and exist for the sole and only reason of you, the programmer, to do all sorts of things with it, like editing its pixels, blitting it on other surfaces, etc.
This is what you should focus on: if you want to edit pixel data or do any sort of modification to something that you then plan to render on screen, then do it in an SDL_Surface
. And only when you are done making your edits, convert the SDL_Surface
to a SDL_Texture
using the SDL_CreateTextureFromSurface
(archive) function.
Besides, as I mentionned, you can blit surfaces on top of other surfaces, just like you can render textures on top of other textures. So it's not like you'd loose anything by using surfaces, besides some performance of course, as SDL_Texture
s are hardware-accelerated whereas SDL_Surface
s aren't.
If you want to go more technical about this, please give a look at the excellent answer to What is the point of an SDL2 Texture?
SDL_Texture
s.So make sure that if you do it anyway, it is actually justified and only way to make your project work.