Setting a renderer's target

I’ve been trying to change the rendering target of my renderer to a texture so that I can draw on it separately from the screen, but all my attempts to calling SDL_SetRenderTarget have failed.

The first issue I was having is that if I call SDL_GetError() before I even try to set the target, it says ‘Invalid Texture’. I’m not sure where this happens, or why it’s there because the texture should exist (I used cout and it displayed a memory address, I admit this is probably terrible checking, but I’m not sure what else to do).
Calling SDL_SetRenderTarger returns -1, and does not change the error message returned by SDL_GetError (further reasoning to me believing the texture does exist.

Is there something I’m supposed to do before calling SDL_SetRenderTarget?

Code:
void Bitmap::draw_rect(int x, int y, int w, int h, int r, int g, int b, int a){
SDL_SetRenderDrawColor(ren, r, g, b, a);
cout << SDL_SetRenderTarget(ren, bitmap) << endl;
SDL_Rect rect = {x, y, w, h};
SDL_RenderFillRect(ren, &rect);
}

‘bitmap’ is defined as ‘SDL_Texture *bitmap’, and ‘ren’ is my renderer.
Am I missing something I’m supposed to be doing? Is anyone else having issues with this? Is it me, or is it broken itself?

Thank you to anyone that can try to help solve this.

Did you call SDL_CreateTexture() to create the texture?

Yes, I have.

Code:
int Bitmap::Create(int w, int h, int access = SDL_TEXTUREACCESS_STREAMING | SDL_TEXTUREACCESS_TARGET){
SDL_RendererInfo *info = new SDL_RendererInfo;
SDL_GetRendererInfo(ren, info);
Uint32 format = 0;
if (info->num_texture_formats > 0){
format = info->texture_formats[0];
}
bitmap = SDL_CreateTexture(ren, format, access, w, h);
Bitmap::w = w; // These are just properties of the texture that I’m storing for refernce later.
Bitmap::h = h;
Bitmap::access = access;
return 0;
}

It does return a memory address for the texture, so I believe it works fine.

I don’t see the problem. I have a texture which I compost a few layers onto
before drawing it in the window and I don’t do anything other than create
the renderer, create the texture with the proper access, and set the
target. I pass an immediate value for the format to SDL_CreateTexture()
(e.g. e.g. SDL_CreateTexture(ren, SDL_PIXELFORMAT_RGBA8888, access, w, h)),
but other than that I’m doing pretty much what you’re doing. Something
going wrong upstream though if you’re getting the ‘Invalid Texture’ error,
so I can only suggest you find out exactly when that happens.On Tue, Nov 5, 2013 at 7:29 AM, Zalerinian wrote:

Yes, I have.

Code:

int Bitmap::Create(int w, int h, int access =
SDL_TEXTUREACCESS_STREAMING | SDL_TEXTUREACCESS_TARGET){
SDL_RendererInfo *info = new SDL_RendererInfo;
SDL_GetRendererInfo(ren, info);
Uint32 format = 0;
if (info->num_texture_formats > 0){
format = info->texture_formats[0];
}
bitmap = SDL_CreateTexture(ren, format, access, w, h);
Bitmap::w = w; // These are just properties of the texture that I’m
storing for refernce later.
Bitmap::h = h;
Bitmap::access = access;
return 0;
}

It does return a memory address for the texture, so I believe it works
fine.


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

A quick glance at the implementation code reveals the problem.? The
"access" parameter is not a bitmask.? You only want to pass
SDL_TEXTUREACCESS_TARGET here.

MasonOn Tuesday, November 5, 2013 4:29 AM, Zalerinian wrote:

Yes, I have.

Code:

int Bitmap::Create(int w, int h, int access = SDL_TEXTUREACCESS_STREAMING | SDL_TEXTUREACCESS_TARGET){
? SDL_RendererInfo *info = new SDL_RendererInfo;
? SDL_GetRendererInfo(ren, info);
? Uint32 format = 0;
? if (info->num_texture_formats > 0){
? ? format = info->texture_formats[0];
? }
? bitmap = SDL_CreateTexture(ren, format, access, w, h);
? Bitmap::w = w; // These are just properties of the texture that I’m storing for refernce later.
? Bitmap::h = h;
? Bitmap::access = access;
? return 0;
}

It does return a memory address for the texture, so I believe it works fine.


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

@Mason I tried your suggestion, but it still has the same error.

@opcow: I’ve found where the problem occurs, but I’m not exactly sure why it does.

Window.cpp:

Code:
int Window::CreateWindow(int x, int y, int w, int h){
cout << "Pre Sprite: " << SDL_GetError() << endl;
window = Sprite(x, y, w, h, 2);
cout << "Post Sprite: " << SDL_GetError() << endl;
return 0;
}

Sprite.cpp:

Code:
Sprite::Sprite(int x, int y, int w, int h, int z){
cout << "Pre Bitmap: " << SDL_GetError() << endl;
bitmap = Bitmap(w, h);
rect = {x, y, w, h};
Sprite::z = z;
cout << "Pre push: " << SDL_GetError() << endl;
sprites.push_back(*this);
cout << "Post Push: " << SDL_GetError() << endl;
}

‘rect’ is an SDL_Rect, and ‘bitmap’ is a Bitmap object of my own (see the ‘create’ method (called by the constructor to actually make the class) above).

Console output:

Code:
Pre Sprite:
Pre Bitmap:
Pre push:
Post Push:
Post Sprite: Invalid texture
Post Window: Invalid texture
-1 // The return value of the SDL_SetRenderTarget call

Why would it magically get an error between pushing the sprite to a list (for updating later), and then exiting the constructor. Could it be an issue with the window = Sprite() line?

I’m going to try messing around a bit with pointers to see if anything gets fixed.

sprites.push_back(*this);

You are copying complex objects and creating temporary Sprite/Bitmap
objects as intermediate step doing something like this.

I suggest you to use vector of pointers or smart pointers or (harder) to
build custom copy operators and a default constructor, otherwise it’s
almost sure the default copy operation of Sprite and Bitmap will break
somehow the objects contained inside the class (probably SDL_Texture *).–
Bye,
Gabry

I had forgotten to mention that ‘sprites’ is a list, not an array. Would it still be better to use a vector for holding objects of the Sprite class (I think it also may be better to store them as pointers, rather than copying the entire memory space, for increased performance), or is a list fine for this?