mirror of https://github.com/encounter/SDL.git
Added NV12 and NV21 texture support for OpenGL and OpenGL ES 2.0 renderers
This commit is contained in:
parent
6299daecba
commit
6fef39d6b8
|
@ -248,7 +248,11 @@ enum
|
||||||
SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
|
SDL_PIXELFORMAT_UYVY = /**< Packed mode: U0+Y0+V0+Y1 (1 plane) */
|
||||||
SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
|
SDL_DEFINE_PIXELFOURCC('U', 'Y', 'V', 'Y'),
|
||||||
SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
|
SDL_PIXELFORMAT_YVYU = /**< Packed mode: Y0+V0+Y1+U0 (1 plane) */
|
||||||
SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U')
|
SDL_DEFINE_PIXELFOURCC('Y', 'V', 'Y', 'U'),
|
||||||
|
SDL_PIXELFORMAT_NV12 = /**< Planar mode: Y + U/V interleaved (2 planes) */
|
||||||
|
SDL_DEFINE_PIXELFOURCC('N', 'V', '1', '2'),
|
||||||
|
SDL_PIXELFORMAT_NV21 = /**< Planar mode: Y + V/U interleaved (2 planes) */
|
||||||
|
SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1')
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SDL_Color
|
typedef struct SDL_Color
|
||||||
|
|
|
@ -164,8 +164,9 @@ typedef struct
|
||||||
int pitch;
|
int pitch;
|
||||||
SDL_Rect locked_rect;
|
SDL_Rect locked_rect;
|
||||||
|
|
||||||
/* YV12 texture support */
|
/* YUV texture support */
|
||||||
SDL_bool yuv;
|
SDL_bool yuv;
|
||||||
|
SDL_bool nv12;
|
||||||
GLuint utexture;
|
GLuint utexture;
|
||||||
GLuint vtexture;
|
GLuint vtexture;
|
||||||
|
|
||||||
|
@ -531,6 +532,8 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
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;
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
||||||
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
|
||||||
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __MACOSX__
|
#ifdef __MACOSX__
|
||||||
|
@ -611,6 +614,8 @@ convert_format(GL_RenderData *renderdata, Uint32 pixel_format,
|
||||||
break;
|
break;
|
||||||
case SDL_PIXELFORMAT_YV12:
|
case SDL_PIXELFORMAT_YV12:
|
||||||
case SDL_PIXELFORMAT_IYUV:
|
case SDL_PIXELFORMAT_IYUV:
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
case SDL_PIXELFORMAT_NV21:
|
||||||
*internalFormat = GL_LUMINANCE;
|
*internalFormat = GL_LUMINANCE;
|
||||||
*format = GL_LUMINANCE;
|
*format = GL_LUMINANCE;
|
||||||
*type = GL_UNSIGNED_BYTE;
|
*type = GL_UNSIGNED_BYTE;
|
||||||
|
@ -672,6 +677,11 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
/* Need to add size for the U and V planes */
|
/* Need to add size for the U and V planes */
|
||||||
size += (2 * (texture->h * data->pitch) / 4);
|
size += (2 * (texture->h * data->pitch) / 4);
|
||||||
}
|
}
|
||||||
|
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||||
|
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||||
|
/* Need to add size for the U/V plane */
|
||||||
|
size += ((texture->h * data->pitch) / 2);
|
||||||
|
}
|
||||||
data->pixels = SDL_calloc(1, size);
|
data->pixels = SDL_calloc(1, size);
|
||||||
if (!data->pixels) {
|
if (!data->pixels) {
|
||||||
SDL_free(data);
|
SDL_free(data);
|
||||||
|
@ -801,6 +811,27 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
renderdata->glDisable(data->type);
|
renderdata->glDisable(data->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (texture->format == SDL_PIXELFORMAT_NV12 ||
|
||||||
|
texture->format == SDL_PIXELFORMAT_NV21) {
|
||||||
|
data->nv12 = SDL_TRUE;
|
||||||
|
|
||||||
|
renderdata->glGenTextures(1, &data->utexture);
|
||||||
|
renderdata->glEnable(data->type);
|
||||||
|
|
||||||
|
renderdata->glBindTexture(data->type, data->utexture);
|
||||||
|
renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
|
||||||
|
scaleMode);
|
||||||
|
renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
|
||||||
|
scaleMode);
|
||||||
|
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, GL_LUMINANCE_ALPHA, texture_w/2,
|
||||||
|
texture_h/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
renderdata->glDisable(data->type);
|
||||||
|
}
|
||||||
|
|
||||||
return GL_CheckError("", renderer);
|
return GL_CheckError("", renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,6 +879,17 @@ GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
rect->w/2, rect->h/2,
|
rect->w/2, rect->h/2,
|
||||||
data->format, data->formattype, pixels);
|
data->format, data->formattype, pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->nv12) {
|
||||||
|
renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH, (pitch / 2));
|
||||||
|
|
||||||
|
/* Skip to the correct offset into the next texture */
|
||||||
|
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
|
||||||
|
renderdata->glBindTexture(data->type, data->utexture);
|
||||||
|
renderdata->glTexSubImage2D(data->type, 0, rect->x/2, rect->y/2,
|
||||||
|
rect->w/2, rect->h/2,
|
||||||
|
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pixels);
|
||||||
|
}
|
||||||
renderdata->glDisable(data->type);
|
renderdata->glDisable(data->type);
|
||||||
|
|
||||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||||
|
@ -1184,15 +1226,10 @@ GL_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
GL_SetupCopy(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
|
|
||||||
{
|
{
|
||||||
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
||||||
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
||||||
GLfloat minx, miny, maxx, maxy;
|
|
||||||
GLfloat minu, maxu, minv, maxv;
|
|
||||||
|
|
||||||
GL_ActivateRenderer(renderer);
|
|
||||||
|
|
||||||
data->glEnable(texturedata->type);
|
data->glEnable(texturedata->type);
|
||||||
if (texturedata->yuv) {
|
if (texturedata->yuv) {
|
||||||
|
@ -1204,6 +1241,12 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
|
||||||
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
data->glActiveTextureARB(GL_TEXTURE0_ARB);
|
||||||
}
|
}
|
||||||
|
if (texturedata->nv12) {
|
||||||
|
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) {
|
||||||
|
@ -1215,10 +1258,33 @@ GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
GL_SetBlendMode(data, texture->blendMode);
|
GL_SetBlendMode(data, texture->blendMode);
|
||||||
|
|
||||||
if (texturedata->yuv) {
|
if (texturedata->yuv) {
|
||||||
GL_SetShader(data, SHADER_YV12);
|
GL_SetShader(data, SHADER_YUV);
|
||||||
|
} else if (texturedata->nv12) {
|
||||||
|
if (texture->format == SDL_PIXELFORMAT_NV12) {
|
||||||
|
GL_SetShader(data, SHADER_NV12);
|
||||||
|
} else {
|
||||||
|
GL_SetShader(data, SHADER_NV21);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
GL_SetShader(data, SHADER_RGB);
|
GL_SetShader(data, SHADER_RGB);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
|
||||||
|
{
|
||||||
|
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
|
||||||
|
GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
|
||||||
|
GLfloat minx, miny, maxx, maxy;
|
||||||
|
GLfloat minu, maxu, minv, maxv;
|
||||||
|
|
||||||
|
GL_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
if (GL_SetupCopy(renderer, texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
minx = dstrect->x;
|
minx = dstrect->x;
|
||||||
miny = dstrect->y;
|
miny = dstrect->y;
|
||||||
|
@ -1263,30 +1329,8 @@ GL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||||
|
|
||||||
GL_ActivateRenderer(renderer);
|
GL_ActivateRenderer(renderer);
|
||||||
|
|
||||||
data->glEnable(texturedata->type);
|
if (GL_SetupCopy(renderer, texture) < 0) {
|
||||||
if (texturedata->yuv) {
|
return -1;
|
||||||
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) {
|
|
||||||
GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
|
|
||||||
} else {
|
|
||||||
GL_SetColor(data, 255, 255, 255, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
GL_SetBlendMode(data, texture->blendMode);
|
|
||||||
|
|
||||||
if (texturedata->yuv) {
|
|
||||||
GL_SetShader(data, SHADER_YV12);
|
|
||||||
} else {
|
|
||||||
GL_SetShader(data, SHADER_RGB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
centerx = center->x;
|
centerx = center->x;
|
||||||
|
|
|
@ -113,7 +113,7 @@ static const char *shader_source[NUM_SHADERS][2] =
|
||||||
"}"
|
"}"
|
||||||
},
|
},
|
||||||
|
|
||||||
/* SHADER_YV12 */
|
/* SHADER_YUV */
|
||||||
{
|
{
|
||||||
/* vertex shader */
|
/* vertex shader */
|
||||||
"varying vec4 v_color;\n"
|
"varying vec4 v_color;\n"
|
||||||
|
@ -162,6 +162,106 @@ static const char *shader_source[NUM_SHADERS][2] =
|
||||||
"\n"
|
"\n"
|
||||||
" // That was easy. :) \n"
|
" // That was easy. :) \n"
|
||||||
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
||||||
|
"}"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* SHADER_NV12 */
|
||||||
|
{
|
||||||
|
/* vertex shader */
|
||||||
|
"varying vec4 v_color;\n"
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||||
|
" v_color = gl_Color;\n"
|
||||||
|
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
|
||||||
|
"}",
|
||||||
|
/* fragment shader */
|
||||||
|
"varying vec4 v_color;\n"
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D tex0; // Y \n"
|
||||||
|
"uniform sampler2D tex1; // U/V \n"
|
||||||
|
"\n"
|
||||||
|
"// YUV offset \n"
|
||||||
|
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
|
||||||
|
"\n"
|
||||||
|
"// RGB coefficients \n"
|
||||||
|
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
|
||||||
|
"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
|
||||||
|
"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 tcoord;\n"
|
||||||
|
" vec3 yuv, rgb;\n"
|
||||||
|
"\n"
|
||||||
|
" // Get the Y value \n"
|
||||||
|
" tcoord = v_texCoord;\n"
|
||||||
|
" yuv.x = texture2D(tex0, tcoord).r;\n"
|
||||||
|
"\n"
|
||||||
|
" // Get the U and V values \n"
|
||||||
|
" tcoord *= 0.5;\n"
|
||||||
|
" yuv.yz = texture2D(tex1, tcoord).ra;\n"
|
||||||
|
"\n"
|
||||||
|
" // Do the color transform \n"
|
||||||
|
" yuv += offset;\n"
|
||||||
|
" rgb.r = dot(yuv, Rcoeff);\n"
|
||||||
|
" rgb.g = dot(yuv, Gcoeff);\n"
|
||||||
|
" rgb.b = dot(yuv, Bcoeff);\n"
|
||||||
|
"\n"
|
||||||
|
" // That was easy. :) \n"
|
||||||
|
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
||||||
|
"}"
|
||||||
|
},
|
||||||
|
|
||||||
|
/* SHADER_NV21 */
|
||||||
|
{
|
||||||
|
/* vertex shader */
|
||||||
|
"varying vec4 v_color;\n"
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
|
||||||
|
" v_color = gl_Color;\n"
|
||||||
|
" v_texCoord = vec2(gl_MultiTexCoord0);\n"
|
||||||
|
"}",
|
||||||
|
/* fragment shader */
|
||||||
|
"varying vec4 v_color;\n"
|
||||||
|
"varying vec2 v_texCoord;\n"
|
||||||
|
"uniform sampler2D tex0; // Y \n"
|
||||||
|
"uniform sampler2D tex1; // U/V \n"
|
||||||
|
"\n"
|
||||||
|
"// YUV offset \n"
|
||||||
|
"const vec3 offset = vec3(-0.0627451017, -0.501960814, -0.501960814);\n"
|
||||||
|
"\n"
|
||||||
|
"// RGB coefficients \n"
|
||||||
|
"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n"
|
||||||
|
"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n"
|
||||||
|
"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n"
|
||||||
|
"\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec2 tcoord;\n"
|
||||||
|
" vec3 yuv, rgb;\n"
|
||||||
|
"\n"
|
||||||
|
" // Get the Y value \n"
|
||||||
|
" tcoord = v_texCoord;\n"
|
||||||
|
" yuv.x = texture2D(tex0, tcoord).r;\n"
|
||||||
|
"\n"
|
||||||
|
" // Get the U and V values \n"
|
||||||
|
" tcoord *= 0.5;\n"
|
||||||
|
" yuv.yz = texture2D(tex1, tcoord).ar;\n"
|
||||||
|
"\n"
|
||||||
|
" // Do the color transform \n"
|
||||||
|
" yuv += offset;\n"
|
||||||
|
" rgb.r = dot(yuv, Rcoeff);\n"
|
||||||
|
" rgb.g = dot(yuv, Gcoeff);\n"
|
||||||
|
" rgb.b = dot(yuv, Bcoeff);\n"
|
||||||
|
"\n"
|
||||||
|
" // That was easy. :) \n"
|
||||||
|
" gl_FragColor = vec4(rgb, 1.0) * v_color;\n"
|
||||||
"}"
|
"}"
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,9 @@ typedef enum {
|
||||||
SHADER_NONE,
|
SHADER_NONE,
|
||||||
SHADER_SOLID,
|
SHADER_SOLID,
|
||||||
SHADER_RGB,
|
SHADER_RGB,
|
||||||
SHADER_YV12,
|
SHADER_YUV,
|
||||||
|
SHADER_NV12,
|
||||||
|
SHADER_NV21,
|
||||||
NUM_SHADERS
|
NUM_SHADERS
|
||||||
} GL_Shader;
|
} GL_Shader;
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,9 @@ typedef struct GLES2_TextureData
|
||||||
GLenum pixel_type;
|
GLenum pixel_type;
|
||||||
void *pixel_data;
|
void *pixel_data;
|
||||||
int pitch;
|
int pitch;
|
||||||
/* YV12 texture support */
|
/* YUV texture support */
|
||||||
SDL_bool yuv;
|
SDL_bool yuv;
|
||||||
|
SDL_bool nv12;
|
||||||
GLenum texture_v;
|
GLenum texture_v;
|
||||||
GLenum texture_u;
|
GLenum texture_u;
|
||||||
GLES2_FBOList *fbo;
|
GLES2_FBOList *fbo;
|
||||||
|
@ -151,7 +152,9 @@ typedef enum
|
||||||
GLES2_IMAGESOURCE_TEXTURE_ARGB,
|
GLES2_IMAGESOURCE_TEXTURE_ARGB,
|
||||||
GLES2_IMAGESOURCE_TEXTURE_RGB,
|
GLES2_IMAGESOURCE_TEXTURE_RGB,
|
||||||
GLES2_IMAGESOURCE_TEXTURE_BGR,
|
GLES2_IMAGESOURCE_TEXTURE_BGR,
|
||||||
GLES2_IMAGESOURCE_TEXTURE_YUV
|
GLES2_IMAGESOURCE_TEXTURE_YUV,
|
||||||
|
GLES2_IMAGESOURCE_TEXTURE_NV12,
|
||||||
|
GLES2_IMAGESOURCE_TEXTURE_NV21
|
||||||
} GLES2_ImageSource;
|
} GLES2_ImageSource;
|
||||||
|
|
||||||
typedef struct GLES2_DriverContext
|
typedef struct GLES2_DriverContext
|
||||||
|
@ -488,6 +491,8 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
break;
|
break;
|
||||||
case SDL_PIXELFORMAT_IYUV:
|
case SDL_PIXELFORMAT_IYUV:
|
||||||
case SDL_PIXELFORMAT_YV12:
|
case SDL_PIXELFORMAT_YV12:
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
case SDL_PIXELFORMAT_NV21:
|
||||||
format = GL_LUMINANCE;
|
format = GL_LUMINANCE;
|
||||||
type = GL_UNSIGNED_BYTE;
|
type = GL_UNSIGNED_BYTE;
|
||||||
break;
|
break;
|
||||||
|
@ -505,6 +510,7 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
data->pixel_format = format;
|
data->pixel_format = format;
|
||||||
data->pixel_type = type;
|
data->pixel_type = type;
|
||||||
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
||||||
|
data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
|
||||||
data->texture_u = 0;
|
data->texture_u = 0;
|
||||||
data->texture_v = 0;
|
data->texture_v = 0;
|
||||||
scaleMode = GetScaleQuality();
|
scaleMode = GetScaleQuality();
|
||||||
|
@ -518,6 +524,10 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
/* Need to add size for the U and V planes */
|
/* Need to add size for the U and V planes */
|
||||||
size += (2 * (texture->h * data->pitch) / 4);
|
size += (2 * (texture->h * data->pitch) / 4);
|
||||||
}
|
}
|
||||||
|
if (data->nv12) {
|
||||||
|
/* Need to add size for the U/V plane */
|
||||||
|
size += ((texture->h * data->pitch) / 2);
|
||||||
|
}
|
||||||
data->pixel_data = SDL_calloc(1, size);
|
data->pixel_data = SDL_calloc(1, size);
|
||||||
if (!data->pixel_data) {
|
if (!data->pixel_data) {
|
||||||
SDL_free(data);
|
SDL_free(data);
|
||||||
|
@ -557,6 +567,23 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data->nv12) {
|
||||||
|
renderdata->glGenTextures(1, &data->texture_u);
|
||||||
|
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
renderdata->glActiveTexture(GL_TEXTURE1);
|
||||||
|
renderdata->glBindTexture(data->texture_type, data->texture_u);
|
||||||
|
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||||
|
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||||
|
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
renderdata->glTexImage2D(data->texture_type, 0, GL_LUMINANCE_ALPHA, texture->w / 2, texture->h / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
renderdata->glGenTextures(1, &data->texture);
|
renderdata->glGenTextures(1, &data->texture);
|
||||||
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -673,6 +700,20 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
pixels, pitch / 2, 1);
|
pixels, pitch / 2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tdata->nv12) {
|
||||||
|
/* Skip to the correct offset into the next texture */
|
||||||
|
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
|
||||||
|
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||||
|
GLES2_TexSubImage2D(data, tdata->texture_type,
|
||||||
|
rect->x / 2,
|
||||||
|
rect->y / 2,
|
||||||
|
rect->w / 2,
|
||||||
|
rect->h / 2,
|
||||||
|
GL_LUMINANCE_ALPHA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
pixels, pitch, 2);
|
||||||
|
}
|
||||||
|
|
||||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1093,6 +1134,12 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
|
||||||
case GLES2_IMAGESOURCE_TEXTURE_YUV:
|
case GLES2_IMAGESOURCE_TEXTURE_YUV:
|
||||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
|
||||||
break;
|
break;
|
||||||
|
case GLES2_IMAGESOURCE_TEXTURE_NV12:
|
||||||
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC;
|
||||||
|
break;
|
||||||
|
case GLES2_IMAGESOURCE_TEXTURE_NV21:
|
||||||
|
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto fault;
|
goto fault;
|
||||||
}
|
}
|
||||||
|
@ -1432,20 +1479,15 @@ GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
|
GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture)
|
||||||
const SDL_FRect *dstrect)
|
|
||||||
{
|
{
|
||||||
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_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
||||||
SDL_BlendMode blendMode;
|
SDL_BlendMode blendMode;
|
||||||
GLfloat vertices[8];
|
|
||||||
GLfloat texCoords[8];
|
|
||||||
GLES2_ProgramCacheEntry *program;
|
GLES2_ProgramCacheEntry *program;
|
||||||
Uint8 r, g, b, a;
|
Uint8 r, g, b, a;
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
|
||||||
|
|
||||||
/* Activate an appropriate shader and set the projection matrix */
|
/* Activate an appropriate shader and set the projection matrix */
|
||||||
blendMode = texture->blendMode;
|
blendMode = texture->blendMode;
|
||||||
if (renderer->target) {
|
if (renderer->target) {
|
||||||
|
@ -1505,11 +1547,22 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SDL_PIXELFORMAT_IYUV:
|
||||||
|
case SDL_PIXELFORMAT_YV12:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV21:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return SDL_SetError("Unsupported texture format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
switch (texture->format)
|
switch (texture->format)
|
||||||
{
|
{
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
case SDL_PIXELFORMAT_ARGB8888:
|
||||||
|
@ -1524,13 +1577,18 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
case SDL_PIXELFORMAT_BGR888:
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
||||||
break;
|
break;
|
||||||
// TODO: new shader to change yv planes YV12 format
|
|
||||||
case SDL_PIXELFORMAT_IYUV:
|
case SDL_PIXELFORMAT_IYUV:
|
||||||
case SDL_PIXELFORMAT_YV12:
|
case SDL_PIXELFORMAT_YV12:
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||||
break;
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV21:
|
||||||
|
sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -1;
|
return SDL_SetError("Unsupported texture format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,6 +1606,12 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
|
|
||||||
data->glActiveTexture(GL_TEXTURE0);
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
if (tdata->nv12) {
|
||||||
|
data->glActiveTexture(GL_TEXTURE1);
|
||||||
|
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||||
|
|
||||||
|
data->glActiveTexture(GL_TEXTURE0);
|
||||||
|
}
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||||
|
|
||||||
/* Configure color modulation */
|
/* Configure color modulation */
|
||||||
|
@ -1578,6 +1642,23 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
||||||
GLES2_SetBlendMode(data, blendMode);
|
GLES2_SetBlendMode(data, blendMode);
|
||||||
|
|
||||||
GLES2_SetTexCoords(data, SDL_TRUE);
|
GLES2_SetTexCoords(data, SDL_TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
|
||||||
|
const SDL_FRect *dstrect)
|
||||||
|
{
|
||||||
|
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||||
|
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||||
|
GLfloat vertices[8];
|
||||||
|
GLfloat texCoords[8];
|
||||||
|
|
||||||
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
if (GLES2_SetupCopy(renderer, texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit the textured quad */
|
/* Emit the textured quad */
|
||||||
vertices[0] = dstrect->x;
|
vertices[0] = dstrect->x;
|
||||||
|
@ -1609,10 +1690,6 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
{
|
{
|
||||||
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_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
|
||||||
GLES2_ProgramCacheEntry *program;
|
|
||||||
Uint8 r, g, b, a;
|
|
||||||
SDL_BlendMode blendMode;
|
|
||||||
GLfloat vertices[8];
|
GLfloat vertices[8];
|
||||||
GLfloat texCoords[8];
|
GLfloat texCoords[8];
|
||||||
GLfloat translate[8];
|
GLfloat translate[8];
|
||||||
|
@ -1621,6 +1698,10 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
|
|
||||||
GLES2_ActivateRenderer(renderer);
|
GLES2_ActivateRenderer(renderer);
|
||||||
|
|
||||||
|
if (GLES2_SetupCopy(renderer, texture) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
|
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
|
||||||
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
|
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
|
||||||
fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
|
fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
|
||||||
|
@ -1628,124 +1709,6 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
||||||
translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
|
translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
|
||||||
translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
|
translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
|
||||||
|
|
||||||
/* Activate an appropriate shader and set the projection matrix */
|
|
||||||
blendMode = texture->blendMode;
|
|
||||||
if (renderer->target) {
|
|
||||||
/* Check if we need to do color mapping between the source and render target textures */
|
|
||||||
if (renderer->target->format != texture->format) {
|
|
||||||
switch (texture->format)
|
|
||||||
{
|
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
|
||||||
switch (renderer->target->format)
|
|
||||||
{
|
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
|
||||||
switch (renderer->target->format)
|
|
||||||
{
|
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
|
||||||
switch (renderer->target->format)
|
|
||||||
{
|
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
|
||||||
switch (renderer->target->format)
|
|
||||||
{
|
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
switch (texture->format)
|
|
||||||
{
|
|
||||||
case SDL_PIXELFORMAT_ARGB8888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_ABGR8888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_RGB888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
|
||||||
break;
|
|
||||||
case SDL_PIXELFORMAT_BGR888:
|
|
||||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Select the target texture */
|
|
||||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
|
||||||
|
|
||||||
/* Configure color modulation */
|
|
||||||
/* !!! FIXME: grep for glUniform4f(), move that stuff to a subroutine, it's a lot of copy/paste. */
|
|
||||||
g = texture->g;
|
|
||||||
a = texture->a;
|
|
||||||
|
|
||||||
if (renderer->target &&
|
|
||||||
(renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
|
|
||||||
renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
|
|
||||||
r = texture->b;
|
|
||||||
b = texture->r;
|
|
||||||
} else {
|
|
||||||
r = texture->r;
|
|
||||||
b = texture->b;
|
|
||||||
}
|
|
||||||
|
|
||||||
program = data->current_program;
|
|
||||||
|
|
||||||
if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
|
|
||||||
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
|
|
||||||
program->modulation_r = r;
|
|
||||||
program->modulation_g = g;
|
|
||||||
program->modulation_b = b;
|
|
||||||
program->modulation_a = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Configure texture blending */
|
|
||||||
GLES2_SetBlendMode(data, blendMode);
|
|
||||||
|
|
||||||
GLES2_SetTexCoords(data, SDL_TRUE);
|
|
||||||
|
|
||||||
/* Emit the textured quad */
|
/* Emit the textured quad */
|
||||||
vertices[0] = dstrect->x;
|
vertices[0] = dstrect->x;
|
||||||
vertices[1] = dstrect->y;
|
vertices[1] = dstrect->y;
|
||||||
|
@ -2066,6 +2029,8 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
||||||
|
|
||||||
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;
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
||||||
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12;
|
||||||
|
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21;
|
||||||
|
|
||||||
GLES2_ResetState(renderer);
|
GLES2_ResetState(renderer);
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,50 @@ static const Uint8 GLES2_FragmentSrc_TextureYUVSrc_[] = " \
|
||||||
} \
|
} \
|
||||||
";
|
";
|
||||||
|
|
||||||
|
/* NV12 to ABGR conversion */
|
||||||
|
static const Uint8 GLES2_FragmentSrc_TextureNV12Src_[] = " \
|
||||||
|
precision mediump float; \
|
||||||
|
uniform sampler2D u_texture; \
|
||||||
|
uniform sampler2D u_texture_u; \
|
||||||
|
uniform vec4 u_modulation; \
|
||||||
|
varying vec2 v_texCoord; \
|
||||||
|
\
|
||||||
|
void main() \
|
||||||
|
{ \
|
||||||
|
mediump vec3 yuv; \
|
||||||
|
lowp vec3 rgb; \
|
||||||
|
yuv.x = texture2D(u_texture, v_texCoord).r; \
|
||||||
|
yuv.yz = texture2D(u_texture_u, v_texCoord).ra - 0.5; \
|
||||||
|
rgb = mat3( 1, 1, 1, \
|
||||||
|
0, -0.39465, 2.03211, \
|
||||||
|
1.13983, -0.58060, 0) * yuv; \
|
||||||
|
gl_FragColor = vec4(rgb, 1); \
|
||||||
|
gl_FragColor *= u_modulation; \
|
||||||
|
} \
|
||||||
|
";
|
||||||
|
|
||||||
|
/* NV21 to ABGR conversion */
|
||||||
|
static const Uint8 GLES2_FragmentSrc_TextureNV21Src_[] = " \
|
||||||
|
precision mediump float; \
|
||||||
|
uniform sampler2D u_texture; \
|
||||||
|
uniform sampler2D u_texture_u; \
|
||||||
|
uniform vec4 u_modulation; \
|
||||||
|
varying vec2 v_texCoord; \
|
||||||
|
\
|
||||||
|
void main() \
|
||||||
|
{ \
|
||||||
|
mediump vec3 yuv; \
|
||||||
|
lowp vec3 rgb; \
|
||||||
|
yuv.x = texture2D(u_texture, v_texCoord).r; \
|
||||||
|
yuv.yz = texture2D(u_texture_u, v_texCoord).ar - 0.5; \
|
||||||
|
rgb = mat3( 1, 1, 1, \
|
||||||
|
0, -0.39465, 2.03211, \
|
||||||
|
1.13983, -0.58060, 0) * yuv; \
|
||||||
|
gl_FragColor = vec4(rgb, 1); \
|
||||||
|
gl_FragColor *= u_modulation; \
|
||||||
|
} \
|
||||||
|
";
|
||||||
|
|
||||||
static const GLES2_ShaderInstance GLES2_VertexSrc_Default = {
|
static const GLES2_ShaderInstance GLES2_VertexSrc_Default = {
|
||||||
GL_VERTEX_SHADER,
|
GL_VERTEX_SHADER,
|
||||||
GLES2_SOURCE_SHADER,
|
GLES2_SOURCE_SHADER,
|
||||||
|
@ -199,6 +243,20 @@ static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureYUVSrc = {
|
||||||
GLES2_FragmentSrc_TextureYUVSrc_
|
GLES2_FragmentSrc_TextureYUVSrc_
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV12Src = {
|
||||||
|
GL_FRAGMENT_SHADER,
|
||||||
|
GLES2_SOURCE_SHADER,
|
||||||
|
sizeof(GLES2_FragmentSrc_TextureNV12Src_),
|
||||||
|
GLES2_FragmentSrc_TextureNV12Src_
|
||||||
|
};
|
||||||
|
|
||||||
|
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV21Src = {
|
||||||
|
GL_FRAGMENT_SHADER,
|
||||||
|
GLES2_SOURCE_SHADER,
|
||||||
|
sizeof(GLES2_FragmentSrc_TextureNV21Src_),
|
||||||
|
GLES2_FragmentSrc_TextureNV21Src_
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************************************
|
/*************************************************************************************************
|
||||||
* Vertex/fragment shader binaries (NVIDIA Tegra 1/2) *
|
* Vertex/fragment shader binaries (NVIDIA Tegra 1/2) *
|
||||||
|
@ -731,6 +789,20 @@ static GLES2_Shader GLES2_FragmentShader_TextureYUVSrc = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static GLES2_Shader GLES2_FragmentShader_TextureNV12Src = {
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
&GLES2_FragmentSrc_TextureNV12Src
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLES2_Shader GLES2_FragmentShader_TextureNV21Src = {
|
||||||
|
1,
|
||||||
|
{
|
||||||
|
&GLES2_FragmentSrc_TextureNV21Src
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************************************
|
/*************************************************************************************************
|
||||||
* Shader selector *
|
* Shader selector *
|
||||||
|
@ -820,6 +892,16 @@ const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type, SDL_BlendMode blendMo
|
||||||
return &GLES2_FragmentShader_TextureYUVSrc;
|
return &GLES2_FragmentShader_TextureYUVSrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC:
|
||||||
|
{
|
||||||
|
return &GLES2_FragmentShader_TextureNV12Src;
|
||||||
|
}
|
||||||
|
|
||||||
|
case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC:
|
||||||
|
{
|
||||||
|
return &GLES2_FragmentShader_TextureNV21Src;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,9 @@ typedef enum
|
||||||
GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC,
|
GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC,
|
||||||
GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC,
|
GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC,
|
||||||
GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC,
|
GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC,
|
||||||
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC
|
GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC,
|
||||||
|
GLES2_SHADER_FRAGMENT_TEXTURE_NV12_SRC,
|
||||||
|
GLES2_SHADER_FRAGMENT_TEXTURE_NV21_SRC
|
||||||
} GLES2_ShaderType;
|
} GLES2_ShaderType;
|
||||||
|
|
||||||
#define GLES2_SOURCE_SHADER (GLenum)-1
|
#define GLES2_SOURCE_SHADER (GLenum)-1
|
||||||
|
|
|
@ -572,6 +572,12 @@ SDLTest_PrintPixelFormat(Uint32 format)
|
||||||
case SDL_PIXELFORMAT_YVYU:
|
case SDL_PIXELFORMAT_YVYU:
|
||||||
fprintf(stderr, "YVYU");
|
fprintf(stderr, "YVYU");
|
||||||
break;
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
fprintf(stderr, "NV12");
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV21:
|
||||||
|
fprintf(stderr, "NV21");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "0x%8.8x", format);
|
fprintf(stderr, "0x%8.8x", format);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -122,6 +122,8 @@ SDL_GetPixelFormatName(Uint32 format)
|
||||||
CASE(SDL_PIXELFORMAT_YUY2)
|
CASE(SDL_PIXELFORMAT_YUY2)
|
||||||
CASE(SDL_PIXELFORMAT_UYVY)
|
CASE(SDL_PIXELFORMAT_UYVY)
|
||||||
CASE(SDL_PIXELFORMAT_YVYU)
|
CASE(SDL_PIXELFORMAT_YVYU)
|
||||||
|
CASE(SDL_PIXELFORMAT_NV12)
|
||||||
|
CASE(SDL_PIXELFORMAT_NV21)
|
||||||
#undef CASE
|
#undef CASE
|
||||||
default:
|
default:
|
||||||
return "SDL_PIXELFORMAT_UNKNOWN";
|
return "SDL_PIXELFORMAT_UNKNOWN";
|
||||||
|
|
|
@ -1005,7 +1005,7 @@ int SDL_ConvertPixels(int width, int height,
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
void *nonconst_src = (void *) src;
|
void *nonconst_src = (void *) src;
|
||||||
|
|
||||||
/* Check to make sure we are bliting somewhere, so we don't crash */
|
/* Check to make sure we are blitting somewhere, so we don't crash */
|
||||||
if (!dst) {
|
if (!dst) {
|
||||||
return SDL_InvalidParamError("dst");
|
return SDL_InvalidParamError("dst");
|
||||||
}
|
}
|
||||||
|
@ -1015,17 +1015,21 @@ int SDL_ConvertPixels(int width, int height,
|
||||||
|
|
||||||
/* Fast path for same format copy */
|
/* Fast path for same format copy */
|
||||||
if (src_format == dst_format) {
|
if (src_format == dst_format) {
|
||||||
int bpp;
|
int bpp, i;
|
||||||
|
|
||||||
if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
if (SDL_ISPIXELFORMAT_FOURCC(src_format)) {
|
||||||
switch (src_format) {
|
switch (src_format) {
|
||||||
case SDL_PIXELFORMAT_YV12:
|
|
||||||
case SDL_PIXELFORMAT_IYUV:
|
|
||||||
case SDL_PIXELFORMAT_YUY2:
|
case SDL_PIXELFORMAT_YUY2:
|
||||||
case SDL_PIXELFORMAT_UYVY:
|
case SDL_PIXELFORMAT_UYVY:
|
||||||
case SDL_PIXELFORMAT_YVYU:
|
case SDL_PIXELFORMAT_YVYU:
|
||||||
bpp = 2;
|
bpp = 2;
|
||||||
break;
|
break;
|
||||||
|
case SDL_PIXELFORMAT_YV12:
|
||||||
|
case SDL_PIXELFORMAT_IYUV:
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
case SDL_PIXELFORMAT_NV21:
|
||||||
|
bpp = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return SDL_SetError("Unknown FOURCC pixel format");
|
return SDL_SetError("Unknown FOURCC pixel format");
|
||||||
}
|
}
|
||||||
|
@ -1034,11 +1038,32 @@ int SDL_ConvertPixels(int width, int height,
|
||||||
}
|
}
|
||||||
width *= bpp;
|
width *= bpp;
|
||||||
|
|
||||||
while (height-- > 0) {
|
for (i = height; i--;) {
|
||||||
SDL_memcpy(dst, src, width);
|
SDL_memcpy(dst, src, width);
|
||||||
src = (Uint8*)src + src_pitch;
|
src = (Uint8*)src + src_pitch;
|
||||||
dst = (Uint8*)dst + dst_pitch;
|
dst = (Uint8*)dst + dst_pitch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src_format == SDL_PIXELFORMAT_YV12 || src_format == SDL_PIXELFORMAT_IYUV) {
|
||||||
|
/* U and V planes are a quarter the size of the Y plane */
|
||||||
|
width /= 2;
|
||||||
|
height /= 2;
|
||||||
|
src_pitch /= 2;
|
||||||
|
dst_pitch /= 2;
|
||||||
|
for (i = height * 2; i--;) {
|
||||||
|
SDL_memcpy(dst, src, width);
|
||||||
|
src = (Uint8*)src + src_pitch;
|
||||||
|
dst = (Uint8*)dst + dst_pitch;
|
||||||
|
}
|
||||||
|
} else if (src_format == SDL_PIXELFORMAT_NV12 || src_format == SDL_PIXELFORMAT_NV21) {
|
||||||
|
/* U/V plane is half the height of the Y plane */
|
||||||
|
height /= 2;
|
||||||
|
for (i = height; i--;) {
|
||||||
|
SDL_memcpy(dst, src, width);
|
||||||
|
src = (Uint8*)src + src_pitch;
|
||||||
|
dst = (Uint8*)dst + dst_pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,14 +79,16 @@ char* _RGBPixelFormatsVerbose[] =
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Definition of all Non-RGB formats used to test pixel conversions */
|
/* Definition of all Non-RGB formats used to test pixel conversions */
|
||||||
const int _numNonRGBPixelFormats = 5;
|
const int _numNonRGBPixelFormats = 7;
|
||||||
Uint32 _nonRGBPixelFormats[] =
|
Uint32 _nonRGBPixelFormats[] =
|
||||||
{
|
{
|
||||||
SDL_PIXELFORMAT_YV12,
|
SDL_PIXELFORMAT_YV12,
|
||||||
SDL_PIXELFORMAT_IYUV,
|
SDL_PIXELFORMAT_IYUV,
|
||||||
SDL_PIXELFORMAT_YUY2,
|
SDL_PIXELFORMAT_YUY2,
|
||||||
SDL_PIXELFORMAT_UYVY,
|
SDL_PIXELFORMAT_UYVY,
|
||||||
SDL_PIXELFORMAT_YVYU
|
SDL_PIXELFORMAT_YVYU,
|
||||||
|
SDL_PIXELFORMAT_NV12,
|
||||||
|
SDL_PIXELFORMAT_NV21
|
||||||
};
|
};
|
||||||
char* _nonRGBPixelFormatsVerbose[] =
|
char* _nonRGBPixelFormatsVerbose[] =
|
||||||
{
|
{
|
||||||
|
@ -94,7 +96,9 @@ char* _nonRGBPixelFormatsVerbose[] =
|
||||||
"SDL_PIXELFORMAT_IYUV",
|
"SDL_PIXELFORMAT_IYUV",
|
||||||
"SDL_PIXELFORMAT_YUY2",
|
"SDL_PIXELFORMAT_YUY2",
|
||||||
"SDL_PIXELFORMAT_UYVY",
|
"SDL_PIXELFORMAT_UYVY",
|
||||||
"SDL_PIXELFORMAT_YVYU"
|
"SDL_PIXELFORMAT_YVYU",
|
||||||
|
"SDL_PIXELFORMAT_NV12",
|
||||||
|
"SDL_PIXELFORMAT_NV21"
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Definition of some invalid formats for negative tests */
|
/* Definition of some invalid formats for negative tests */
|
||||||
|
|
|
@ -206,6 +206,29 @@ ConvertRGBtoYV12(Uint8 *rgb, Uint8 *out, int w, int h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConvertRGBtoNV12(Uint8 *rgb, Uint8 *out, int w, int h,
|
||||||
|
int monochrome, int luminance)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
int yuv[3];
|
||||||
|
Uint8 *op[2];
|
||||||
|
|
||||||
|
op[0] = out;
|
||||||
|
op[1] = op[0] + w*h;
|
||||||
|
for (y = 0; y < h; ++y) {
|
||||||
|
for (x = 0; x < w; ++x) {
|
||||||
|
RGBtoYUV(rgb, yuv, monochrome, luminance);
|
||||||
|
*(op[0]++) = yuv[0];
|
||||||
|
if (x % 2 == 0 && y % 2 == 0) {
|
||||||
|
*(op[1]++) = yuv[1];
|
||||||
|
*(op[1]++) = yuv[2];
|
||||||
|
}
|
||||||
|
rgb += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PrintUsage(char *argv0)
|
PrintUsage(char *argv0)
|
||||||
{
|
{
|
||||||
|
@ -241,7 +264,11 @@ main(int argc, char **argv)
|
||||||
int fps = 12;
|
int fps = 12;
|
||||||
int fpsdelay;
|
int fpsdelay;
|
||||||
int nodelay = 0;
|
int nodelay = 0;
|
||||||
|
#ifdef TEST_NV12
|
||||||
|
Uint32 pixel_format = SDL_PIXELFORMAT_NV12;
|
||||||
|
#else
|
||||||
Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
|
Uint32 pixel_format = SDL_PIXELFORMAT_YV12;
|
||||||
|
#endif
|
||||||
int scale = 5;
|
int scale = 5;
|
||||||
SDL_bool done = SDL_FALSE;
|
SDL_bool done = SDL_FALSE;
|
||||||
|
|
||||||
|
@ -371,7 +398,17 @@ main(int argc, char **argv)
|
||||||
rgb[2] = MooseColors[frame[j]].b;
|
rgb[2] = MooseColors[frame[j]].b;
|
||||||
rgb += 3;
|
rgb += 3;
|
||||||
}
|
}
|
||||||
|
switch (pixel_format) {
|
||||||
|
case SDL_PIXELFORMAT_YV12:
|
||||||
ConvertRGBtoYV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100);
|
ConvertRGBtoYV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100);
|
||||||
|
break;
|
||||||
|
case SDL_PIXELFORMAT_NV12:
|
||||||
|
ConvertRGBtoNV12(MooseFrameRGB, MooseFrame[i], MOOSEPIC_W, MOOSEPIC_H, 0, 100);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Unsupported pixel format\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(RawMooseData);
|
free(RawMooseData);
|
||||||
|
|
Loading…
Reference in New Issue