SDL_RenderReadPixels() now returns a surface

Fixes https://github.com/libsdl-org/SDL/issues/8977
This commit is contained in:
Sam Lantinga 2024-02-03 10:18:12 -08:00
parent ab571633d1
commit 89b9d6cbdc
22 changed files with 216 additions and 310 deletions

View file

@ -1457,74 +1457,58 @@ static int GL_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, vo
return GL_CheckError("", renderer);
}
static int GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect,
Uint32 pixel_format, void *pixels, int pitch)
static SDL_Surface *GL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
{
GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888;
void *temp_pixels;
int temp_pitch;
Uint32 format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888;
GLint internalFormat;
GLenum format, type;
Uint8 *src, *dst, *tmp;
int w, h, length, rows;
int status;
GLenum targetFormat, type;
int w, h;
SDL_Surface *surface;
GL_ActivateRenderer(renderer);
if (!convert_format(temp_format, &internalFormat, &format, &type)) {
return SDL_SetError("Texture format %s not supported by OpenGL",
SDL_GetPixelFormatName(temp_format));
if (!convert_format(format, &internalFormat, &targetFormat, &type)) {
SDL_SetError("Texture format %s not supported by OpenGL", SDL_GetPixelFormatName(format));
return NULL;
}
if (rect->w == 0 || rect->h == 0) {
return 0; /* nothing to do. */
}
temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
temp_pixels = SDL_malloc((size_t)rect->h * temp_pitch);
if (!temp_pixels) {
return -1;
surface = SDL_CreateSurface(rect->w, rect->h, format);
if (!surface) {
return NULL;
}
SDL_GetCurrentRenderOutputSize(renderer, &w, &h);
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
data->glPixelStorei(GL_PACK_ROW_LENGTH,
(temp_pitch / SDL_BYTESPERPIXEL(temp_format)));
data->glPixelStorei(GL_PACK_ROW_LENGTH, (surface->pitch / SDL_BYTESPERPIXEL(format)));
data->glReadPixels(rect->x, renderer->target ? rect->y : (h - rect->y) - rect->h,
rect->w, rect->h, format, type, temp_pixels);
rect->w, rect->h, targetFormat, type, surface->pixels);
if (GL_CheckError("glReadPixels()", renderer) < 0) {
SDL_free(temp_pixels);
return -1;
SDL_DestroySurface(surface);
return NULL;
}
/* Flip the rows to be top-down if necessary */
if (!renderer->target) {
SDL_bool isstack;
length = rect->w * SDL_BYTESPERPIXEL(temp_format);
src = (Uint8 *)temp_pixels + (rect->h - 1) * temp_pitch;
dst = (Uint8 *)temp_pixels;
tmp = SDL_small_alloc(Uint8, length, &isstack);
rows = rect->h / 2;
int length = rect->w * SDL_BYTESPERPIXEL(format);
Uint8 *src = (Uint8 *)surface->pixels + (rect->h - 1) * surface->pitch;
Uint8 *dst = (Uint8 *)surface->pixels;
Uint8 *tmp = SDL_small_alloc(Uint8, length, &isstack);
int rows = rect->h / 2;
while (rows--) {
SDL_memcpy(tmp, dst, length);
SDL_memcpy(dst, src, length);
SDL_memcpy(src, tmp, length);
dst += temp_pitch;
src -= temp_pitch;
dst += surface->pitch;
src -= surface->pitch;
}
SDL_small_free(tmp, isstack);
}
status = SDL_ConvertPixels(rect->w, rect->h,
temp_format, temp_pixels, temp_pitch,
pixel_format, pixels, pitch);
SDL_free(temp_pixels);
return status;
return surface;
}
static int GL_RenderPresent(SDL_Renderer *renderer)