SDL_RenderReadPixels always returns black rectangle

Hi,

I am using SDL2.0 (tried also with the latest 2.0.1) and I am unable to make a “screenshot”. The method SDL_RenderReadPixels fills the pixel buffer with 0’s.

I believe that I’ve tried everything possible and triple checked that everything has been properly set. In debug mode, I’ve verified, that all parameters are there. One of my (thousands of testing) code versions is here:

Code:

SDL_Surface* surface = NULL;
surface = SDL_GetWindowSurface(m_Win); //m_Win contains current window
if (!surface) return NULL;

unsigned char * pixels = new unsigned char[surface->w * surface->h * surface->format->BytesPerPixel];
if (pixels == 0) return NULL;

if (SDL_RenderReadPixels(GetSdlRenderer(), &surface->clip_rect, surface->format->format, pixels, surface->w * surface->format->BytesPerPixel) != 0) //GetSdlRenderer() is verified to return proper renderer
{
SDL_GetError();
return NULL;
}

/* DEBUG to see if ANYTHINGt actually works. It doesn't...

int dirtyTest = 0;
for (int x=0;x<surface->w * surface->h * surface->format->BytesPerPixel;x++)
{
	if (pixels[x] !=0)
	{
		dirtyTest++;
	}
}

dirtyTest++; // breakpoint line - always 0

Any help would be greatly appreciated!

Thanks,
Jan

Never mind. It was a double buffer issue. Sorry about confusion.

Wait… Are you using GetWindowSurface() and renderer? I’m not sure of the current state but I remember reading a while back that this is a bad idea.

– Aggelos Kolaitis
– The SDL Utility library (http://bitbucket.org/sdlu/sdlu)On 9 ??? 2014, at 6:02 ?.?., “metamorphium” <jan.kavan at cbe-software.com> wrote:

Never mind. It was a double buffer issue. Sorry about confusion.


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

Ended up here via Google and adding what I’ve learned in case it helps others. I’m noticing that SDL_RenderReadPixels seems to always read the previous buffer (and thus on the first frame, results in a black image), not the one that’s currently on the screen.

This makes sense because SDL_RenderPresent draws what’s currently in the main buffer to the screen, then the main buffer is swapped to become the back buffer. So if you call SDL_RenderReadPixels after calling SDL_RenderPresent you’ll be rendering not what was just written to the screen but whatever was in the back buffer when you called SDL_RenderPresent (because that back buffer is now the main buffer). Probably what you’ll get is whatever content was in the previous frame, or a black screen if you’re calling SDL_RenderReadPixels right after your very first SDL_RenderPresent call. This is probably not a big deal if you’re constantly pushing frames, but took a little time for me to figure out.

I would prefer to say that you might get anything at all (or nothing) because the backbuffer is explicitly documented to be invalid after SDL_RenderPresent().

Yep definitely. I wonder if there should be a note added to the SDL_RenderReadPixels() method about not returning what you’d expect if you call it after SDL_RenderPresent() but before drawing. For it to not potentially return garbage, you need to call it only after drawing AND before SDL_RenderPresent() which seems like a very specific requirement.

Most people probably don’t notice since the back buffer isn’t actually cleared or otherwise corrupted from what I’ve seen, and if you’re calling SDL_RenderPresent() at any meaningful framerate, getting the previous frame is probably fine.