SDL_render_gles2.c
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
#include "SDL_assert.h"
#include "SDL_hints.h"
#include "SDL_opengles2.h"
#include "../SDL_sysrender.h"
#include "../../video/SDL_blit.h"
#include "SDL_shaders_gles2.h"
/* To prevent unnecessary window recreation,
* these should match the defaults selected in SDL_GL_ResetAttributes
*/
#define RENDERER_CONTEXT_MAJOR 2
#define RENDERER_CONTEXT_MINOR 0
/* Used to re-create the window with OpenGL ES capability */
extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
/*************************************************************************************************
* Context structures *
*************************************************************************************************/
typedef struct GLES2_FBOList GLES2_FBOList;
struct GLES2_FBOList
{
Uint32 w, h;
GLuint FBO;
GLES2_FBOList *next;
};
typedef struct GLES2_TextureData
{
GLenum texture;
GLenum texture_type;
GLenum pixel_format;
GLenum pixel_type;
void *pixel_data;
int pitch;
/* YUV texture support */
SDL_bool yuv;
SDL_bool nv12;
GLenum texture_v;
GLenum texture_u;
GLES2_FBOList *fbo;
} GLES2_TextureData;
typedef struct GLES2_ShaderCacheEntry
{
GLuint id;
GLES2_ShaderType type;
const GLES2_ShaderInstance *instance;
int references;
struct GLES2_ShaderCacheEntry *prev;
struct GLES2_ShaderCacheEntry *next;
} GLES2_ShaderCacheEntry;
typedef struct GLES2_ShaderCache
{
int count;
GLES2_ShaderCacheEntry *head;
} GLES2_ShaderCache;
typedef struct GLES2_ProgramCacheEntry
{
GLuint id;
GLES2_ShaderCacheEntry *vertex_shader;
GLES2_ShaderCacheEntry *fragment_shader;
GLuint uniform_locations[16];
Uint32 color;
GLfloat projection[4][4];
struct GLES2_ProgramCacheEntry *prev;
struct GLES2_ProgramCacheEntry *next;
} GLES2_ProgramCacheEntry;
typedef struct GLES2_ProgramCache
{
int count;
GLES2_ProgramCacheEntry *head;
GLES2_ProgramCacheEntry *tail;
} GLES2_ProgramCache;
typedef enum
{
GLES2_ATTRIBUTE_POSITION = 0,
GLES2_ATTRIBUTE_TEXCOORD = 1,
GLES2_ATTRIBUTE_ANGLE = 2,
GLES2_ATTRIBUTE_CENTER = 3,
} GLES2_Attribute;
typedef enum
{
GLES2_UNIFORM_PROJECTION,
GLES2_UNIFORM_TEXTURE,
GLES2_UNIFORM_COLOR,
GLES2_UNIFORM_TEXTURE_U,
GLES2_UNIFORM_TEXTURE_V
} GLES2_Uniform;
typedef enum
{
GLES2_IMAGESOURCE_INVALID,
GLES2_IMAGESOURCE_SOLID,
GLES2_IMAGESOURCE_TEXTURE_ABGR,
GLES2_IMAGESOURCE_TEXTURE_ARGB,
GLES2_IMAGESOURCE_TEXTURE_RGB,
GLES2_IMAGESOURCE_TEXTURE_BGR,
GLES2_IMAGESOURCE_TEXTURE_YUV,
GLES2_IMAGESOURCE_TEXTURE_NV12,
GLES2_IMAGESOURCE_TEXTURE_NV21,
GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES
} GLES2_ImageSource;
typedef struct
{
SDL_Rect viewport;
SDL_bool viewport_dirty;
SDL_Texture *texture;
SDL_Texture *target;
SDL_BlendMode blend;
SDL_bool cliprect_enabled_dirty;
SDL_bool cliprect_enabled;
SDL_bool cliprect_dirty;
SDL_Rect cliprect;
SDL_bool texturing;
SDL_bool is_copy_ex;
Uint32 color;
Uint32 clear_color;
int drawablew;
int drawableh;
GLES2_ProgramCacheEntry *program;
GLfloat projection[4][4];
} GLES2_DrawStateCache;
typedef struct GLES2_RenderData
{
SDL_GLContext *context;
SDL_bool debug_enabled;
#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
#include "SDL_gles2funcs.h"
#undef SDL_PROC
GLES2_FBOList *framebuffers;
GLuint window_framebuffer;
int shader_format_count;
GLenum *shader_formats;
GLES2_ShaderCache shader_cache;
GLES2_ProgramCache program_cache;
Uint8 clear_r, clear_g, clear_b, clear_a;
GLuint vertex_buffers[8];
size_t vertex_buffer_size[8];
int current_vertex_buffer;
GLES2_DrawStateCache drawstate;
} GLES2_RenderData;
#define GLES2_MAX_CACHED_PROGRAMS 8
static const float inv255f = 1.0f / 255.0f;
SDL_FORCE_INLINE const char*
GL_TranslateError (GLenum error)
{
#define GL_ERROR_TRANSLATE(e) case e: return #e;
switch (error) {
GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
GL_ERROR_TRANSLATE(GL_NO_ERROR)
default:
return "UNKNOWN";
}
#undef GL_ERROR_TRANSLATE
}
SDL_FORCE_INLINE void
GL_ClearErrors(SDL_Renderer *renderer)
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
if (!data->debug_enabled) {
return;
}
while (data->glGetError() != GL_NO_ERROR) {
continue;
}
}
SDL_FORCE_INLINE int
GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
int ret = 0;
if (!data->debug_enabled) {
return 0;
}
/* check gl errors (can return multiple errors) */
for (;;) {
GLenum error = data->glGetError();
if (error != GL_NO_ERROR) {
if (prefix == NULL || prefix[0] == '\0') {
prefix = "generic";
}
SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
ret = -1;
} else {
break;
}
}
return ret;
}
#if 0
#define GL_CheckError(prefix, renderer)
#else
#define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
#endif
/*************************************************************************************************
* Renderer state APIs *
*************************************************************************************************/
static int GLES2_LoadFunctions(GLES2_RenderData * data)
{
#if SDL_VIDEO_DRIVER_UIKIT
#define __SDL_NOGETPROCADDR__
#elif SDL_VIDEO_DRIVER_ANDROID
#define __SDL_NOGETPROCADDR__
#elif SDL_VIDEO_DRIVER_PANDORA
#define __SDL_NOGETPROCADDR__
#endif
#if defined __SDL_NOGETPROCADDR__
#define SDL_PROC(ret,func,params) data->func=func;
#else
#define SDL_PROC(ret,func,params) \
do { \
data->func = SDL_GL_GetProcAddress(#func); \
if ( ! data->func ) { \
return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \
} \
} while ( 0 );
#endif /* __SDL_NOGETPROCADDR__ */
#include "SDL_gles2funcs.h"
#undef SDL_PROC
return 0;
}
static GLES2_FBOList *
GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h)
{
GLES2_FBOList *result = data->framebuffers;
while ((result) && ((result->w != w) || (result->h != h)) ) {
result = result->next;
}
if (result == NULL) {
result = SDL_malloc(sizeof(GLES2_FBOList));
result->w = w;
result->h = h;
data->glGenFramebuffers(1, &result->FBO);
result->next = data->framebuffers;
data->framebuffers = result;
}
return result;
}
static int
GLES2_ActivateRenderer(SDL_Renderer * renderer)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
if (SDL_GL_GetCurrentContext() != data->context) {
/* Null out the current program to ensure we set it again */
data->drawstate.program = NULL;
if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
return -1;
}
}
GL_ClearErrors(renderer);
return 0;
}
static void
GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
/* According to Apple documentation, we need to finish drawing NOW! */
data->glFinish();
}
}
static int
GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
SDL_GL_GetDrawableSize(renderer->window, w, h);
return 0;
}
static GLenum GetBlendFunc(SDL_BlendFactor factor)
{
switch (factor) {
case SDL_BLENDFACTOR_ZERO:
return GL_ZERO;
case SDL_BLENDFACTOR_ONE:
return GL_ONE;
case SDL_BLENDFACTOR_SRC_COLOR:
return GL_SRC_COLOR;
case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
return GL_ONE_MINUS_SRC_COLOR;
case SDL_BLENDFACTOR_SRC_ALPHA:
return GL_SRC_ALPHA;
case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
return GL_ONE_MINUS_SRC_ALPHA;
case SDL_BLENDFACTOR_DST_COLOR:
return GL_DST_COLOR;
case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
return GL_ONE_MINUS_DST_COLOR;
case SDL_BLENDFACTOR_DST_ALPHA:
return GL_DST_ALPHA;
case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
return GL_ONE_MINUS_DST_ALPHA;
default:
return GL_INVALID_ENUM;
}
}
static GLenum GetBlendEquation(SDL_BlendOperation operation)
{
switch (operation) {
case SDL_BLENDOPERATION_ADD:
return GL_FUNC_ADD;
case SDL_BLENDOPERATION_SUBTRACT:
return GL_FUNC_SUBTRACT;
case SDL_BLENDOPERATION_REV_SUBTRACT:
return GL_FUNC_REVERSE_SUBTRACT;
default:
return GL_INVALID_ENUM;
}
}
static SDL_bool
GLES2_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode)
{
SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
return SDL_FALSE;
}
return SDL_TRUE;
}
static void
GLES2_EvictShader(GLES2_RenderData *data, GLES2_ShaderCacheEntry *entry)
{
/* Unlink the shader from the cache */
if (entry->next) {
entry->next->prev = entry->prev;
}
if (entry->prev) {
entry->prev->next = entry->next;
}
if (data->shader_cache.head == entry) {
data->shader_cache.head = entry->next;
}
--data->shader_cache.count;
/* Deallocate the shader */
data->glDeleteShader(entry->id);
SDL_free(entry);
}
static GLES2_ProgramCacheEntry *
GLES2_CacheProgram(GLES2_RenderData *data, GLES2_ShaderCacheEntry *vertex,
GLES2_ShaderCacheEntry *fragment)
{
GLES2_ProgramCacheEntry *entry;
GLES2_ShaderCacheEntry *shaderEntry;
GLint linkSuccessful;
/* Check if we've already cached this program */
entry = data->program_cache.head;
while (entry) {
if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) {
break;
}
entry = entry->next;
}
if (entry) {
if (data->program_cache.head != entry) {
if (entry->next) {
entry->next->prev = entry->prev;
}
if (entry->prev) {
entry->prev->next = entry->next;
}
entry->prev = NULL;
entry->next = data->program_cache.head;
data->program_cache.head->prev = entry;
data->program_cache.head = entry;
}
return entry;
}
/* Create a program cache entry */
entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
if (!entry) {
SDL_OutOfMemory();
return NULL;
}
entry->vertex_shader = vertex;
entry->fragment_shader = fragment;
/* Create the program and link it */
entry->id = data->glCreateProgram();
data->glAttachShader(entry->id, vertex->id);
data->glAttachShader(entry->id, fragment->id);
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
data->glLinkProgram(entry->id);
data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
if (!linkSuccessful) {
data->glDeleteProgram(entry->id);
SDL_free(entry);
SDL_SetError("Failed to link shader program");
return NULL;
}
/* 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_COLOR] =
data->glGetUniformLocation(entry->id, "u_color");
entry->color = 0;
data->glUseProgram(entry->id);
if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] != -1) {
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */
}
if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] != -1) {
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */
}
if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE] != -1) {
data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
}
if (entry->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
}
if (entry->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f);
}
/* Cache the linked program */
if (data->program_cache.head) {
entry->next = data->program_cache.head;
data->program_cache.head->prev = entry;
} else {
data->program_cache.tail = entry;
}
data->program_cache.head = entry;
++data->program_cache.count;
/* Increment the refcount of the shaders we're using */
++vertex->references;
++fragment->references;
/* Evict the last entry from the cache if we exceed the limit */
if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
shaderEntry = data->program_cache.tail->vertex_shader;
if (--shaderEntry->references <= 0) {
GLES2_EvictShader(data, shaderEntry);
}
shaderEntry = data->program_cache.tail->fragment_shader;
if (--shaderEntry->references <= 0) {
GLES2_EvictShader(data, shaderEntry);
}
data->glDeleteProgram(data->program_cache.tail->id);
data->program_cache.tail = data->program_cache.tail->prev;
if (data->program_cache.tail != NULL) {
SDL_free(data->program_cache.tail->next);
data->program_cache.tail->next = NULL;
}
--data->program_cache.count;
}
return entry;
}
static GLES2_ShaderCacheEntry *
GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type)
{
const GLES2_Shader *shader;
const GLES2_ShaderInstance *instance = NULL;
GLES2_ShaderCacheEntry *entry = NULL;
GLint compileSuccessful = GL_FALSE;
int i, j;
/* Find the corresponding shader */
shader = GLES2_GetShader(type);
if (!shader) {
SDL_SetError("No shader matching the requested characteristics was found");
return NULL;
}
/* Find a matching shader instance that's supported on this hardware */
for (i = 0; i < shader->instance_count && !instance; ++i) {
for (j = 0; j < data->shader_format_count && !instance; ++j) {
if (!shader->instances[i]) {
continue;
}
if (shader->instances[i]->format != data->shader_formats[j]) {
continue;
}
instance = shader->instances[i];
}
}
if (!instance) {
SDL_SetError("The specified shader cannot be loaded on the current platform");
return NULL;
}
/* Check if we've already cached this shader */
entry = data->shader_cache.head;
while (entry) {
if (entry->instance == instance) {
break;
}
entry = entry->next;
}
if (entry) {
return entry;
}
/* Create a shader cache entry */
entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
if (!entry) {
SDL_OutOfMemory();
return NULL;
}
entry->type = type;
entry->instance = instance;
/* Compile or load the selected shader instance */
entry->id = data->glCreateShader(instance->type);
if (instance->format == (GLenum)-1) {
data->glShaderSource(entry->id, 1, (const char **)(char *)&instance->data, NULL);
data->glCompileShader(entry->id);
data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
} else {
data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
compileSuccessful = GL_TRUE;
}
if (!compileSuccessful) {
SDL_bool isstack = SDL_FALSE;
char *info = NULL;
int length = 0;
data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
if (length > 0) {
info = SDL_small_alloc(char, length, &isstack);
if (info) {
data->glGetShaderInfoLog(entry->id, length, &length, info);
}
}
if (info) {
SDL_SetError("Failed to load the shader: %s", info);
SDL_small_free(info, isstack);
} else {
SDL_SetError("Failed to load the shader");
}
data->glDeleteShader(entry->id);
SDL_free(entry);
return NULL;
}
/* Link the shader entry in at the front of the cache */
if (data->shader_cache.head) {
entry->next = data->shader_cache.head;
data->shader_cache.head->prev = entry;
}
data->shader_cache.head = entry;
++data->shader_cache.count;
return entry;
}
static int
GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, int w, int h)
{
GLES2_ShaderCacheEntry *vertex = NULL;
GLES2_ShaderCacheEntry *fragment = NULL;
GLES2_ShaderType vtype, ftype;
GLES2_ProgramCacheEntry *program;
/* Select an appropriate shader pair for the specified modes */
vtype = GLES2_SHADER_VERTEX_DEFAULT;
switch (source) {
case GLES2_IMAGESOURCE_SOLID:
ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_ABGR:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_ARGB:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_RGB:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_BGR:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
break;
case GLES2_IMAGESOURCE_TEXTURE_YUV:
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
case SDL_YUV_CONVERSION_JPEG:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG_SRC;
break;
case SDL_YUV_CONVERSION_BT601:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601_SRC;
break;
case SDL_YUV_CONVERSION_BT709:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709_SRC;
break;
default:
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
goto fault;
}
break;
case GLES2_IMAGESOURCE_TEXTURE_NV12:
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
case SDL_YUV_CONVERSION_JPEG:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG_SRC;
break;
case SDL_YUV_CONVERSION_BT601:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601_SRC;
break;
case SDL_YUV_CONVERSION_BT709:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709_SRC;
break;
default:
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
goto fault;
}
break;
case GLES2_IMAGESOURCE_TEXTURE_NV21:
switch (SDL_GetYUVConversionModeForResolution(w, h)) {
case SDL_YUV_CONVERSION_JPEG:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC;
break;
case SDL_YUV_CONVERSION_BT601:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC;
break;
case SDL_YUV_CONVERSION_BT709:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC;
break;
default:
SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h));
goto fault;
}
break;
case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC;
break;
default:
goto fault;
}
/* Load the requested shaders */
vertex = GLES2_CacheShader(data, vtype);
if (!vertex) {
goto fault;
}
fragment = GLES2_CacheShader(data, ftype);
if (!fragment) {
goto fault;
}
/* Check if we need to change programs at all */
if (data->drawstate.program &&
data->drawstate.program->vertex_shader == vertex &&
data->drawstate.program->fragment_shader == fragment) {
return 0;
}
/* Generate a matching program */
program = GLES2_CacheProgram(data, vertex, fragment);
if (!program) {
goto fault;
}
/* Select that program in OpenGL */
data->glUseProgram(program->id);
/* Set the current program */
data->drawstate.program = program;
/* Clean up and return */
return 0;
fault:
if (vertex && vertex->references <= 0) {
GLES2_EvictShader(data, vertex);
}
if (fragment && fragment->references <= 0) {
GLES2_EvictShader(data, fragment);
}
data->drawstate.program = NULL;
return -1;
}
static int
GLES2_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd)
{
return 0; /* nothing to do in this backend. */
}
static int
GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count)
{
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 0, &cmd->data.draw.first);
int i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
for (i = 0; i < count; i++) {
*(verts++) = 0.5f + points[i].x;
*(verts++) = 0.5f + points[i].y;
}
return 0;
}
static int
GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count)
{
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 0, &cmd->data.draw.first);
int i;
if (!verts) {
return -1;
}
cmd->data.draw.count = count;
for (i = 0; i < count; i++) {
const SDL_FRect *rect = &rects[i];
const GLfloat minx = rect->x;
const GLfloat maxx = rect->x + rect->w;
const GLfloat miny = rect->y;
const GLfloat maxy = rect->y + rect->h;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
}
return 0;
}
static int
GLES2_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_FRect * dstrect)
{
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
cmd->data.draw.count = 1;
minx = dstrect->x;
miny = dstrect->y;
maxx = dstrect->x + dstrect->w;
maxy = dstrect->y + dstrect->h;
minu = (GLfloat) srcrect->x / texture->w;
maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
minv = (GLfloat) srcrect->y / texture->h;
maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = maxu;
*(verts++) = maxv;
return 0;
}
static int
GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture,
const SDL_Rect * srcquad, const SDL_FRect * dstrect,
const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
{
/* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0);
const GLfloat s = (GLfloat) SDL_sin(radian_angle);
const GLfloat c = (GLfloat) SDL_cos(radian_angle) - 1.0f;
const GLfloat centerx = center->x + dstrect->x;
const GLfloat centery = center->y + dstrect->y;
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 32 * sizeof (GLfloat), 0, &cmd->data.draw.first);
if (!verts) {
return -1;
}
if (flip & SDL_FLIP_HORIZONTAL) {
minx = dstrect->x + dstrect->w;
maxx = dstrect->x;
} else {
minx = dstrect->x;
maxx = dstrect->x + dstrect->w;
}
if (flip & SDL_FLIP_VERTICAL) {
miny = dstrect->y + dstrect->h;
maxy = dstrect->y;
} else {
miny = dstrect->y;
maxy = dstrect->y + dstrect->h;
}
minu = ((GLfloat) srcquad->x) / ((GLfloat) texture->w);
maxu = ((GLfloat) (srcquad->x + srcquad->w)) / ((GLfloat) texture->w);
minv = ((GLfloat) srcquad->y) / ((GLfloat) texture->h);
maxv = ((GLfloat) (srcquad->y + srcquad->h)) / ((GLfloat) texture->h);
cmd->data.draw.count = 1;
*(verts++) = minx;
*(verts++) = miny;
*(verts++) = maxx;
*(verts++) = miny;
*(verts++) = minx;
*(verts++) = maxy;
*(verts++) = maxx;
*(verts++) = maxy;
*(verts++) = minu;
*(verts++) = minv;
*(verts++) = maxu;
*(verts++) = minv;
*(verts++) = minu;
*(verts++) = maxv;
*(verts++) = maxu;
*(verts++) = maxv;
*(verts++) = s;
*(verts++) = c;
*(verts++) = s;
*(verts++) = c;
*(verts++) = s;
*(verts++) = c;
*(verts++) = s;
*(verts++) = c;
*(verts++) = centerx;
*(verts++) = centery;
*(verts++) = centerx;
*(verts++) = centery;
*(verts++) = centerx;
*(verts++) = centery;
*(verts++) = centerx;
*(verts++) = centery;
return 0;
}
static int
SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc)
{
const SDL_bool was_copy_ex = data->drawstate.is_copy_ex;
const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX);
SDL_Texture *texture = cmd->data.draw.texture;
const SDL_BlendMode blend = cmd->data.draw.blend;
GLES2_ProgramCacheEntry *program;
SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
if (data->drawstate.viewport_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
data->glViewport(viewport->x,
data->drawstate.target ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
viewport->w, viewport->h);
if (viewport->w && viewport->h) {
data->drawstate.projection[0][0] = 2.0f / viewport->w;
data->drawstate.projection[1][1] = (data->drawstate.target ? 2.0f : -2.0f) / viewport->h;
data->drawstate.projection[3][1] = data->drawstate.target ? -1.0f : 1.0f;
}
data->drawstate.viewport_dirty = SDL_FALSE;
}
if (data->drawstate.cliprect_enabled_dirty) {
if (!data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
} else {
data->glEnable(GL_SCISSOR_TEST);
}
data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
}
if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
const SDL_Rect *viewport = &data->drawstate.viewport;
const SDL_Rect *rect = &data->drawstate.cliprect;
data->glScissor(viewport->x + rect->x,
data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
rect->w, rect->h);
data->drawstate.cliprect_dirty = SDL_FALSE;
}
if (texture != data->drawstate.texture) {
if ((texture != NULL) != data->drawstate.texturing) {
if (texture == NULL) {
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_FALSE;
} else {
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_TEXCOORD);
data->drawstate.texturing = SDL_TRUE;
}
}
if (texture) {
GLES2_TextureData *tdata = (GLES2_TextureData *) texture->driverdata;
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);
} else 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->drawstate.texture = texture;
}
if (texture) {
data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 8)));
}
if (GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) {
return -1;
}
program = data->drawstate.program;
if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)) != 0) {
data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection);
SDL_memcpy(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection));
}
}
if (program->uniform_locations[GLES2_UNIFORM_COLOR] != -1) {
if (data->drawstate.color != program->color) {
const Uint8 r = (data->drawstate.color >> 16) & 0xFF;
const Uint8 g = (data->drawstate.color >> 8) & 0xFF;
const Uint8 b = (data->drawstate.color >> 0) & 0xFF;
const Uint8 a = (data->drawstate.color >> 24) & 0xFF;
data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
program->color = data->drawstate.color;
}
}
if (blend != data->drawstate.blend) {
if (blend == SDL_BLENDMODE_NONE) {
data->glDisable(GL_BLEND);
} else {
data->glEnable(GL_BLEND);
data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
}
data->drawstate.blend = blend;
}
/* all drawing commands use this */
data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first);
if (is_copy_ex != was_copy_ex) {
if (is_copy_ex) {
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
data->glEnableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
} else {
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_ANGLE);
data->glDisableVertexAttribArray((GLenum) GLES2_ATTRIBUTE_CENTER);
}
data->drawstate.is_copy_ex = is_copy_ex;
}
if (is_copy_ex) {
data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16)));
data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24)));
}
return 0;
}
static int
SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd)
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
SDL_Texture *texture = cmd->data.draw.texture;
/* Pick an appropriate shader */
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;
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;
case SDL_PIXELFORMAT_EXTERNAL_OES:
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
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 {
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;
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;
case SDL_PIXELFORMAT_EXTERNAL_OES:
sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
break;
default:
return SDL_SetError("Unsupported texture format");
}
}
return SetDrawState(data, cmd, sourceType);
}
static int
GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888));
const int vboidx = data->current_vertex_buffer;
const GLuint vbo = data->vertex_buffers[vboidx];
size_t i;
if (GLES2_ActivateRenderer(renderer) < 0) {
return -1;
}
data->drawstate.target = renderer->target;
if (!data->drawstate.target) {
SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh);
}
/* upload the new VBO data for this set of commands. */
data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
if (data->vertex_buffer_size[vboidx] < vertsize) {
data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW);
data->vertex_buffer_size[vboidx] = vertsize;
} else {
data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices);
}
/* cycle through a few VBOs so the GL has some time with the data before we replace it. */
data->current_vertex_buffer++;
if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
data->current_vertex_buffer = 0;
}
while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR: {
const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
data->drawstate.color = ((a << 24) | (r << 16) | (g << 8) | b);
break;
}
case SDL_RENDERCMD_SETVIEWPORT: {
SDL_Rect *viewport = &data->drawstate.viewport;
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
data->drawstate.viewport_dirty = SDL_TRUE;
}
break;
}
case SDL_RENDERCMD_SETCLIPRECT: {
const SDL_Rect *rect = &cmd->data.cliprect.rect;
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
data->drawstate.cliprect_dirty = SDL_TRUE;
}
break;
}
case SDL_RENDERCMD_CLEAR: {
const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r;
const Uint8 g = cmd->data.color.g;
const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
if (color != data->drawstate.clear_color) {
const GLfloat fr = ((GLfloat) r) * inv255f;
const GLfloat fg = ((GLfloat) g) * inv255f;
const GLfloat fb = ((GLfloat) b) * inv255f;
const GLfloat fa = ((GLfloat) a) * inv255f;
data->glClearColor(fr, fg, fb, fa);
data->drawstate.clear_color = color;
}
if (data->drawstate.cliprect_enabled) {
data->glDisable(GL_SCISSOR_TEST);
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
data->glClear(GL_COLOR_BUFFER_BIT);
break;
}
case SDL_RENDERCMD_DRAW_POINTS: {
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
data->glDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count);
}
break;
}
case SDL_RENDERCMD_DRAW_LINES: {
const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first);
const size_t count = cmd->data.draw.count;
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) {
/* GL_LINE_LOOP takes care of the final segment */
data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1));
} else {
data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count);
/* We need to close the endpoint of the line */
data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1);
}
}
break;
}
case SDL_RENDERCMD_FILL_RECTS: {
const size_t count = cmd->data.draw.count;
size_t offset = 0;
if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID) == 0) {
for (i = 0; i < count; ++i, offset += 4) {
data->glDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4);
}
}
break;
}
case SDL_RENDERCMD_COPY:
case SDL_RENDERCMD_COPY_EX: {
if (SetCopyState(renderer, cmd) == 0) {
data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
break;
}
case SDL_RENDERCMD_NO_OP:
break;
}
cmd = cmd->next;
}
return GL_CheckError("", renderer);
}
static void
GLES2_DestroyRenderer(SDL_Renderer *renderer)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
/* Deallocate everything */
if (data) {
GLES2_ActivateRenderer(renderer);
{
GLES2_ShaderCacheEntry *entry;
GLES2_ShaderCacheEntry *next;
entry = data->shader_cache.head;
while (entry) {
data->glDeleteShader(entry->id);
next = entry->next;
SDL_free(entry);
entry = next;
}
}
{
GLES2_ProgramCacheEntry *entry;
GLES2_ProgramCacheEntry *next;
entry = data->program_cache.head;
while (entry) {
data->glDeleteProgram(entry->id);
next = entry->next;
SDL_free(entry);
entry = next;
}
}
if (data->context) {
while (data->framebuffers) {
GLES2_FBOList *nextnode = data->framebuffers->next;
data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
GL_CheckError("", renderer);
SDL_free(data->framebuffers);
data->framebuffers = nextnode;
}
data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
GL_CheckError("", renderer);
SDL_GL_DeleteContext(data->context);
}
SDL_free(data->shader_formats);
SDL_free(data);
}
SDL_free(renderer);
}
static int
GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *data;
GLenum format;
GLenum type;
GLenum scaleMode;
GLES2_ActivateRenderer(renderer);
renderdata->drawstate.texture = NULL; /* we trash this state. */
/* Determine the corresponding GLES texture format params */
switch (texture->format)
{
case SDL_PIXELFORMAT_ARGB8888:
case SDL_PIXELFORMAT_ABGR8888:
case SDL_PIXELFORMAT_RGB888:
case SDL_PIXELFORMAT_BGR888:
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
case SDL_PIXELFORMAT_IYUV:
case SDL_PIXELFORMAT_YV12:
case SDL_PIXELFORMAT_NV12:
case SDL_PIXELFORMAT_NV21:
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));
data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
data->texture_u = 0;
data->texture_v = 0;
scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR;
/* Allocate a blob for image renderdata */
if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
size_t size;
data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
size = texture->h * data->pitch;
if (data->yuv) {
/* Need to add size for the U and V planes */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
} else if (data->nv12) {
/* Need to add size for the U/V plane */
size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
}
data->pixel_data = SDL_calloc(1, size);
if (!data->pixel_data) {
SDL_free(data);
return SDL_OutOfMemory();
}
}
/* 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 + 1) / 2, (texture->h + 1) / 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 + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
if (GL_CheckError("glTexImage2D()", renderer) < 0) {
return -1;
}
} else 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 + 1) / 2, (texture->h + 1) / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 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);
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);
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) {
data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
} else {
data->fbo = NULL;
}
return GL_CheckError("", renderer);
}
static int
GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
{
Uint8 *blob = NULL;
Uint8 *src;
int src_pitch;
int y;
if ((width == 0) || (height == 0) || (bpp == 0)) {
return 0; /* nothing to do */
}
/* Reformat the texture data into a tightly packed array */
src_pitch = width * bpp;
src = (Uint8 *)pixels;
if (pitch != src_pitch) {
blob = (Uint8 *)SDL_malloc(src_pitch * height);
if (!blob) {
return SDL_OutOfMemory();
}
src = blob;
for (y = 0; y < height; ++y)
{
SDL_memcpy(src, pixels, src_pitch);
src += src_pitch;
pixels = (Uint8 *)pixels + pitch;
}
src = blob;
}
data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
if (blob) {
SDL_free(blob);
}
return 0;
}
static int
GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
const void *pixels, int pitch)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
/* Bail out if we're supposed to update an empty rectangle */
if (rect->w <= 0 || rect->h <= 0) {
return 0;
}
data->drawstate.texture = NULL; /* we trash this state. */
/* Create a texture subimage with the supplied data */
data->glBindTexture(tdata->texture_type, tdata->texture);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x,
rect->y,
rect->w,
rect->h,
tdata->pixel_format,
tdata->pixel_type,
pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
if (tdata->yuv) {
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + rect->h * pitch);
if (texture->format == SDL_PIXELFORMAT_YV12) {
data->glBindTexture(tdata->texture_type, tdata->texture_v);
} else {
data->glBindTexture(tdata->texture_type, tdata->texture_u);
}
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
(rect->w + 1) / 2,
(rect->h + 1) / 2,
tdata->pixel_format,
tdata->pixel_type,
pixels, (pitch + 1) / 2, 1);
/* Skip to the correct offset into the next texture */
pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2));
if (texture->format == SDL_PIXELFORMAT_YV12) {
data->glBindTexture(tdata->texture_type, tdata->texture_u);
} else {
data->glBindTexture(tdata->texture_type, tdata->texture_v);
}
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
(rect->w + 1) / 2,
(rect->h + 1) / 2,
tdata->pixel_format,
tdata->pixel_type,
pixels, (pitch + 1) / 2, 1);
} else 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 + 1) / 2,
(rect->h + 1) / 2,
GL_LUMINANCE_ALPHA,
GL_UNSIGNED_BYTE,
pixels, 2 * ((pitch + 1) / 2), 2);
}
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_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
/* Bail out if we're supposed to update an empty rectangle */
if (rect->w <= 0 || rect->h <= 0) {
return 0;
}
data->drawstate.texture = NULL; /* we trash this state. */
data->glBindTexture(tdata->texture_type, tdata->texture_v);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
(rect->w + 1) / 2,
(rect->h + 1) / 2,
tdata->pixel_format,
tdata->pixel_type,
Vplane, Vpitch, 1);
data->glBindTexture(tdata->texture_type, tdata->texture_u);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x / 2,
rect->y / 2,
(rect->w + 1) / 2,
(rect->h + 1) / 2,
tdata->pixel_format,
tdata->pixel_type,
Uplane, Upitch, 1);
data->glBindTexture(tdata->texture_type, tdata->texture);
GLES2_TexSubImage2D(data, tdata->texture_type,
rect->x,
rect->y,
rect->w,
rect->h,
tdata->pixel_format,
tdata->pixel_type,
Yplane, Ypitch, 1);
return GL_CheckError("glTexSubImage2D()", renderer);
}
static int
GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
void **pixels, int *pitch)
{
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
/* Retrieve the buffer/pitch for the specified region */
*pixels = (Uint8 *)tdata->pixel_data +
(tdata->pitch * rect->y) +
(rect->x * SDL_BYTESPERPIXEL(texture->format));
*pitch = tdata->pitch;
return 0;
}
static void
GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
SDL_Rect rect;
/* We do whole texture updates, at least for now */
rect.x = 0;
rect.y = 0;
rect.w = texture->w;
rect.h = texture->h;
GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
}
static int
GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
{
GLES2_RenderData *data = (GLES2_RenderData *) renderer->driverdata;
GLES2_TextureData *texturedata = NULL;
GLenum status;
data->drawstate.viewport_dirty = SDL_TRUE;
if (texture == NULL) {
data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
} else {
texturedata = (GLES2_TextureData *) texture->driverdata;
data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
/* TODO: check if texture pixel format allows this operation */
data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
/* Check FBO status */
status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
return SDL_SetError("glFramebufferTexture2D() failed");
}
}
return 0;
}
static void
GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
if (data->drawstate.texture == texture) {
data->drawstate.texture = NULL;
}
if (data->drawstate.target == texture) {
data->drawstate.target = NULL;
}
/* Destroy the 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;
}
}
static int
GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
size_t buflen;
void *temp_pixels;
int temp_pitch;
Uint8 *src, *dst, *tmp;
int w, h, length, rows;
int status;
temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
buflen = (size_t) (rect->h * temp_pitch);
if (buflen == 0) {
return 0; /* nothing to do. */
}
temp_pixels = SDL_malloc(buflen);
if (!temp_pixels) {
return SDL_OutOfMemory();
}
SDL_GetRendererOutputSize(renderer, &w, &h);
data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
if (GL_CheckError("glReadPixels()", renderer) < 0) {
return -1;
}
/* Flip the rows to be top-down if necessary */
if (!renderer->target) {
SDL_bool isstack;
length = rect->w * SDL_BYTESPERPIXEL(temp_format);
src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
dst = (Uint8*)temp_pixels;
tmp = SDL_small_alloc(Uint8, length, &isstack);
rows = rect->h / 2;
while (rows--) {
SDL_memcpy(tmp, dst, length);
SDL_memcpy(dst, src, length);
SDL_memcpy(src, tmp, length);
dst += temp_pitch;
src -= temp_pitch;
}
SDL_small_free(tmp, isstack);
}
status = SDL_ConvertPixels(rect->w, rect->h,
temp_format, temp_pixels, temp_pitch,
pixel_format, pixels, pitch);
SDL_free(temp_pixels);
return status;
}
static void
GLES2_RenderPresent(SDL_Renderer *renderer)
{
/* Tell the video driver to swap buffers */
SDL_GL_SwapWindow(renderer->window);
}
/*************************************************************************************************
* Bind/unbinding of textures
*************************************************************************************************/
static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
data->glBindTexture(texturedata->texture_type, texturedata->texture);
data->drawstate.texture = texture;
if (texw) {
*texw = 1.0;
}
if (texh) {
*texh = 1.0;
}
return 0;
}
static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
{
GLES2_RenderData *data = (GLES2_RenderData *)renderer->driverdata;
GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
GLES2_ActivateRenderer(renderer);
data->glBindTexture(texturedata->texture_type, 0);
data->drawstate.texture = NULL;
return 0;
}
/*************************************************************************************************
* Renderer instantiation *
*************************************************************************************************/
#ifdef ZUNE_HD
#define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
#endif
static SDL_Renderer *
GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
{
SDL_Renderer *renderer;
GLES2_RenderData *data;
GLint nFormats;
#ifndef ZUNE_HD
GLboolean hasCompiler;
#endif
Uint32 window_flags = 0; /* -Wconditional-uninitialized */
GLint window_framebuffer;
GLint value;
int profile_mask = 0, major = 0, minor = 0;
SDL_bool changed_window = SDL_FALSE;
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask) < 0) {
goto error;
}
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major) < 0) {
goto error;
}
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor) < 0) {
goto error;
}
window_flags = SDL_GetWindowFlags(window);
/* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */
if (!(window_flags & SDL_WINDOW_OPENGL) ||
profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) {
changed_window = SDL_TRUE;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
goto error;
}
}
/* Create the renderer struct */
renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
if (!renderer) {
SDL_OutOfMemory();
goto error;
}
data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
if (!data) {
SDL_free(renderer);
SDL_OutOfMemory();
goto error;
}
renderer->info = GLES2_RenderDriver.info;
renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
renderer->driverdata = data;
renderer->window = window;
/* Create an OpenGL ES 2.0 context */
data->context = SDL_GL_CreateContext(window);
if (!data->context) {
SDL_free(renderer);
SDL_free(data);
goto error;
}
if (SDL_GL_MakeCurrent(window, data->context) < 0) {
SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error;
}
if (GLES2_LoadFunctions(data) < 0) {
SDL_GL_DeleteContext(data->context);
SDL_free(renderer);
SDL_free(data);
goto error;
}
#if __WINRT__
/* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
* is turned on. Not doing so will freeze the screen's contents to that
* of the first drawn frame.
*/
flags |= SDL_RENDERER_PRESENTVSYNC;
#endif
if (flags & SDL_RENDERER_PRESENTVSYNC) {
SDL_GL_SetSwapInterval(1);
} else {
SDL_GL_SetSwapInterval(0);
}
if (SDL_GL_GetSwapInterval() > 0) {
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
/* Check for debug output support */
if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
(value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
data->debug_enabled = SDL_TRUE;
}
value = 0;
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
renderer->info.max_texture_width = value;
value = 0;
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
renderer->info.max_texture_height = value;
/* Determine supported shader formats */
/* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
#ifdef ZUNE_HD
nFormats = 1;
#else /* !ZUNE_HD */
data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
if (hasCompiler) {
++nFormats;
}
#endif /* ZUNE_HD */
data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
if (!data->shader_formats) {
GLES2_DestroyRenderer(renderer);
SDL_OutOfMemory();
goto error;
}
data->shader_format_count = nFormats;
#ifdef ZUNE_HD
data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
#else /* !ZUNE_HD */
data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
if (hasCompiler) {
data->shader_formats[nFormats - 1] = (GLenum)-1;
}
#endif /* ZUNE_HD */
/* we keep a few of these and cycle through them, so data can live for a few frames. */
data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
data->framebuffers = NULL;
data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
data->window_framebuffer = (GLuint)window_framebuffer;
/* Populate the function pointers for the module */
renderer->WindowEvent = GLES2_WindowEvent;
renderer->GetOutputSize = GLES2_GetOutputSize;
renderer->SupportsBlendMode = GLES2_SupportsBlendMode;
renderer->CreateTexture = GLES2_CreateTexture;
renderer->UpdateTexture = GLES2_UpdateTexture;
renderer->UpdateTextureYUV = GLES2_UpdateTextureYUV;
renderer->LockTexture = GLES2_LockTexture;
renderer->UnlockTexture = GLES2_UnlockTexture;
renderer->SetRenderTarget = GLES2_SetRenderTarget;
renderer->QueueSetViewport = GLES2_QueueSetViewport;
renderer->QueueSetDrawColor = GLES2_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */
renderer->QueueDrawPoints = GLES2_QueueDrawPoints;
renderer->QueueDrawLines = GLES2_QueueDrawPoints; /* lines and points queue vertices the same way. */
renderer->QueueFillRects = GLES2_QueueFillRects;
renderer->QueueCopy = GLES2_QueueCopy;
renderer->QueueCopyEx = GLES2_QueueCopyEx;
renderer->RunCommandQueue = GLES2_RunCommandQueue;
renderer->RenderReadPixels = GLES2_RenderReadPixels;
renderer->RenderPresent = GLES2_RenderPresent;
renderer->DestroyTexture = GLES2_DestroyTexture;
renderer->DestroyRenderer = GLES2_DestroyRenderer;
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;
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
/* Set up parameters for rendering */
data->glActiveTexture(GL_TEXTURE0);
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
data->drawstate.blend = SDL_BLENDMODE_INVALID;
data->drawstate.color = 0xFFFFFFFF;
data->drawstate.clear_color = 0xFFFFFFFF;
data->drawstate.projection[3][0] = -1.0f;
data->drawstate.projection[3][3] = 1.0f;
GL_CheckError("", renderer);
return renderer;
error:
if (changed_window) {
/* Uh oh, better try to put it back... */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
SDL_RecreateWindow(window, window_flags);
}
return NULL;
}
SDL_RenderDriver GLES2_RenderDriver = {
GLES2_CreateRenderer,
{
"opengles2",
(SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
4,
{
SDL_PIXELFORMAT_ARGB8888,
SDL_PIXELFORMAT_ABGR8888,
SDL_PIXELFORMAT_RGB888,
SDL_PIXELFORMAT_BGR888
},
0,
0
}
};
#endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */
format
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
points
GLfixed GLfixed GLint GLint GLfixed points
Definition: SDL_opengl_glext.h:4558
c
const GLubyte * c
Definition: SDL_opengl_glext.h:11093
Uint32
uint32_t Uint32
Definition: SDL_stdinc.h:203
GL_ONE
#define GL_ONE
Definition: SDL_opengl.h:401
SDL_Renderer::GL_UnbindTexture
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:164
SDL_BLENDOPERATION_SUBTRACT
@ SDL_BLENDOPERATION_SUBTRACT
Definition: SDL_blendmode.h:65
GL_POINTS
#define GL_POINTS
Definition: SDL_opengl.h:216
SDL_small_free
#define SDL_small_free(ptr, isstack)
Definition: SDL_internal.h:40
offset
GLintptr offset
Definition: SDL_opengl_glext.h:538
target
GLenum target
Definition: SDL_opengl_glext.h:1551
blendMode
static SDL_BlendMode blendMode
Definition: testdraw2.c:34
SDL_BLENDOPERATION_ADD
@ SDL_BLENDOPERATION_ADD
Definition: SDL_blendmode.h:64
SDL_RecreateWindow
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
Definition: SDL_video.c:1614
GLvoid
void GLvoid
Definition: SDL_opengl.h:179
tail
SDL_EventEntry * tail
Definition: SDL_events.c:81
SDL_BLENDFACTOR_SRC_ALPHA
@ SDL_BLENDFACTOR_SRC_ALPHA
Definition: SDL_blendmode.h:81
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
@ SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA
Definition: SDL_blendmode.h:82
GL_TEXTURE_2D
#define GL_TEXTURE_2D
Definition: SDL_opengl.h:671
GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER
Definition: SDL_opengl_glext.h:481
SDL_BLENDOPERATION_REV_SUBTRACT
@ SDL_BLENDOPERATION_REV_SUBTRACT
Definition: SDL_blendmode.h:66
xoffset
GLint GLint xoffset
Definition: SDL_opengl.h:1573
SDL_Renderer::QueueCopyEx
int(* QueueCopyEx)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
Definition: SDL_sysrender.h:140
GLES2_RenderDriver
SDL_RenderDriver GLES2_RenderDriver
SDL_PIXELFORMAT_RGB888
@ SDL_PIXELFORMAT_RGB888
Definition: SDL_pixels.h:236
SDL_AllocateRenderVertices
void * SDL_AllocateRenderVertices(SDL_Renderer *renderer, const size_t numbytes, const size_t alignment, size_t *offset)
Definition: SDL_render.c:284
GL_FALSE
#define GL_FALSE
Definition: SDL_opengl.h:199
SDL_opengles2.h
SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR
@ SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR
Definition: SDL_blendmode.h:84
SDL_RenderCommand::cliprect
struct SDL_RenderCommand::@30::@32 cliprect
SDL_Renderer::RunCommandQueue
int(* RunCommandQueue)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
Definition: SDL_sysrender.h:143
SDL_PIXELFORMAT_NV21
@ SDL_PIXELFORMAT_NV21
Definition: SDL_pixels.h:289
SDL_FPoint::x
float x
Definition: SDL_rect.h:62
SDL_FRect::h
float h
Definition: SDL_rect.h:92
source
GLsizei GLsizei GLchar * source
Definition: SDL_opengl_glext.h:677
NULL
#define NULL
Definition: begin_code.h:167
SDL_ScaleModeNearest
@ SDL_ScaleModeNearest
Definition: SDL_sysrender.h:37
GL_NEAREST
#define GL_NEAREST
Definition: SDL_opengl.h:704
b
GLboolean GLboolean GLboolean b
Definition: SDL_opengl_glext.h:1109
SDL_Renderer::SetRenderTarget
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:155
width
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
GL_FRAMEBUFFER_BINDING
#define GL_FRAMEBUFFER_BINDING
Definition: SDL_opengl_glext.h:1014
GL_INFO_LOG_LENGTH
#define GL_INFO_LOG_LENGTH
Definition: SDL_opengl_glext.h:634
g
GLboolean GLboolean g
Definition: SDL_opengl_glext.h:1109
GL_MAX_TEXTURE_SIZE
#define GL_MAX_TEXTURE_SIZE
Definition: SDL_opengl.h:536
SDL_GL_CreateContext
#define SDL_GL_CreateContext
Definition: SDL_dynapi_overrides.h:559
count
GLuint GLuint GLsizei count
Definition: SDL_opengl.h:1571
GL_FUNC_ADD
#define GL_FUNC_ADD
Definition: SDL_opengl.h:1652
SDL_GetWindowFlags
#define SDL_GetWindowFlags
Definition: SDL_dynapi_overrides.h:518
SDL_RenderCommand::next
struct SDL_RenderCommand * next
Definition: SDL_sysrender.h:110
SDL_PIXELFORMAT_BGR888
@ SDL_PIXELFORMAT_BGR888
Definition: SDL_pixels.h:242
SDL_BlendOperation
SDL_BlendOperation
The blend operation used when combining source and destination pixel components.
Definition: SDL_blendmode.h:62
GL_ONE_MINUS_DST_ALPHA
#define GL_ONE_MINUS_DST_ALPHA
Definition: SDL_opengl.h:407
r
GLdouble GLdouble GLdouble r
Definition: SDL_opengl.h:2079
SDL_PIXELFORMAT_EXTERNAL_OES
@ SDL_PIXELFORMAT_EXTERNAL_OES
Definition: SDL_pixels.h:291
SDL_WINDOW_OPENGL
@ SDL_WINDOW_OPENGL
Definition: SDL_video.h:101
viewport
SDL_Rect viewport
Definition: testviewport.c:28
SDL_RenderDriver
Definition: SDL_sysrender.h:236
GL_FRAMEBUFFER
#define GL_FRAMEBUFFER
Definition: SDL_opengl_glext.h:1051
SDL_FRect::x
float x
Definition: SDL_rect.h:89
GL_COLOR_BUFFER_BIT
#define GL_COLOR_BUFFER_BIT
Definition: SDL_opengl.h:742
SDL_Renderer::WindowEvent
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
Definition: SDL_sysrender.h:126
GL_UNPACK_ALIGNMENT
#define GL_UNPACK_ALIGNMENT
Definition: SDL_opengl.h:658
SDL_FPoint::y
float y
Definition: SDL_rect.h:63
a
GLboolean GLboolean GLboolean GLboolean a
Definition: SDL_opengl_glext.h:1109
SDL_gles2funcs.h
GL_SHADER_BINARY_FORMATS
#define GL_SHADER_BINARY_FORMATS
Definition: SDL_opengl_glext.h:1842
SDL_GL_CONTEXT_MINOR_VERSION
@ SDL_GL_CONTEXT_MINOR_VERSION
Definition: SDL_video.h:218
GLboolean
unsigned char GLboolean
Definition: SDL_opengl.h:177
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
SDL_RendererFlip
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
Definition: SDL_render.h:111
SDL_small_alloc
#define SDL_small_alloc(type, count, pisstack)
Definition: SDL_internal.h:39
length
GLuint GLsizei GLsizei * length
Definition: SDL_opengl_glext.h:669
SDL_GL_CONTEXT_FLAGS
@ SDL_GL_CONTEXT_FLAGS
Definition: SDL_video.h:220
SDL_Rect::x
int x
Definition: SDL_rect.h:79
GL_LUMINANCE_ALPHA
#define GL_LUMINANCE_ALPHA
Definition: SDL_opengl.h:511
SDL_RENDERCMD_COPY
@ SDL_RENDERCMD_COPY
Definition: SDL_sysrender.h:82
shader
GLuint shader
Definition: SDL_opengl_glext.h:659
GL_BLEND
#define GL_BLEND
Definition: SDL_opengl.h:397
SDL_RENDERCMD_SETCLIPRECT
@ SDL_RENDERCMD_SETCLIPRECT
Definition: SDL_sysrender.h:76
result
GLuint64EXT * result
Definition: SDL_opengl_glext.h:9432
SDL_PIXELFORMAT_IYUV
@ SDL_PIXELFORMAT_IYUV
Definition: SDL_pixels.h:279
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
SDL_Rect::w
int w
Definition: SDL_rect.h:80
GL_TEXTURE_WRAP_T
#define GL_TEXTURE_WRAP_T
Definition: SDL_opengl.h:673
GL_ZERO
#define GL_ZERO
Definition: SDL_opengl.h:400
SDL_Window
The type used to identify a window.
Definition: SDL_sysvideo.h:73
yoffset
GLint GLint GLint yoffset
Definition: SDL_opengl.h:1573
SDL_YUV_CONVERSION_JPEG
@ SDL_YUV_CONVERSION_JPEG
Definition: SDL_surface.h:106
dst
GLenum GLenum dst
Definition: SDL_opengl_glext.h:1737
GL_LINE_STRIP
#define GL_LINE_STRIP
Definition: SDL_opengl.h:219
SDL_GL_GetDrawableSize
#define SDL_GL_GetDrawableSize
Definition: SDL_dynapi_overrides.h:563
GL_INVALID_OPERATION
#define GL_INVALID_OPERATION
Definition: SDL_opengl.h:722
SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR
@ SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR
Definition: SDL_blendmode.h:80
SDL_GL_CONTEXT_DEBUG_FLAG
@ SDL_GL_CONTEXT_DEBUG_FLAG
Definition: SDL_video.h:238
SDL_BLENDMODE_NONE
@ SDL_BLENDMODE_NONE
Definition: SDL_blendmode.h:42
SDL_memcpy
#define SDL_memcpy
Definition: SDL_dynapi_overrides.h:387
GL_TEXTURE_MIN_FILTER
#define GL_TEXTURE_MIN_FILTER
Definition: SDL_opengl.h:675
event
struct _cl_event * event
Definition: SDL_opengl_glext.h:2649
SDL_Renderer
Definition: SDL_sysrender.h:122
SDL_FALSE
@ SDL_FALSE
Definition: SDL_stdinc.h:163
context
static screen_context_t context
Definition: video.c:25
SDL_Renderer::QueueSetDrawColor
int(* QueueSetDrawColor)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
Definition: SDL_sysrender.h:131
SDL_FPoint
The structure that defines a point (floating point)
Definition: SDL_rect.h:60
SDL_Renderer::driverdata
void * driverdata
Definition: SDL_sysrender.h:232
SDL_FRect::y
float y
Definition: SDL_rect.h:90
SDL_FRect::w
float w
Definition: SDL_rect.h:91
GL_COMPILE_STATUS
#define GL_COMPILE_STATUS
Definition: SDL_opengl_glext.h:631
SDL_FLIP_HORIZONTAL
@ SDL_FLIP_HORIZONTAL
Definition: SDL_render.h:114
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
color
GLuint color
Definition: SDL_opengl_glext.h:1148
window
EGLSurface EGLNativeWindowType * window
Definition: eglext.h:1025
GL_LINE_LOOP
#define GL_LINE_LOOP
Definition: SDL_opengl.h:218
SDL_RendererInfo::flags
Uint32 flags
Definition: SDL_render.h:81
SDL_GL_SetAttribute
#define SDL_GL_SetAttribute
Definition: SDL_dynapi_overrides.h:557
SDL_Rect::y
int y
Definition: SDL_rect.h:79
GL_ONE_MINUS_SRC_COLOR
#define GL_ONE_MINUS_SRC_COLOR
Definition: SDL_opengl.h:403
GL_NO_ERROR
#define GL_NO_ERROR
Definition: SDL_opengl.h:719
SDL_memcmp
#define SDL_memcmp
Definition: SDL_dynapi_overrides.h:389
SDL_Rect::h
int h
Definition: SDL_rect.h:80
SDL_free
#define SDL_free
Definition: SDL_dynapi_overrides.h:377
SDL_TEXTUREACCESS_STATIC
@ SDL_TEXTUREACCESS_STATIC
Definition: SDL_render.h:93
f
GLfloat f
Definition: SDL_opengl_glext.h:1870
height
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
SDL_cos
#define SDL_cos
Definition: SDL_dynapi_overrides.h:428
GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES
Definition: SDL_opengles2_gl2ext.h:77
SDL_Renderer::SupportsBlendMode
SDL_bool(* SupportsBlendMode)(SDL_Renderer *renderer, SDL_BlendMode blendMode)
Definition: SDL_sysrender.h:128
SDL_RENDERCMD_SETVIEWPORT
@ SDL_RENDERCMD_SETVIEWPORT
Definition: SDL_sysrender.h:75
SDL_Renderer::QueueDrawLines
int(* QueueDrawLines)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
Definition: SDL_sysrender.h:134
SDL_RENDERER_PRESENTVSYNC
@ SDL_RENDERER_PRESENTVSYNC
Definition: SDL_render.h:69
SDL_RenderCommand::color
struct SDL_RenderCommand::@30::@34 color
SDL_RENDERCMD_DRAW_POINTS
@ SDL_RENDERCMD_DRAW_POINTS
Definition: SDL_sysrender.h:79
SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA
@ SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA
Definition: SDL_blendmode.h:86
rect
SDL_Rect rect
Definition: testrelative.c:27
GL_NONE
#define GL_NONE
Definition: SDL_opengl.h:491
SDL_shaders_gles2.h
SDL_GL_CONTEXT_PROFILE_ES
@ SDL_GL_CONTEXT_PROFILE_ES
Definition: SDL_video.h:233
SDL_GL_GetSwapInterval
#define SDL_GL_GetSwapInterval
Definition: SDL_dynapi_overrides.h:565
head
SDL_EventEntry * head
Definition: SDL_events.c:80
SDL_BlendFactor
SDL_BlendFactor
The normalized factor used to multiply pixel components.
Definition: SDL_blendmode.h:75
SDL_assert.h
GL_TRUE
#define GL_TRUE
Definition: SDL_opengl.h:200
SetDrawState
static void SetDrawState(SDL_Surface *surface, SW_DrawStateCache *drawstate)
Definition: SDL_render_sw.c:584
SDL_GL_SetSwapInterval
#define SDL_GL_SetSwapInterval
Definition: SDL_dynapi_overrides.h:564
SDL_GetBlendModeDstAlphaFactor
SDL_BlendFactor SDL_GetBlendModeDstAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3370
GL_TEXTURE_MAG_FILTER
#define GL_TEXTURE_MAG_FILTER
Definition: SDL_opengl.h:674
SDL_Renderer::GL_BindTexture
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
Definition: SDL_sysrender.h:163
SDL_RenderCommand::command
SDL_RenderCommandType command
Definition: SDL_sysrender.h:88
SDL_RENDERCMD_NO_OP
@ SDL_RENDERCMD_NO_OP
Definition: SDL_sysrender.h:74
SDL_Renderer::QueueSetViewport
int(* QueueSetViewport)(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
Definition: SDL_sysrender.h:130
SDL_PIXELFORMAT_ARGB8888
@ SDL_PIXELFORMAT_ARGB8888
Definition: SDL_pixels.h:248
SDL_assert
#define SDL_assert(condition)
Definition: SDL_assert.h:169
SDL_GL_GetCurrentContext
#define SDL_GL_GetCurrentContext
Definition: SDL_dynapi_overrides.h:562
SDL_BLENDFACTOR_ZERO
@ SDL_BLENDFACTOR_ZERO
Definition: SDL_blendmode.h:77
SDL_WINDOWEVENT_MINIMIZED
@ SDL_WINDOWEVENT_MINIMIZED
Definition: SDL_video.h:159
GL_TEXTURE_WRAP_S
#define GL_TEXTURE_WRAP_S
Definition: SDL_opengl.h:672
GL_LINK_STATUS
#define GL_LINK_STATUS
Definition: SDL_opengl_glext.h:632
pixels
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: SDL_opengl.h:1572
SDL_RENDERCMD_DRAW_LINES
@ SDL_RENDERCMD_DRAW_LINES
Definition: SDL_sysrender.h:80
SDL_Renderer::GetOutputSize
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
Definition: SDL_sysrender.h:127
SDL_RenderCommand::data
union SDL_RenderCommand::@30 data
SDL_BLENDFACTOR_DST_COLOR
@ SDL_BLENDFACTOR_DST_COLOR
Definition: SDL_blendmode.h:83
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_GL_CONTEXT_MAJOR_VERSION
@ SDL_GL_CONTEXT_MAJOR_VERSION
Definition: SDL_video.h:217
SDL_GL_CONTEXT_PROFILE_MASK
@ SDL_GL_CONTEXT_PROFILE_MASK
Definition: SDL_video.h:221
SDL_Renderer::CreateTexture
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:129
size
GLsizeiptr size
Definition: SDL_opengl_glext.h:537
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_Texture::format
Uint32 format
Definition: SDL_sysrender.h:46
SDL_RENDERCMD_FILL_RECTS
@ SDL_RENDERCMD_FILL_RECTS
Definition: SDL_sysrender.h:81
id
GLuint id
Definition: SDL_opengl_glext.h:528
GL_SCISSOR_TEST
#define GL_SCISSOR_TEST
Definition: SDL_opengl.h:615
SDL_Renderer::DestroyRenderer
void(* DestroyRenderer)(SDL_Renderer *renderer)
Definition: SDL_sysrender.h:161
SDL_Renderer::LockTexture
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
Definition: SDL_sysrender.h:152
GL_COLOR_ATTACHMENT0
#define GL_COLOR_ATTACHMENT0
Definition: SDL_opengl_glext.h:1033
SDL_arraysize
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
SDL_BLENDMODE_INVALID
@ SDL_BLENDMODE_INVALID
Definition: SDL_blendmode.h:53
SDL_calloc
#define SDL_calloc
Definition: SDL_dynapi_overrides.h:375
SDL_GetRendererOutputSize
#define SDL_GetRendererOutputSize
Definition: SDL_dynapi_overrides.h:305
GL_FUNC_SUBTRACT
#define GL_FUNC_SUBTRACT
Definition: SDL_opengl.h:1653
SDL_Renderer::RenderReadPixels
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
Definition: SDL_sysrender.h:156
SDL_GetBlendModeSrcAlphaFactor
SDL_BlendFactor SDL_GetBlendModeSrcAlphaFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3363
SDL_GetBlendModeColorOperation
SDL_BlendOperation SDL_GetBlendModeColorOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3356
SDL_RENDERCMD_COPY_EX
@ SDL_RENDERCMD_COPY_EX
Definition: SDL_sysrender.h:83
GL_SRC_COLOR
#define GL_SRC_COLOR
Definition: SDL_opengl.h:402
SDL_GLContext
void * SDL_GLContext
An opaque handle to an OpenGL context.
Definition: SDL_video.h:193
src
GLenum src
Definition: SDL_opengl_glext.h:1737
SDL_RenderCommand
Definition: SDL_sysrender.h:86
renderer
static SDL_Renderer * renderer
Definition: testaudiocapture.c:21
GL_DST_ALPHA
#define GL_DST_ALPHA
Definition: SDL_opengl.h:406
SDL_TRUE
@ SDL_TRUE
Definition: SDL_stdinc.h:164
SDL_GetBlendModeDstColorFactor
SDL_BlendFactor SDL_GetBlendModeDstColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3349
SDL_Renderer::info
SDL_RendererInfo info
Definition: SDL_sysrender.h:170
value
GLsizei const GLfloat * value
Definition: SDL_opengl_glext.h:698
SDL_RENDERER_TARGETTEXTURE
@ SDL_RENDERER_TARGETTEXTURE
Definition: SDL_render.h:71
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
SDL_Renderer::RenderPresent
void(* RenderPresent)(SDL_Renderer *renderer)
Definition: SDL_sysrender.h:158
SDL_BYTESPERPIXEL
#define SDL_BYTESPERPIXEL(X)
Definition: SDL_pixels.h:128
s
GLdouble s
Definition: SDL_opengl.h:2063
SDL_Rect
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:77
j
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
SDL_RendererInfo::max_texture_width
int max_texture_width
Definition: SDL_render.h:84
SDL_RenderCommand::viewport
struct SDL_RenderCommand::@30::@31 viewport
GL_RGBA
#define GL_RGBA
Definition: SDL_opengl.h:529
SDL_BLENDFACTOR_SRC_COLOR
@ SDL_BLENDFACTOR_SRC_COLOR
Definition: SDL_blendmode.h:79
SDL_Texture
Definition: SDL_sysrender.h:43
SDL_Renderer::QueueFillRects
int(* QueueFillRects)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FRect *rects, int count)
Definition: SDL_sysrender.h:136
SDL_Renderer::UpdateTexture
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
Definition: SDL_sysrender.h:144
SDL_hints.h
GLsizei
int GLsizei
Definition: SDL_opengl.h:186
SDL_PIXELFORMAT_NV12
@ SDL_PIXELFORMAT_NV12
Definition: SDL_pixels.h:287
SDL_GL_MakeCurrent
#define SDL_GL_MakeCurrent
Definition: SDL_dynapi_overrides.h:560
SDL_TEXTUREACCESS_TARGET
@ SDL_TEXTUREACCESS_TARGET
Definition: SDL_render.h:95
GL_TEXTURE0
#define GL_TEXTURE0
Definition: SDL_opengl.h:1774
GLenum
unsigned int GLenum
Definition: SDL_opengl.h:176
GL_PACK_ALIGNMENT
#define GL_PACK_ALIGNMENT
Definition: SDL_opengl.h:652
SDL_WindowEvent
Window state change event data (event.window.*)
Definition: SDL_events.h:195
GL_LINEAR
#define GL_LINEAR
Definition: SDL_opengl.h:447
SDL_GL_GetAttribute
#define SDL_GL_GetAttribute
Definition: SDL_dynapi_overrides.h:558
SDL_FRect
A rectangle, with the origin at the upper left (floating point).
Definition: SDL_rect.h:87
SDL_RenderCommand::draw
struct SDL_RenderCommand::@30::@33 draw
SDL_RenderDriver::info
SDL_RendererInfo info
Definition: SDL_sysrender.h:241
SDL_ConvertPixels
#define SDL_ConvertPixels
Definition: SDL_dynapi_overrides.h:465
angle
GLfloat angle
Definition: SDL_opengl_glext.h:6097
SDL_BLENDFACTOR_DST_ALPHA
@ SDL_BLENDFACTOR_DST_ALPHA
Definition: SDL_blendmode.h:85
SDL_FLIP_VERTICAL
@ SDL_FLIP_VERTICAL
Definition: SDL_render.h:115
GL_INVALID_VALUE
#define GL_INVALID_VALUE
Definition: SDL_opengl.h:721
GL_TEXTURE1
#define GL_TEXTURE1
Definition: SDL_opengl.h:1775
SDL_GetYUVConversionModeForResolution
#define SDL_GetYUVConversionModeForResolution
Definition: SDL_dynapi_overrides.h:665
GL_OUT_OF_MEMORY
#define GL_OUT_OF_MEMORY
Definition: SDL_opengl.h:725
program
GLbitfield GLuint program
Definition: SDL_opengl_glext.h:1875
GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE
Definition: SDL_opengl.h:1507
size_t
unsigned int size_t
Definition: SDL_config_windows.h:68
SDL_Renderer::QueueDrawPoints
int(* QueueDrawPoints)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
Definition: SDL_sysrender.h:132
SDL_BLENDFACTOR_ONE
@ SDL_BLENDFACTOR_ONE
Definition: SDL_blendmode.h:78
GLuint
unsigned int GLuint
Definition: SDL_opengl.h:185
SDL_GL_SwapWindow
#define SDL_GL_SwapWindow
Definition: SDL_dynapi_overrides.h:566
SDL_YUV_CONVERSION_BT709
@ SDL_YUV_CONVERSION_BT709
Definition: SDL_surface.h:108
SDL_malloc
#define SDL_malloc
Definition: SDL_dynapi_overrides.h:374
SDL_RENDERER_ACCELERATED
@ SDL_RENDERER_ACCELERATED
Definition: SDL_render.h:67
SDL_RendererInfo::texture_formats
Uint32 texture_formats[16]
Definition: SDL_render.h:83
GL_ONE_MINUS_SRC_ALPHA
#define GL_ONE_MINUS_SRC_ALPHA
Definition: SDL_opengl.h:405
framebuffers
const GLuint * framebuffers
Definition: SDL_opengl_glext.h:1175
SDL_RendererInfo::max_texture_height
int max_texture_height
Definition: SDL_render.h:85
SDL_PIXELFORMAT_YV12
@ SDL_PIXELFORMAT_YV12
Definition: SDL_pixels.h:277
SDL_RENDERCMD_SETDRAWCOLOR
@ SDL_RENDERCMD_SETDRAWCOLOR
Definition: SDL_sysrender.h:77
flags
GLbitfield flags
Definition: SDL_opengl_glext.h:1480
SDL_Renderer::QueueCopy
int(* QueueCopy)(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Definition: SDL_sysrender.h:138
SDL_Renderer::window
SDL_Window * window
Definition: SDL_sysrender.h:173
GL_FRAMEBUFFER_COMPLETE
#define GL_FRAMEBUFFER_COMPLETE
Definition: SDL_opengl_glext.h:1026
SDL_TEXTUREACCESS_STREAMING
@ SDL_TEXTUREACCESS_STREAMING
Definition: SDL_render.h:94
SDL_Renderer::target
SDL_Texture * target
Definition: SDL_sysrender.h:206
texture
GLenum GLenum GLuint texture
Definition: SDL_opengl_glext.h:1178
GL_SRC_ALPHA
#define GL_SRC_ALPHA
Definition: SDL_opengl.h:404
GL_SHADER_COMPILER
#define GL_SHADER_COMPILER
Definition: SDL_opengl_glext.h:1841
GL_INVALID_ENUM
#define GL_INVALID_ENUM
Definition: SDL_opengl.h:720
GL_DST_COLOR
#define GL_DST_COLOR
Definition: SDL_opengl.h:408
GL_ONE_MINUS_DST_COLOR
#define GL_ONE_MINUS_DST_COLOR
Definition: SDL_opengl.h:409
rects
EGLSurface EGLint * rects
Definition: eglext.h:282
SDL_FORCE_INLINE
#define SDL_FORCE_INLINE
Definition: begin_code.h:147
GL_TEXTURE2
#define GL_TEXTURE2
Definition: SDL_opengl.h:1776
SDL_sin
#define SDL_sin
Definition: SDL_dynapi_overrides.h:435
SDL_PIXELFORMAT_ABGR8888
@ SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:254
SDL_GetBlendModeAlphaOperation
SDL_BlendOperation SDL_GetBlendModeAlphaOperation(SDL_BlendMode blendMode)
Definition: SDL_render.c:3377
SDL_BlendMode
SDL_BlendMode
The blend mode used in SDL_RenderCopy() and drawing operations.
Definition: SDL_blendmode.h:40
type
GLuint GLuint GLsizei GLenum type
Definition: SDL_opengl.h:1571
GL_FUNC_REVERSE_SUBTRACT
#define GL_FUNC_REVERSE_SUBTRACT
Definition: SDL_opengl.h:1654
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
GL_UNSIGNED_BYTE
#define GL_UNSIGNED_BYTE
Definition: SDL_opengl.h:204
SDL_GL_DeleteContext
#define SDL_GL_DeleteContext
Definition: SDL_dynapi_overrides.h:567
GL_LUMINANCE
#define GL_LUMINANCE
Definition: SDL_opengl.h:510
SDL_GetBlendModeSrcColorFactor
SDL_BlendFactor SDL_GetBlendModeSrcColorFactor(SDL_BlendMode blendMode)
Definition: SDL_render.c:3342
GL_TRIANGLE_STRIP
#define GL_TRIANGLE_STRIP
Definition: SDL_opengl.h:221
GLint
int GLint
Definition: SDL_opengl.h:182
GLfloat
float GLfloat
Definition: SDL_opengl.h:187
SDL_RENDERCMD_CLEAR
@ SDL_RENDERCMD_CLEAR
Definition: SDL_sysrender.h:78
SDL_YUV_CONVERSION_BT601
@ SDL_YUV_CONVERSION_BT601
Definition: SDL_surface.h:107
GL_FLOAT
#define GL_FLOAT
Definition: SDL_opengl.h:209
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:161
SDL_Renderer::UnlockTexture
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:154
SDL_RendererInfo::num_texture_formats
Uint32 num_texture_formats
Definition: SDL_render.h:82
SDL_Renderer::DestroyTexture
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
Definition: SDL_sysrender.h:159
SDL_Renderer::UpdateTextureYUV
int(* 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)
Definition: SDL_sysrender.h:147
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
GL_STREAM_DRAW
#define GL_STREAM_DRAW
Definition: SDL_opengl_glext.h:492
GL_NUM_SHADER_BINARY_FORMATS
#define GL_NUM_SHADER_BINARY_FORMATS
Definition: SDL_opengl_glext.h:1843
Uint8
uint8_t Uint8
Definition: SDL_stdinc.h:179