--- a/src/render/opengl/SDL_render_gl.c Fri Feb 11 23:02:35 2011 -0800
+++ b/src/render/opengl/SDL_render_gl.c Sat Feb 12 00:25:02 2011 -0800
@@ -119,6 +119,11 @@
void *pixels;
int pitch;
SDL_Rect locked_rect;
+
+ /* YV12 texture support */
+ SDL_bool yuv;
+ GLuint utexture;
+ GLuint vtexture;
} GL_TextureData;
@@ -292,12 +297,11 @@
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
data->shaders ? "ENABLED" : "DISABLED");
-#if 0
/* We support YV12 textures using 3 textures and a shader */
if (data->shaders && data->num_texture_units >= 3) {
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
+ renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
}
-#endif
/* Set up parameters for rendering */
data->blendMode = -1;
@@ -372,6 +376,12 @@
*format = GL_BGRA;
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
break;
+ case SDL_PIXELFORMAT_YV12:
+ case SDL_PIXELFORMAT_IYUV:
+ *internalFormat = GL_LUMINANCE;
+ *format = GL_LUMINANCE;
+ *type = GL_UNSIGNED_BYTE;
+ break;
default:
return SDL_FALSE;
}
@@ -404,8 +414,15 @@
}
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
+ size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
- data->pixels = SDL_malloc(texture->h * data->pitch);
+ size = texture->h * data->pitch;
+ if (texture->format == SDL_PIXELFORMAT_YV12 ||
+ texture->format == SDL_PIXELFORMAT_IYUV) {
+ /* Need to add size for the U and V planes */
+ size += (2 * (texture->h * data->pitch) / 4);
+ }
+ data->pixels = SDL_malloc(size);
if (!data->pixels) {
SDL_OutOfMemory();
SDL_free(data);
@@ -478,6 +495,41 @@
GL_SetError("glTexImage2D()", result);
return -1;
}
+
+ if (texture->format == SDL_PIXELFORMAT_YV12 ||
+ texture->format == SDL_PIXELFORMAT_IYUV) {
+ data->yuv = SDL_TRUE;
+
+ renderdata->glGenTextures(1, &data->utexture);
+ renderdata->glGenTextures(1, &data->vtexture);
+ renderdata->glEnable(data->type);
+
+ renderdata->glBindTexture(data->type, data->utexture);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+ renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
+ texture_h/2, 0, format, type, NULL);
+
+ renderdata->glBindTexture(data->type, data->vtexture);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
+ GL_LINEAR);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
+ GL_CLAMP_TO_EDGE);
+ renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
+ GL_CLAMP_TO_EDGE);
+ renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w/2,
+ texture_h/2, 0, format, type, NULL);
+
+ renderdata->glDisable(data->type);
+ }
return 0;
}
@@ -500,6 +552,35 @@
renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
rect->h, data->format, data->formattype,
pixels);
+ if (data->yuv) {
+ /* Skip to the top of the next texture */
+ const void *top = (const void*)((const Uint8*)pixels + (texture->h-rect->y) * pitch - rect->x);
+
+ /* Skip to the correct offset into the next texture */
+ pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2);
+ if (texture->format == SDL_PIXELFORMAT_YV12) {
+ renderdata->glBindTexture(data->type, data->vtexture);
+ } else {
+ renderdata->glBindTexture(data->type, data->utexture);
+ }
+ renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
+ rect->w/2, rect->h/2,
+ data->format, data->formattype, pixels);
+
+ /* Skip to the top of the next texture */
+ top = (const void*)((const Uint8*)top + (texture->h * pitch)/4);
+
+ /* Skip to the correct offset into the next texture */
+ pixels = (const void*)((const Uint8*)top + (rect->y / 2) * pitch + rect->x / 2);
+ if (texture->format == SDL_PIXELFORMAT_YV12) {
+ renderdata->glBindTexture(data->type, data->utexture);
+ } else {
+ renderdata->glBindTexture(data->type, data->vtexture);
+ }
+ renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
+ rect->w/2, rect->h/2,
+ data->format, data->formattype, pixels);
+ }
renderdata->glDisable(data->type);
result = renderdata->glGetError();
if (result != GL_NO_ERROR) {
@@ -750,6 +831,13 @@
maxv *= texturedata->texh;
data->glEnable(texturedata->type);
+ if (texturedata->yuv) {
+ data->glActiveTextureARB(GL_TEXTURE2_ARB);
+ data->glBindTexture(texturedata->type, texturedata->vtexture);
+ data->glActiveTextureARB(GL_TEXTURE1_ARB);
+ data->glBindTexture(texturedata->type, texturedata->utexture);
+ data->glActiveTextureARB(GL_TEXTURE0_ARB);
+ }
data->glBindTexture(texturedata->type, texturedata->texture);
if (texture->modMode) {
@@ -762,7 +850,11 @@
}
GL_SetBlendMode(data, texture->blendMode);
- GL_SelectShader(data->shaders, SHADER_RGB);
+ if (texturedata->yuv) {
+ GL_SelectShader(data->shaders, SHADER_YV12);
+ } else {
+ GL_SelectShader(data->shaders, SHADER_RGB);
+ }
data->glBegin(GL_TRIANGLE_STRIP);
data->glTexCoord2f(minu, minv);
@@ -848,6 +940,10 @@
if (data->texture) {
renderdata->glDeleteTextures(1, &data->texture);
}
+ if (data->yuv) {
+ renderdata->glDeleteTextures(1, &data->utexture);
+ renderdata->glDeleteTextures(1, &data->vtexture);
+ }
if (data->pixels) {
SDL_free(data->pixels);
}
--- a/test/testoverlay2.c Fri Feb 11 23:02:35 2011 -0800
+++ b/test/testoverlay2.c Sat Feb 12 00:25:02 2011 -0800
@@ -360,7 +360,7 @@
int fps = 12;
int fpsdelay;
int nodelay = 0;
- int overlay_format = SDL_YUY2_OVERLAY;
+ Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
int scale = 5;
SDL_bool done = SDL_FALSE;
@@ -397,15 +397,15 @@
} else if (strcmp(argv[1], "-format") == 0) {
if (argv[2]) {
if (!strcmp(argv[2], "YV12"))
- overlay_format = SDL_YV12_OVERLAY;
+ pixel_format = SDL_PIXELFORMAT_YV12;
else if (!strcmp(argv[2], "IYUV"))
- overlay_format = SDL_IYUV_OVERLAY;
+ pixel_format = SDL_PIXELFORMAT_IYUV;
else if (!strcmp(argv[2], "YUY2"))
- overlay_format = SDL_YUY2_OVERLAY;
+ pixel_format = SDL_PIXELFORMAT_YUY2;
else if (!strcmp(argv[2], "UYVY"))
- overlay_format = SDL_UYVY_OVERLAY;
+ pixel_format = SDL_PIXELFORMAT_UYVY;
else if (!strcmp(argv[2], "YVYU"))
- overlay_format = SDL_YVYU_OVERLAY;
+ pixel_format = SDL_PIXELFORMAT_YVYU;
else {
fprintf(stderr,
"The -format option %s is not recognized, see help for info.\n",
@@ -490,7 +490,7 @@
quit(4);
}
- MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H);
+ MooseTexture = SDL_CreateTexture(renderer, pixel_format, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H);
if (!MooseTexture) {
fprintf(stderr, "Couldn't set create texture: %s\n", SDL_GetError());
free(RawMooseData);
@@ -569,7 +569,7 @@
if (!paused) {
i = (i + 1) % MOOSEFRAMES_COUNT;
- SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*2);
+ SDL_UpdateTexture(MooseTexture, NULL, MooseFrame[i], MOOSEPIC_W*SDL_BYTESPERPIXEL(pixel_format));
}
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect);