21 #include "../../SDL_internal.h" 23 #if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED 27 #include "../SDL_sysrender.h" 33 #define RENDERER_CONTEXT_MAJOR 1 34 #define RENDERER_CONTEXT_MINOR 1 36 #if defined(SDL_VIDEO_DRIVER_PANDORA) 53 static const float inv255f = 1.0f / 255.0f;
93 typedef struct GLES_FBOList GLES_FBOList;
123 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; 124 #define SDL_PROC_OES SDL_PROC 128 SDL_bool GL_OES_framebuffer_object_supported;
130 GLuint window_framebuffer;
133 SDL_bool GL_OES_draw_texture_supported;
134 SDL_bool GL_OES_blend_func_separate_supported;
157 error =
"GL_NO_ERROR";
160 error =
"GL_INVALID_ENUM";
163 error =
"GL_INVALID_VALUE";
166 error =
"GL_INVALID_OPERATION";
169 error =
"GL_STACK_OVERFLOW";
172 error =
"GL_STACK_UNDERFLOW";
175 error =
"GL_OUT_OF_MEMORY";
184 static int GLES_LoadFunctions(GLES_RenderData *
data)
186 #if SDL_VIDEO_DRIVER_UIKIT 187 #define __SDL_NOGETPROCADDR__ 188 #elif SDL_VIDEO_DRIVER_ANDROID 189 #define __SDL_NOGETPROCADDR__ 190 #elif SDL_VIDEO_DRIVER_PANDORA 191 #define __SDL_NOGETPROCADDR__ 194 #ifdef __SDL_NOGETPROCADDR__ 195 #define SDL_PROC(ret,func,params) data->func=func; 196 #define SDL_PROC_OES(ret,func,params) data->func=func; 198 #define SDL_PROC(ret,func,params) \ 200 data->func = SDL_GL_GetProcAddress(#func); \ 201 if ( ! data->func ) { \ 202 return SDL_SetError("Couldn't load GLES function %s: %s\n", #func, SDL_GetError()); \ 205 #define SDL_PROC_OES(ret,func,params) \ 207 data->func = SDL_GL_GetProcAddress(#func); \ 222 GLES_FBOList *result = data->framebuffers;
223 while ((result) && ((result->w != w) || (result->h != h)) ) {
224 result = result->next;
226 if (result ==
NULL) {
230 data->glGenFramebuffersOES(1, &result->FBO);
231 result->next = data->framebuffers;
232 data->framebuffers =
result;
241 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
243 if (SDL_CurrentContext != data->context) {
247 SDL_CurrentContext = data->context;
249 GLES_UpdateViewport(renderer);
258 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
260 if (SDL_CurrentContext == data->context) {
261 GLES_UpdateViewport(renderer);
263 GLES_ActivateRenderer(renderer);
266 data->current.color = 0;
267 data->current.blendMode = -1;
274 data->glLoadIdentity();
285 GLES_RenderData *
data;
288 int profile_mask = 0, major = 0, minor = 0;
315 data = (GLES_RenderData *)
SDL_calloc(1,
sizeof(*data));
317 GLES_DestroyRenderer(renderer);
343 renderer->
info = GLES_RenderDriver.
info;
349 if (!data->context) {
350 GLES_DestroyRenderer(renderer);
354 GLES_DestroyRenderer(renderer);
358 if (GLES_LoadFunctions(data) < 0) {
359 GLES_DestroyRenderer(renderer);
372 #if SDL_VIDEO_DRIVER_PANDORA 373 data->GL_OES_draw_texture_supported =
SDL_FALSE;
377 data->GL_OES_draw_texture_supported =
SDL_TRUE;
380 data->GL_OES_draw_texture_supported =
SDL_FALSE;
394 data->GL_OES_framebuffer_object_supported =
SDL_TRUE;
398 data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value);
399 data->window_framebuffer = (
GLuint)value;
401 data->framebuffers =
NULL;
404 data->GL_OES_blend_func_separate_supported =
SDL_TRUE;
408 GLES_ResetState(renderer);
413 if (changed_window) {
426 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
432 SDL_CurrentContext =
NULL;
442 GLES_GetOutputSize(
SDL_Renderer * renderer,
int *w,
int *h)
449 power_of_2(
int input)
453 while (value < input) {
464 if (!hint || *hint ==
'0' ||
SDL_strcasecmp(hint,
"nearest") == 0) {
474 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->
driverdata;
475 GLES_TextureData *data;
478 int texture_w, texture_h;
482 GLES_ActivateRenderer(renderer);
484 switch (texture->
format) {
494 data = (GLES_TextureData *)
SDL_calloc(1,
sizeof(*data));
501 data->pixels =
SDL_calloc(1, texture->
h * data->pitch);
510 if (!renderdata->GL_OES_framebuffer_object_supported) {
512 return SDL_SetError(
"GL_OES_framebuffer_object not supported");
514 data->fbo = GLES_GetFBO(renderer->
driverdata, texture->
w, texture->
h);
520 renderdata->glGetError();
522 renderdata->glGenTextures(1, &data->texture);
523 result = renderdata->glGetError();
526 return GLES_SetError(
"glGenTextures()", result);
531 texture_w = power_of_2(texture->
w);
532 texture_h = power_of_2(texture->
h);
533 data->texw = (
GLfloat) texture->
w / texture_w;
534 data->texh = (
GLfloat) texture->
h / texture_h;
537 data->formattype =
type;
539 renderdata->glBindTexture(data->type, data->texture);
545 renderdata->glTexImage2D(data->type, 0,
internalFormat, texture_w,
549 result = renderdata->glGetError();
552 return GLES_SetError(
"glTexImage2D()", result);
563 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->
driverdata;
564 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
570 GLES_ActivateRenderer(renderer);
573 if (rect->
w <= 0 || rect->
h <= 0) {
579 src = (
Uint8 *)pixels;
580 if (pitch != srcPitch) {
586 for (y = 0; y < rect->
h; ++
y) {
589 pixels = (
Uint8 *)pixels + pitch;
595 renderdata->glGetError();
596 renderdata->glEnable(data->type);
597 renderdata->glBindTexture(data->type, data->texture);
599 renderdata->glTexSubImage2D(data->type,
618 const SDL_Rect * rect,
void **pixels,
int *pitch)
620 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
623 (
void *) ((
Uint8 *) data->pixels + rect->
y * data->pitch +
625 *pitch = data->pitch;
632 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
640 GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch);
646 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
647 GLES_TextureData *texturedata =
NULL;
650 GLES_ActivateRenderer(renderer);
652 if (!data->GL_OES_framebuffer_object_supported) {
653 return SDL_SetError(
"Can't enable render target support in this renderer");
656 if (texture ==
NULL) {
657 data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer);
661 texturedata = (GLES_TextureData *) texture->
driverdata;
662 data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO);
664 data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0);
666 status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
667 if (status != GL_FRAMEBUFFER_COMPLETE_OES) {
668 return SDL_SetError(
"glFramebufferTexture2DOES() failed");
676 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
678 if (SDL_CurrentContext != data->context) {
696 data->glLoadIdentity();
708 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
710 if (SDL_CurrentContext != data->context) {
724 data->glScissor(renderer->
viewport.
x + rect->
x, h - renderer->
viewport.
y - rect->
y - rect->
h, rect->
w, rect->
h);
735 Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
737 if (color != data->current.color) {
738 data->glColor4f((
GLfloat) r * inv255f,
742 data->current.color =
color;
747 GLES_SetBlendMode(GLES_RenderData * data,
int blendMode)
749 if (blendMode != data->current.blendMode) {
758 if (data->GL_OES_blend_func_separate_supported) {
767 if (data->GL_OES_blend_func_separate_supported) {
776 if (data->GL_OES_blend_func_separate_supported) {
790 if (enabled != data->current.tex_coords) {
796 data->current.tex_coords =
enabled;
803 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
805 GLES_ActivateRenderer(renderer);
807 GLES_SetColor(data, (
GLfloat) renderer->
r,
812 GLES_SetBlendMode(data, renderer->
blendMode);
820 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
822 GLES_ActivateRenderer(renderer);
824 data->glClearColor((
GLfloat) renderer->
r * inv255f,
838 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
842 GLES_SetDrawingState(renderer);
846 for (idx = 0; idx <
count; ++idx) {
850 vertices[idx * 2] =
x;
851 vertices[(idx * 2) + 1] = y;
854 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
864 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
868 GLES_SetDrawingState(renderer);
872 for (idx = 0; idx <
count; ++idx) {
876 vertices[idx * 2] =
x;
877 vertices[(idx * 2) + 1] = y;
880 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
882 points[0].
x == points[count-1].
x && points[0].y == points[count-1].y) {
889 data->glDrawArrays(
GL_POINTS, count-1, 1);
900 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
903 GLES_SetDrawingState(renderer);
921 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
932 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
933 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
934 GLfloat minx, miny, maxx, maxy;
935 GLfloat minu, maxu, minv, maxv;
939 GLES_ActivateRenderer(renderer);
943 data->glBindTexture(texturedata->type, texturedata->texture);
946 GLES_SetColor(data, texture->
r, texture->
g, texture->
b, texture->
a);
948 GLES_SetColor(data, 255, 255, 255, 255);
951 GLES_SetBlendMode(data, texture->
blendMode);
955 if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
963 cropRect[0] = srcrect->
x;
964 cropRect[1] = srcrect->
y;
965 cropRect[2] = srcrect->
w;
966 cropRect[3] = srcrect->
h;
967 data->glTexParameteriv(
GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
970 dstrect->
w, dstrect->
h);
972 cropRect[0] = srcrect->
x;
973 cropRect[1] = srcrect->
y + srcrect->
h;
974 cropRect[2] = srcrect->
w;
975 cropRect[3] = -srcrect->
h;
976 data->glTexParameteriv(
GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
978 data->glDrawTexfOES(renderer->
viewport.
x + dstrect->
x,
979 h - (renderer->
viewport.
y + dstrect->
y) - dstrect->
h, 0,
980 dstrect->
w, dstrect->
h);
986 maxx = dstrect->
x + dstrect->
w;
987 maxy = dstrect->
y + dstrect->
h;
989 minu = (
GLfloat) srcrect->
x / texture->
w;
990 minu *= texturedata->texw;
991 maxu = (
GLfloat) (srcrect->
x + srcrect->
w) / texture->
w;
992 maxu *= texturedata->texw;
993 minv = (
GLfloat) srcrect->
y / texture->
h;
994 minv *= texturedata->texh;
995 maxv = (
GLfloat) (srcrect->
y + srcrect->
h) / texture->
h;
996 maxv *= texturedata->texh;
1007 texCoords[0] = minu;
1008 texCoords[1] = minv;
1009 texCoords[2] = maxu;
1010 texCoords[3] = minv;
1011 texCoords[4] = minu;
1012 texCoords[5] = maxv;
1013 texCoords[6] = maxu;
1014 texCoords[7] = maxv;
1016 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
1017 data->glTexCoordPointer(2,
GL_FLOAT, 0, texCoords);
1031 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1032 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
1033 GLfloat minx, miny, maxx, maxy;
1034 GLfloat minu, maxu, minv, maxv;
1040 GLES_ActivateRenderer(renderer);
1044 data->glBindTexture(texturedata->type, texturedata->texture);
1047 GLES_SetColor(data, texture->
r, texture->
g, texture->
b, texture->
a);
1049 GLES_SetColor(data, 255, 255, 255, 255);
1052 GLES_SetBlendMode(data, texture->
blendMode);
1056 centerx = center->
x;
1057 centery = center->
y;
1060 data->glPushMatrix();
1061 data->glTranslatef(dstrect->
x + centerx, dstrect->
y + centery, 0.0f);
1062 data->glRotatef((
GLfloat)angle, 0.0
f, 0.0
f, 1.0
f);
1065 minx = dstrect->
w - centerx;
1069 maxx = dstrect->
w - centerx;
1073 miny = dstrect->
h - centery;
1077 maxy = dstrect->
h - centery;
1080 minu = (
GLfloat) srcrect->
x / texture->
w;
1081 minu *= texturedata->texw;
1082 maxu = (
GLfloat) (srcrect->
x + srcrect->
w) / texture->
w;
1083 maxu *= texturedata->texw;
1084 minv = (
GLfloat) srcrect->
y / texture->
h;
1085 minv *= texturedata->texh;
1086 maxv = (
GLfloat) (srcrect->
y + srcrect->
h) / texture->
h;
1087 maxv *= texturedata->texh;
1098 texCoords[0] = minu;
1099 texCoords[1] = minv;
1100 texCoords[2] = maxu;
1101 texCoords[3] = minv;
1102 texCoords[4] = minu;
1103 texCoords[5] = maxv;
1104 texCoords[6] = maxu;
1105 texCoords[7] = maxv;
1106 data->glVertexPointer(2,
GL_FLOAT, 0, vertices);
1107 data->glTexCoordPointer(2,
GL_FLOAT, 0, texCoords);
1109 data->glPopMatrix();
1119 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1127 GLES_ActivateRenderer(renderer);
1139 data->glReadPixels(rect->
x, (h-rect->
y)-rect->
h, rect->
w, rect->
h,
1144 src = (
Uint8*)temp_pixels + (rect->
h-1)*temp_pitch;
1158 temp_format, temp_pixels, temp_pitch,
1159 pixel_format, pixels, pitch);
1168 GLES_ActivateRenderer(renderer);
1176 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->
driverdata;
1178 GLES_TextureData *data = (GLES_TextureData *) texture->
driverdata;
1180 GLES_ActivateRenderer(renderer);
1185 if (data->texture) {
1186 renderdata->glDeleteTextures(1, &data->texture);
1196 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1199 if (data->context) {
1200 while (data->framebuffers) {
1201 GLES_FBOList *nextnode = data->framebuffers->next;
1202 data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO);
1204 data->framebuffers = nextnode;
1215 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1216 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
1217 GLES_ActivateRenderer(renderer);
1220 data->glBindTexture(texturedata->type, texturedata->texture);
1223 *texw = (float)texturedata->texw;
1226 *texh = (float)texturedata->texh;
1234 GLES_RenderData *data = (GLES_RenderData *) renderer->
driverdata;
1235 GLES_TextureData *texturedata = (GLES_TextureData *) texture->
driverdata;
1236 GLES_ActivateRenderer(renderer);
1237 data->glDisable(texturedata->type);
int(* RenderDrawLines)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
#define GL_STACK_UNDERFLOW
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
#define SDL_GL_ExtensionSupported
int(* RenderDrawPoints)(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
int(* LockTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, void **pixels, int *pitch)
#define GL_INVALID_OPERATION
GLdouble GLdouble GLdouble r
GLint GLint GLsizei width
uint32_t Uint32
An unsigned 32-bit integer type.
#define SDL_GL_CreateContext
int(* RenderReadPixels)(SDL_Renderer *renderer, const SDL_Rect *rect, Uint32 format, void *pixels, int pitch)
const GLuint * framebuffers
GLint GLint GLint GLint GLint x
GLuint GLuint GLsizei count
#define SDL_HINT_RENDER_SCALE_QUALITY
A variable controlling the scaling quality.
GLenum GLenum GLuint texture
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
#define SDL_GetWindowFlags
#define SDL_BYTESPERPIXEL(X)
#define GL_TEXTURE_MAG_FILTER
int(* RenderFillRects)(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
#define GL_TRIANGLE_STRIP
GLint GLint GLsizei GLsizei height
#define GL_ONE_MINUS_SRC_ALPHA
int(* RenderClear)(SDL_Renderer *renderer)
void(* DestroyRenderer)(SDL_Renderer *renderer)
GLfixed GLfixed GLint GLint GLfixed points
int(* GetOutputSize)(SDL_Renderer *renderer, int *w, int *h)
#define GL_PACK_ALIGNMENT
#define GL_MAX_TEXTURE_SIZE
static SDL_BlendMode blendMode
int(* UpdateTexture)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, const void *pixels, int pitch)
#define SDL_GL_SetAttribute
#define SDL_GetWindowSize
#define SDL_GL_GetDrawableSize
GLuint GLuint GLsizei GLenum type
void * SDL_calloc(size_t nmemb, size_t size)
void * SDL_GLContext
An opaque handle to an OpenGL context.
#define SDL_GL_GetSwapInterval
GLenum GLenum GLenum input
GLint GLint GLint GLint GLint GLint y
int SDL_RecreateWindow(SDL_Window *window, Uint32 flags)
GLsizei const GLfloat * value
#define GL_STACK_OVERFLOW
static int GetScaleQuality(void)
uint8_t Uint8
An unsigned 8-bit integer type.
#define SDL_stack_alloc(type, count)
#define SDL_GL_SetSwapInterval
#define GL_TEXTURE_WRAP_T
int(* GL_BindTexture)(SDL_Renderer *renderer, SDL_Texture *texture, float *texw, float *texh)
void(* UnlockTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* SetRenderTarget)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* UpdateViewport)(SDL_Renderer *renderer)
#define GL_COLOR_BUFFER_BIT
int(* GL_UnbindTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
SDL_RendererFlip
Flip constants for SDL_RenderCopyEx.
GLenum GLenum GLsizei const GLuint GLboolean enabled
int(* RenderCopy)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, const SDL_FRect *dstrect)
Window state change event data (event.window.*)
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)
#define SDL_OutOfMemory()
int(* RenderCopyEx)(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcquad, const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
#define SDL_GL_MakeCurrent
#define SDL_GetRendererOutputSize
The type used to identify a window.
SDL_Rect rects[MAX_RECTS]
#define GL_TEXTURE_ENV_MODE
void(* WindowEvent)(SDL_Renderer *renderer, const SDL_WindowEvent *event)
#define GL_TEXTURE_COORD_ARRAY
#define SDL_GL_GetAttribute
GLubyte GLubyte GLubyte GLubyte w
#define SDL_ConvertPixels
void(* DestroyTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
int(* CreateTexture)(SDL_Renderer *renderer, SDL_Texture *texture)
void(* RenderPresent)(SDL_Renderer *renderer)
#define SDL_GL_DeleteContext
#define SDL_stack_free(data)
#define GL_TEXTURE_WRAP_S
GLuint GLsizei GLsizei * length
#define GL_TEXTURE_MIN_FILTER
GLboolean GLboolean GLboolean GLboolean a
#define GL_UNPACK_ALIGNMENT
int(* UpdateClipRect)(SDL_Renderer *renderer)
GLboolean GLboolean GLboolean b
#define SDL_GL_SwapWindow
GLfloat GLfloat GLfloat GLfloat h
SDL_bool clipping_enabled
A rectangle, with the origin at the upper left.