Commit 53654196 authored by Sam Lantinga's avatar Sam Lantinga

Initial pass at shader YV12 support - doesn't quite work yet.

parent 8ecd7110
...@@ -124,9 +124,7 @@ enum ...@@ -124,9 +124,7 @@ enum
#define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF) #define SDL_BITSPERPIXEL(X) (((X) >> 8) & 0xFF)
#define SDL_BYTESPERPIXEL(X) \ #define SDL_BYTESPERPIXEL(X) \
(SDL_ISPIXELFORMAT_FOURCC(X) ? \ (SDL_ISPIXELFORMAT_FOURCC(X) ? \
((((X) == SDL_PIXELFORMAT_YV12) || \ ((((X) == SDL_PIXELFORMAT_YUY2) || \
((X) == SDL_PIXELFORMAT_IYUV) || \
((X) == SDL_PIXELFORMAT_YUY2) || \
((X) == SDL_PIXELFORMAT_UYVY) || \ ((X) == SDL_PIXELFORMAT_UYVY) || \
((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF)) ((X) == SDL_PIXELFORMAT_YVYU)) ? 2 : 1) : (((X) >> 0) & 0xFF))
......
...@@ -119,6 +119,11 @@ typedef struct ...@@ -119,6 +119,11 @@ typedef struct
void *pixels; void *pixels;
int pitch; int pitch;
SDL_Rect locked_rect; SDL_Rect locked_rect;
/* YV12 texture support */
SDL_bool yuv;
GLuint utexture;
GLuint vtexture;
} GL_TextureData; } GL_TextureData;
...@@ -292,12 +297,11 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) ...@@ -292,12 +297,11 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s", SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
data->shaders ? "ENABLED" : "DISABLED"); data->shaders ? "ENABLED" : "DISABLED");
#if 0
/* We support YV12 textures using 3 textures and a shader */ /* We support YV12 textures using 3 textures and a shader */
if (data->shaders && data->num_texture_units >= 3) { 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_YV12;
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
} }
#endif
/* Set up parameters for rendering */ /* Set up parameters for rendering */
data->blendMode = -1; data->blendMode = -1;
...@@ -372,6 +376,12 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format, ...@@ -372,6 +376,12 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
*format = GL_BGRA; *format = GL_BGRA;
*type = GL_UNSIGNED_INT_8_8_8_8_REV; *type = GL_UNSIGNED_INT_8_8_8_8_REV;
break; break;
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_IYUV:
*internalFormat = GL_LUMINANCE;
*format = GL_LUMINANCE;
*type = GL_UNSIGNED_BYTE;
break;
default: default:
return SDL_FALSE; return SDL_FALSE;
} }
...@@ -404,8 +414,15 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -404,8 +414,15 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
} }
if (texture->access == SDL_TEXTUREACCESS_STREAMING) { if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); 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) { if (!data->pixels) {
SDL_OutOfMemory(); SDL_OutOfMemory();
SDL_free(data); SDL_free(data);
...@@ -478,6 +495,41 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -478,6 +495,41 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
GL_SetError("glTexImage2D()", result); GL_SetError("glTexImage2D()", result);
return -1; 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; return 0;
} }
...@@ -500,6 +552,35 @@ GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -500,6 +552,35 @@ GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
rect->h, data->format, data->formattype, rect->h, data->format, data->formattype,
pixels); 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); renderdata->glDisable(data->type);
result = renderdata->glGetError(); result = renderdata->glGetError();
if (result != GL_NO_ERROR) { if (result != GL_NO_ERROR) {
...@@ -750,6 +831,13 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -750,6 +831,13 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
maxv *= texturedata->texh; maxv *= texturedata->texh;
data->glEnable(texturedata->type); 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); data->glBindTexture(texturedata->type, texturedata->texture);
if (texture->modMode) { if (texture->modMode) {
...@@ -762,7 +850,11 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, ...@@ -762,7 +850,11 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
} }
GL_SetBlendMode(data, texture->blendMode); GL_SetBlendMode(data, texture->blendMode);
if (texturedata->yuv) {
GL_SelectShader(data->shaders, SHADER_YV12);
} else {
GL_SelectShader(data->shaders, SHADER_RGB); GL_SelectShader(data->shaders, SHADER_RGB);
}
data->glBegin(GL_TRIANGLE_STRIP); data->glBegin(GL_TRIANGLE_STRIP);
data->glTexCoord2f(minu, minv); data->glTexCoord2f(minu, minv);
...@@ -848,6 +940,10 @@ GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) ...@@ -848,6 +940,10 @@ GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
if (data->texture) { if (data->texture) {
renderdata->glDeleteTextures(1, &data->texture); renderdata->glDeleteTextures(1, &data->texture);
} }
if (data->yuv) {
renderdata->glDeleteTextures(1, &data->utexture);
renderdata->glDeleteTextures(1, &data->vtexture);
}
if (data->pixels) { if (data->pixels) {
SDL_free(data->pixels); SDL_free(data->pixels);
} }
......
...@@ -360,7 +360,7 @@ main(int argc, char **argv) ...@@ -360,7 +360,7 @@ main(int argc, char **argv)
int fps = 12; int fps = 12;
int fpsdelay; int fpsdelay;
int nodelay = 0; int nodelay = 0;
int overlay_format = SDL_YUY2_OVERLAY; Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
int scale = 5; int scale = 5;
SDL_bool done = SDL_FALSE; SDL_bool done = SDL_FALSE;
...@@ -397,15 +397,15 @@ main(int argc, char **argv) ...@@ -397,15 +397,15 @@ main(int argc, char **argv)
} else if (strcmp(argv[1], "-format") == 0) { } else if (strcmp(argv[1], "-format") == 0) {
if (argv[2]) { if (argv[2]) {
if (!strcmp(argv[2], "YV12")) if (!strcmp(argv[2], "YV12"))
overlay_format = SDL_YV12_OVERLAY; pixel_format = SDL_PIXELFORMAT_YV12;
else if (!strcmp(argv[2], "IYUV")) else if (!strcmp(argv[2], "IYUV"))
overlay_format = SDL_IYUV_OVERLAY; pixel_format = SDL_PIXELFORMAT_IYUV;
else if (!strcmp(argv[2], "YUY2")) else if (!strcmp(argv[2], "YUY2"))
overlay_format = SDL_YUY2_OVERLAY; pixel_format = SDL_PIXELFORMAT_YUY2;
else if (!strcmp(argv[2], "UYVY")) else if (!strcmp(argv[2], "UYVY"))
overlay_format = SDL_UYVY_OVERLAY; pixel_format = SDL_PIXELFORMAT_UYVY;
else if (!strcmp(argv[2], "YVYU")) else if (!strcmp(argv[2], "YVYU"))
overlay_format = SDL_YVYU_OVERLAY; pixel_format = SDL_PIXELFORMAT_YVYU;
else { else {
fprintf(stderr, fprintf(stderr,
"The -format option %s is not recognized, see help for info.\n", "The -format option %s is not recognized, see help for info.\n",
...@@ -490,7 +490,7 @@ main(int argc, char **argv) ...@@ -490,7 +490,7 @@ main(int argc, char **argv)
quit(4); 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) { if (!MooseTexture) {
fprintf(stderr, "Couldn't set create texture: %s\n", SDL_GetError()); fprintf(stderr, "Couldn't set create texture: %s\n", SDL_GetError());
free(RawMooseData); free(RawMooseData);
...@@ -569,7 +569,7 @@ main(int argc, char **argv) ...@@ -569,7 +569,7 @@ main(int argc, char **argv)
if (!paused) { if (!paused) {
i = (i + 1) % MOOSEFRAMES_COUNT; 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_RenderClear(renderer);
SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect); SDL_RenderCopy(renderer, MooseTexture, NULL, &displayrect);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment