From e8bbbb37f1cf814118f1d517bb8803abe4bc7651 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 12 Dec 2017 12:52:17 -0800 Subject: [PATCH] Added support for Android video textures --- include/SDL_pixels.h | 4 ++- src/render/opengles2/SDL_render_gles2.c | 38 +++++++++++++++++++++--- src/render/opengles2/SDL_shaders_gles2.c | 31 +++++++++++++++++++ src/render/opengles2/SDL_shaders_gles2.h | 1 + 4 files changed, 69 insertions(+), 5 deletions(-) diff --git a/include/SDL_pixels.h b/include/SDL_pixels.h index 04246689f5957..7c4e7b26a2f41 100644 --- a/include/SDL_pixels.h +++ b/include/SDL_pixels.h @@ -287,7 +287,9 @@ enum 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') + SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), + SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */ + SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') }; typedef struct SDL_Color diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 4b09e3a043092..32c6f8049587f 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -166,7 +166,8 @@ typedef enum GLES2_IMAGESOURCE_TEXTURE_BGR, GLES2_IMAGESOURCE_TEXTURE_YUV, GLES2_IMAGESOURCE_TEXTURE_NV12, - GLES2_IMAGESOURCE_TEXTURE_NV21 + GLES2_IMAGESOURCE_TEXTURE_NV21, + GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES } GLES2_ImageSource; typedef struct GLES2_DriverContext @@ -593,17 +594,32 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) format = GL_LUMINANCE; type = GL_UNSIGNED_BYTE; break; +#ifdef GL_TEXTURE_EXTERNAL_OES + case SDL_PIXELFORMAT_EXTERNAL_OES: + format = GL_NONE; + type = GL_NONE; + break; +#endif default: return SDL_SetError("Texture format not supported"); } + if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES && + texture->access != SDL_TEXTUREACCESS_STATIC) { + return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES"); + } + /* Allocate a texture struct */ data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData)); if (!data) { return SDL_OutOfMemory(); } data->texture = 0; +#ifdef GL_TEXTURE_EXTERNAL_OES + data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; +#else data->texture_type = GL_TEXTURE_2D; +#endif data->pixel_format = format; data->pixel_type = type; data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12)); @@ -692,9 +708,11 @@ GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) 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, texture->h, 0, format, type, NULL); - if (GL_CheckError("glTexImage2D()", renderer) < 0) { - return -1; + if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { + renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); + if (GL_CheckError("glTexImage2D()", renderer) < 0) { + return -1; + } } if (texture->access == SDL_TEXTUREACCESS_TARGET) { @@ -1263,6 +1281,9 @@ GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int goto fault; } break; + case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES: + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC; + break; default: goto fault; } @@ -1711,6 +1732,9 @@ GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture) case SDL_PIXELFORMAT_NV21: sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21; break; + case SDL_PIXELFORMAT_EXTERNAL_OES: + sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES; + break; default: return SDL_SetError("Unsupported texture format"); } @@ -1741,6 +1765,9 @@ GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture) case SDL_PIXELFORMAT_NV21: sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21; break; + case SDL_PIXELFORMAT_EXTERNAL_OES: + sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES; + break; default: return SDL_SetError("Unsupported texture format"); } @@ -2208,6 +2235,9 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) 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 GL_TEXTURE_EXTERNAL_OES + renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES; +#endif GLES2_ResetState(renderer); diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c index 8b3306b66cd1e..9fe583dbdf078 100644 --- a/src/render/opengles2/SDL_shaders_gles2.c +++ b/src/render/opengles2/SDL_shaders_gles2.c @@ -275,6 +275,21 @@ static const Uint8 GLES2_FragmentSrc_TextureNV21BT709Src_[] = \ NV21_SHADER_BODY \ ; +/* Custom Android video format texture */ +static const Uint8 GLES2_FragmentSrc_TextureExternalOESSrc_[] = " \ + #extension GL_OES_EGL_image_external : require\n\ + precision mediump float; \ + uniform samplerExternalOES u_texture; \ + uniform vec4 u_modulation; \ + varying vec2 v_texCoord; \ + \ + void main() \ + { \ + gl_FragColor = texture2D(u_texture, v_texCoord); \ + gl_FragColor *= u_modulation; \ + } \ +"; + static const GLES2_ShaderInstance GLES2_VertexSrc_Default = { GL_VERTEX_SHADER, GLES2_SOURCE_SHADER, @@ -380,6 +395,13 @@ static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureNV12BT709Src = { GLES2_FragmentSrc_TextureNV12BT709Src_ }; +static const GLES2_ShaderInstance GLES2_FragmentSrc_TextureExternalOESSrc = { + GL_FRAGMENT_SHADER, + GLES2_SOURCE_SHADER, + sizeof(GLES2_FragmentSrc_TextureExternalOESSrc_), + GLES2_FragmentSrc_TextureExternalOESSrc_ +}; + /************************************************************************************************* * Vertex/fragment shader definitions * @@ -490,6 +512,13 @@ static GLES2_Shader GLES2_FragmentShader_TextureNV21BT709Src = { } }; +static GLES2_Shader GLES2_FragmentShader_TextureExternalOESSrc = { + 1, + { + &GLES2_FragmentSrc_TextureExternalOESSrc + } +}; + /************************************************************************************************* * Shader selector * @@ -528,6 +557,8 @@ const GLES2_Shader *GLES2_GetShader(GLES2_ShaderType type) return &GLES2_FragmentShader_TextureNV21BT601Src; case GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC: return &GLES2_FragmentShader_TextureNV21BT709Src; + case GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC: + return &GLES2_FragmentShader_TextureExternalOESSrc; default: return NULL; } diff --git a/src/render/opengles2/SDL_shaders_gles2.h b/src/render/opengles2/SDL_shaders_gles2.h index 6be9c2fd198a2..b7a607539c196 100644 --- a/src/render/opengles2/SDL_shaders_gles2.h +++ b/src/render/opengles2/SDL_shaders_gles2.h @@ -56,6 +56,7 @@ typedef enum GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC, GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC, GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC, + GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC } GLES2_ShaderType; #define GLES2_SOURCE_SHADER (GLenum)-1