mirror of https://github.com/encounter/SDL.git
dront78 implemented YUV texture support for OpenGL ES 2.0
This commit is contained in:
parent
93aabd3224
commit
9fb2cc10c0
|
@ -79,6 +79,10 @@ typedef struct GLES2_TextureData
|
|||
GLenum pixel_type;
|
||||
void *pixel_data;
|
||||
size_t pitch;
|
||||
/* YV12 texture support */
|
||||
SDL_bool yuv;
|
||||
GLenum texture_v;
|
||||
GLenum texture_u;
|
||||
GLES2_FBOList *fbo;
|
||||
} GLES2_TextureData;
|
||||
|
||||
|
@ -133,7 +137,9 @@ typedef enum
|
|||
GLES2_UNIFORM_PROJECTION,
|
||||
GLES2_UNIFORM_TEXTURE,
|
||||
GLES2_UNIFORM_MODULATION,
|
||||
GLES2_UNIFORM_COLOR
|
||||
GLES2_UNIFORM_COLOR,
|
||||
GLES2_UNIFORM_TEXTURE_U,
|
||||
GLES2_UNIFORM_TEXTURE_V
|
||||
} GLES2_Uniform;
|
||||
|
||||
typedef enum
|
||||
|
@ -142,7 +148,8 @@ typedef enum
|
|||
GLES2_IMAGESOURCE_TEXTURE_ABGR,
|
||||
GLES2_IMAGESOURCE_TEXTURE_ARGB,
|
||||
GLES2_IMAGESOURCE_TEXTURE_RGB,
|
||||
GLES2_IMAGESOURCE_TEXTURE_BGR
|
||||
GLES2_IMAGESOURCE_TEXTURE_BGR,
|
||||
GLES2_IMAGESOURCE_TEXTURE_YUV
|
||||
} GLES2_ImageSource;
|
||||
|
||||
typedef struct GLES2_DriverContext
|
||||
|
@ -433,6 +440,11 @@ GLES2_DestroyRenderer(SDL_Renderer *renderer)
|
|||
static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||
static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
|
||||
const void *pixels, int pitch);
|
||||
static int GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect,
|
||||
const Uint8 *Yplane, int Ypitch,
|
||||
const Uint8 *Uplane, int Upitch,
|
||||
const Uint8 *Vplane, int Vpitch);
|
||||
static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
|
||||
void **pixels, int *pitch);
|
||||
static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
|
||||
|
@ -472,6 +484,11 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
format = GL_RGBA;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
format = GL_LUMINANCE;
|
||||
type = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
default:
|
||||
return SDL_SetError("Texture format not supported");
|
||||
}
|
||||
|
@ -485,12 +502,21 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
data->texture_type = GL_TEXTURE_2D;
|
||||
data->pixel_format = format;
|
||||
data->pixel_type = type;
|
||||
data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
|
||||
data->texture_u = 0;
|
||||
data->texture_v = 0;
|
||||
scaleMode = GetScaleQuality();
|
||||
|
||||
/* Allocate a blob for image renderdata */
|
||||
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
|
||||
size_t size;
|
||||
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
|
||||
data->pixel_data = SDL_calloc(1, data->pitch * texture->h);
|
||||
size = texture->h * data->pitch;
|
||||
if (data->yuv) {
|
||||
/* Need to add size for the U and V planes */
|
||||
size += (2 * (texture->h * data->pitch) / 4);
|
||||
}
|
||||
data->pixel_data = SDL_calloc(1, size);
|
||||
if (!data->pixel_data) {
|
||||
SDL_free(data);
|
||||
return SDL_OutOfMemory();
|
||||
|
@ -499,11 +525,42 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
|
||||
/* Allocate the texture */
|
||||
GL_CheckError("", renderer);
|
||||
|
||||
if (data->yuv) {
|
||||
renderdata->glGenTextures(1, &data->texture_v);
|
||||
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
||||
return -1;
|
||||
}
|
||||
renderdata->glActiveTexture(GL_TEXTURE2);
|
||||
renderdata->glBindTexture(data->texture_type, data->texture_v);
|
||||
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, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
|
||||
|
||||
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, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
|
||||
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
renderdata->glGenTextures(1, &data->texture);
|
||||
if (GL_CheckError("glGenTexures()", renderer) < 0) {
|
||||
return -1;
|
||||
}
|
||||
texture->driverdata = data;
|
||||
renderdata->glActiveTexture(GL_TEXTURE0);
|
||||
renderdata->glBindTexture(data->texture_type, data->texture);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
|
||||
renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
|
||||
|
@ -574,6 +631,53 @@ GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect
|
|||
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||
}
|
||||
|
||||
static int
|
||||
GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
|
||||
const SDL_Rect * rect,
|
||||
const Uint8 *Yplane, int Ypitch,
|
||||
const Uint8 *Uplane, int Upitch,
|
||||
const Uint8 *Vplane, int Vpitch)
|
||||
{
|
||||
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
|
||||
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
data->glTexSubImage2D(tdata->texture_type,
|
||||
0,
|
||||
rect->x,
|
||||
rect->y,
|
||||
rect->w / 2,
|
||||
rect->h / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Vplane);
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
data->glTexSubImage2D(tdata->texture_type,
|
||||
0,
|
||||
rect->x,
|
||||
rect->y,
|
||||
rect->w / 2,
|
||||
rect->h / 2,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Uplane);
|
||||
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
data->glTexSubImage2D(tdata->texture_type,
|
||||
0,
|
||||
rect->x,
|
||||
rect->y,
|
||||
rect->w,
|
||||
rect->h,
|
||||
tdata->pixel_format,
|
||||
tdata->pixel_type,
|
||||
Yplane);
|
||||
|
||||
|
||||
return GL_CheckError("glTexSubImage2D()", renderer);
|
||||
}
|
||||
|
||||
static int
|
||||
GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
|
||||
void **pixels, int *pitch)
|
||||
|
@ -638,6 +742,12 @@ GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
|
|||
if (tdata)
|
||||
{
|
||||
data->glDeleteTextures(1, &tdata->texture);
|
||||
if (tdata->texture_v) {
|
||||
data->glDeleteTextures(1, &tdata->texture_v);
|
||||
}
|
||||
if (tdata->texture_u) {
|
||||
data->glDeleteTextures(1, &tdata->texture_u);
|
||||
}
|
||||
SDL_free(tdata->pixel_data);
|
||||
SDL_free(tdata);
|
||||
texture->driverdata = NULL;
|
||||
|
@ -723,6 +833,10 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
|
|||
/* Predetermine locations of uniform variables */
|
||||
entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
|
||||
data->glGetUniformLocation(entry->id, "u_projection");
|
||||
entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
|
||||
data->glGetUniformLocation(entry->id, "u_texture_v");
|
||||
entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
|
||||
data->glGetUniformLocation(entry->id, "u_texture_u");
|
||||
entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
|
||||
data->glGetUniformLocation(entry->id, "u_texture");
|
||||
entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
|
||||
|
@ -734,8 +848,10 @@ GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
|
|||
entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
|
||||
|
||||
data->glUseProgram(entry->id);
|
||||
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
|
||||
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */
|
||||
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */
|
||||
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
|
||||
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
|
||||
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
|
@ -927,6 +1043,9 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendM
|
|||
case GLES2_IMAGESOURCE_TEXTURE_BGR:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
|
||||
break;
|
||||
case GLES2_IMAGESOURCE_TEXTURE_YUV:
|
||||
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
|
||||
break;
|
||||
default:
|
||||
goto fault;
|
||||
}
|
||||
|
@ -1358,6 +1477,11 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
case SDL_PIXELFORMAT_RGB888:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
|
||||
break;
|
||||
// TODO: new shader to change yv planes YV12 format
|
||||
case SDL_PIXELFORMAT_IYUV:
|
||||
case SDL_PIXELFORMAT_YV12:
|
||||
sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -1368,6 +1492,15 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
|
|||
}
|
||||
|
||||
/* Select the target texture */
|
||||
if (tdata->yuv) {
|
||||
data->glActiveTexture(GL_TEXTURE2);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_v);
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE1);
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture_u);
|
||||
|
||||
data->glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
data->glBindTexture(tdata->texture_type, tdata->texture);
|
||||
|
||||
/* Configure color modulation */
|
||||
|
@ -1869,6 +2002,7 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
|||
renderer->WindowEvent = &GLES2_WindowEvent;
|
||||
renderer->CreateTexture = &GLES2_CreateTexture;
|
||||
renderer->UpdateTexture = &GLES2_UpdateTexture;
|
||||
renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV;
|
||||
renderer->LockTexture = &GLES2_LockTexture;
|
||||
renderer->UnlockTexture = &GLES2_UnlockTexture;
|
||||
renderer->SetRenderTarget = &GLES2_SetRenderTarget;
|
||||
|
@ -1887,6 +2021,9 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
|
|||
renderer->GL_BindTexture = &GLES2_BindTexture;
|
||||
renderer->GL_UnbindTexture = &GLES2_UnbindTexture;
|
||||
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
|
||||
renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
|
||||
|
||||
GLES2_ResetState(renderer);
|
||||
|
||||
return renderer;
|
||||
|
|
|
@ -126,6 +126,30 @@ static const Uint8 GLES2_FragmentSrc_TextureBGRSrc_[] = " \
|
|||
} \
|
||||
";
|
||||
|
||||
/* YUV to ABGR conversion */
|
||||
static const Uint8 GLES2_FragmentSrc_TextureYUVSrc_[] = " \
|
||||
precision mediump float; \
|
||||
uniform sampler2D u_texture; \
|
||||
uniform sampler2D u_texture_u; \
|
||||
uniform sampler2D u_texture_v; \
|
||||
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.y = texture2D(u_texture_u, v_texCoord).r - 0.5; \
|
||||
yuv.z = texture2D(u_texture_v, v_texCoord).r - 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 = {
|
||||
GL_VERTEX_SHADER,
|
||||
GLES2_SOURCE_SHADER,
|
||||
|
@ -168,6 +192,14 @@ static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureBGRSrc = {
|
|||
GLES2_FragmentSrc_TextureBGRSrc_
|
||||
};
|
||||
|
||||
static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureYUVSrc = {
|
||||
GL_FRAGMENT_SHADER,
|
||||
GLES2_SOURCE_SHADER,
|
||||
sizeof(GLES2_FragmentSrc_TextureYUVSrc_),
|
||||
GLES2_FragmentSrc_TextureYUVSrc_
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Vertex/fragment shader binaries (NVIDIA Tegra 1/2) *
|
||||
*************************************************************************************************/
|
||||
|
@ -692,6 +724,14 @@ static GLES2_Shader GLES2_FragmentShader_Modulated_TextureBGRSrc = {
|
|||
}
|
||||
};
|
||||
|
||||
static GLES2_Shader GLES2_FragmentShader_TextureYUVSrc = {
|
||||
1,
|
||||
{
|
||||
&GLES2_FragmentSrc_TextureYUVSrc
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
* Shader selector *
|
||||
*************************************************************************************************/
|
||||
|
@ -774,6 +814,11 @@ const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type, SDL_BlendMode blendMo
|
|||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
case GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC:
|
||||
{
|
||||
return &GLES2_FragmentShader_TextureYUVSrc;
|
||||
}
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
|
|
|
@ -46,7 +46,8 @@ typedef enum
|
|||
GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC,
|
||||
GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_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_ShaderType;
|
||||
|
||||
#define GLES2_SOURCE_SHADER (GLenum)-1
|
||||
|
|
Loading…
Reference in New Issue