mirror of https://github.com/encounter/SDL.git
Fixed bug 2595 - Padded, non-contiguous YUV does not display correctly using OpenGL ES 2.0 renderer
Alvin The new OpenGL ES 2.0 YUV Texture support does not correctly display padded, non-contiguous YUV data. I am using SDL2 95bd3d33482e (as provided by 'hg id --id') from Mercurial. The YUV data I am using is provided by the FFMPEG family of libraries. According to FFMPEG's documentation, "The linesize [pitch] may be larger than the size of usable data -- there may be extra padding present for performance reasons." The dimensions of the video file that I am using are 480x360. What I get from FFMPEG is a Ypitch of 512, and Upitch and Vpitch are both 256. When I pack new Y, U and V buffers with only the "usable" data (Ypitch is 480 and Upitch and Vpitch are both 240), and use those new buffers, the image is display correctly. It appears that the Ypitch, Upitch and Vpitch parameters are not being used by SDL_UpdateYUVTexture(). I use SDL_PIXELFORMAT_YV12 for my YUV texture, however, the same results are seen when I use SDL_PIXELFORMAT_IYUV. Not sure if this is related or not, but when I render the YUV texture (padded and unpadded) to a RGB24 texture, the resulting image is greyscale (or could by just the Y channel). The URL field for this bug entry is set to my email (SDL mailing list archive) which includes an example image of what I see when rendering padded, non-contiguous YUV data.
This commit is contained in:
parent
41a39837ca
commit
e8f8e6727a
|
@ -580,16 +580,45 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
return GL_CheckError("", renderer);
|
return GL_CheckError("", renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES2_TexSubImage2D(GLES2_DriverContext *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
|
||||||
|
{
|
||||||
|
Uint8 *blob = NULL;
|
||||||
|
Uint8 *src;
|
||||||
|
int src_pitch;
|
||||||
|
int y;
|
||||||
|
|
||||||
|
/* Reformat the texture data into a tightly packed array */
|
||||||
|
src_pitch = width * bpp;
|
||||||
|
src = (Uint8 *)data;
|
||||||
|
if (pitch != src_pitch) {
|
||||||
|
blob = (Uint8 *)SDL_malloc(src_pitch * height);
|
||||||
|
if (!blob) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
src = blob;
|
||||||
|
for (y = 0; y < height; ++y)
|
||||||
|
{
|
||||||
|
SDL_memcpy(src, pixels, src_pitch);
|
||||||
|
src += src_pitch;
|
||||||
|
pixels = (Uint8 *)pixels + pitch;
|
||||||
|
}
|
||||||
|
src = blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
|
||||||
|
if (blob) {
|
||||||
|
SDL_free(blob);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
|
GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
|
||||||
const void *pixels, int pitch)
|
const void *pixels, int pitch)
|
||||||
{
|
{
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||||
Uint8 *blob = NULL;
|
|
||||||
Uint8 *src;
|
|
||||||
int srcPitch;
|
|
||||||
int y;
|
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
@ -597,36 +626,16 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
if (rect->w <= 0 || rect->h <= 0)
|
if (rect->w <= 0 || rect->h <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reformat the texture data into a tightly packed array */
|
|
||||||
srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format);
|
|
||||||
src = (Uint8 *)pixels;
|
|
||||||
if (pitch != srcPitch) {
|
|
||||||
blob = (Uint8 *)SDL_malloc(srcPitch * rect->h);
|
|
||||||
if (!blob) {
|
|
||||||
return SDL_OutOfMemory();
|
|
||||||
}
|
|
||||||
src = blob;
|
|
||||||
for (y = 0; y < rect->h; ++y)
|
|
||||||
{
|
|
||||||
SDL_memcpy(src, pixels, srcPitch);
|
|
||||||
src += srcPitch;
|
|
||||||
pixels = (Uint8 *)pixels + pitch;
|
|
||||||
}
|
|
||||||
src = blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a texture subimage with the supplied data */
|
/* Create a texture subimage with the supplied data */
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||||
data->glTexSubImage2D(tdata->texture_type,
|
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||||
0,
|
|
||||||
rect->x,
|
rect->x,
|
||||||
rect->y,
|
rect->y,
|
||||||
rect->w,
|
rect->w,
|
||||||
rect->h,
|
rect->h,
|
||||||
tdata->pixel_format,
|
tdata->pixel_format,
|
||||||
tdata->pixel_type,
|
tdata->pixel_type,
|
||||||
src);
|
pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
|
||||||
SDL_free(blob);
|
|
||||||
|
|
||||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||||
}
|
}
|
||||||
|
@ -641,39 +650,41 @@ GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||||
|
|
||||||
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
/* Bail out if we're supposed to update an empty rectangle */
|
||||||
|
if (rect->w <= 0 || rect->h <= 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||||
data->glTexSubImage2D(tdata->texture_type,
|
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||||
0,
|
|
||||||
rect->x,
|
rect->x,
|
||||||
rect->y,
|
rect->y,
|
||||||
rect->w / 2,
|
rect->w / 2,
|
||||||
rect->h / 2,
|
rect->h / 2,
|
||||||
tdata->pixel_format,
|
tdata->pixel_format,
|
||||||
tdata->pixel_type,
|
tdata->pixel_type,
|
||||||
Vplane);
|
Vplane, Vpitch, 1);
|
||||||
|
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||||
data->glTexSubImage2D(tdata->texture_type,
|
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||||
0,
|
|
||||||
rect->x,
|
rect->x,
|
||||||
rect->y,
|
rect->y,
|
||||||
rect->w / 2,
|
rect->w / 2,
|
||||||
rect->h / 2,
|
rect->h / 2,
|
||||||
tdata->pixel_format,
|
tdata->pixel_format,
|
||||||
tdata->pixel_type,
|
tdata->pixel_type,
|
||||||
Uplane);
|
Uplane, Upitch, 1);
|
||||||
|
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||||
data->glTexSubImage2D(tdata->texture_type,
|
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||||
0,
|
|
||||||
rect->x,
|
rect->x,
|
||||||
rect->y,
|
rect->y,
|
||||||
rect->w,
|
rect->w,
|
||||||
rect->h,
|
rect->h,
|
||||||
tdata->pixel_format,
|
tdata->pixel_format,
|
||||||
tdata->pixel_type,
|
tdata->pixel_type,
|
||||||
Yplane);
|
Vplane, Vpitch, 1);
|
||||||
|
|
||||||
|
|
||||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue