Atlas - SDL_render_gles.c

Home / ext / SDL2 / src / render / opengles Lines: 1 | Size: 40328 bytes [Download] [Show on GitHub] [Search similar files] [Raw] [Raw (proxy)]
[FILE BEGIN]
1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2018 Sam Lantinga <[email protected]> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20*/ 21#include "../../SDL_internal.h" 22 23#if SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED 24 25#include "SDL_hints.h" 26#include "SDL_opengles.h" 27#include "../SDL_sysrender.h" 28 29/* To prevent unnecessary window recreation, 30 * these should match the defaults selected in SDL_GL_ResetAttributes 31 */ 32 33#define RENDERER_CONTEXT_MAJOR 1 34#define RENDERER_CONTEXT_MINOR 1 35 36#if defined(SDL_VIDEO_DRIVER_PANDORA) 37 38/* Empty function stub to get OpenGL ES 1.x support without */ 39/* OpenGL ES extension GL_OES_draw_texture supported */ 40GL_API void GL_APIENTRY 41glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) 42{ 43 return; 44} 45 46#endif /* SDL_VIDEO_DRIVER_PANDORA */ 47 48/* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */ 49 50/* Used to re-create the window with OpenGL ES capability */ 51extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); 52 53static const float inv255f = 1.0f / 255.0f; 54 55static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags); 56static void GLES_WindowEvent(SDL_Renderer * renderer, 57 const SDL_WindowEvent *event); 58static int GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h); 59static SDL_bool GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode); 60static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); 61static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 62 const SDL_Rect * rect, const void *pixels, 63 int pitch); 64static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 65 const SDL_Rect * rect, void **pixels, int *pitch); 66static void GLES_UnlockTexture(SDL_Renderer * renderer, 67 SDL_Texture * texture); 68static int GLES_SetRenderTarget(SDL_Renderer * renderer, 69 SDL_Texture * texture); 70static int GLES_UpdateViewport(SDL_Renderer * renderer); 71static int GLES_UpdateClipRect(SDL_Renderer * renderer); 72static int GLES_RenderClear(SDL_Renderer * renderer); 73static int GLES_RenderDrawPoints(SDL_Renderer * renderer, 74 const SDL_FPoint * points, int count); 75static int GLES_RenderDrawLines(SDL_Renderer * renderer, 76 const SDL_FPoint * points, int count); 77static int GLES_RenderFillRects(SDL_Renderer * renderer, 78 const SDL_FRect * rects, int count); 79static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 80 const SDL_Rect * srcrect, 81 const SDL_FRect * dstrect); 82static int GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 83 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 84 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip); 85static int GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 86 Uint32 pixel_format, void * pixels, int pitch); 87static void GLES_RenderPresent(SDL_Renderer * renderer); 88static void GLES_DestroyTexture(SDL_Renderer * renderer, 89 SDL_Texture * texture); 90static void GLES_DestroyRenderer(SDL_Renderer * renderer); 91static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); 92static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture); 93 94typedef struct GLES_FBOList GLES_FBOList; 95 96struct GLES_FBOList 97{ 98 Uint32 w, h; 99 GLuint FBO; 100 GLES_FBOList *next; 101}; 102 103 104SDL_RenderDriver GLES_RenderDriver = { 105 GLES_CreateRenderer, 106 { 107 "opengles", 108 (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), 109 1, 110 {SDL_PIXELFORMAT_ABGR8888}, 111 0, 112 0} 113}; 114 115typedef struct 116{ 117 SDL_GLContext context; 118 struct { 119 Uint32 color; 120 SDL_BlendMode blendMode; 121 SDL_bool tex_coords; 122 } current; 123 124#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; 125#define SDL_PROC_OES SDL_PROC 126#include "SDL_glesfuncs.h" 127#undef SDL_PROC 128#undef SDL_PROC_OES 129 SDL_bool GL_OES_framebuffer_object_supported; 130 GLES_FBOList *framebuffers; 131 GLuint window_framebuffer; 132 133 SDL_bool GL_OES_blend_func_separate_supported; 134 SDL_bool GL_OES_blend_equation_separate_supported; 135 SDL_bool GL_OES_blend_subtract_supported; 136} GLES_RenderData; 137 138typedef struct 139{ 140 GLuint texture; 141 GLenum type; 142 GLfloat texw; 143 GLfloat texh; 144 GLenum format; 145 GLenum formattype; 146 void *pixels; 147 int pitch; 148 GLES_FBOList *fbo; 149} GLES_TextureData; 150 151static int 152GLES_SetError(const char *prefix, GLenum result) 153{ 154 const char *error; 155 156 switch (result) { 157 case GL_NO_ERROR: 158 error = "GL_NO_ERROR"; 159 break; 160 case GL_INVALID_ENUM: 161 error = "GL_INVALID_ENUM"; 162 break; 163 case GL_INVALID_VALUE: 164 error = "GL_INVALID_VALUE"; 165 break; 166 case GL_INVALID_OPERATION: 167 error = "GL_INVALID_OPERATION"; 168 break; 169 case GL_STACK_OVERFLOW: 170 error = "GL_STACK_OVERFLOW"; 171 break; 172 case GL_STACK_UNDERFLOW: 173 error = "GL_STACK_UNDERFLOW"; 174 break; 175 case GL_OUT_OF_MEMORY: 176 error = "GL_OUT_OF_MEMORY"; 177 break; 178 default: 179 error = "UNKNOWN"; 180 break; 181 } 182 return SDL_SetError("%s: %s", prefix, error); 183} 184 185static int GLES_LoadFunctions(GLES_RenderData * data) 186{ 187#if SDL_VIDEO_DRIVER_UIKIT 188#define __SDL_NOGETPROCADDR__ 189#elif SDL_VIDEO_DRIVER_ANDROID 190#define __SDL_NOGETPROCADDR__ 191#elif SDL_VIDEO_DRIVER_PANDORA 192#define __SDL_NOGETPROCADDR__ 193#endif 194 195#ifdef __SDL_NOGETPROCADDR__ 196#define SDL_PROC(ret,func,params) data->func=func; 197#define SDL_PROC_OES(ret,func,params) data->func=func; 198#else 199#define SDL_PROC(ret,func,params) \ 200 do { \ 201 data->func = SDL_GL_GetProcAddress(#func); \ 202 if ( ! data->func ) { \ 203 return SDL_SetError("Couldn't load GLES function %s: %s", #func, SDL_GetError()); \ 204 } \ 205 } while ( 0 ); 206#define SDL_PROC_OES(ret,func,params) \ 207 do { \ 208 data->func = SDL_GL_GetProcAddress(#func); \ 209 } while ( 0 ); 210#endif /* __SDL_NOGETPROCADDR__ */ 211 212#include "SDL_glesfuncs.h" 213#undef SDL_PROC 214#undef SDL_PROC_OES 215 return 0; 216} 217 218static SDL_GLContext SDL_CurrentContext = NULL; 219 220static GLES_FBOList * 221GLES_GetFBO(GLES_RenderData *data, Uint32 w, Uint32 h) 222{ 223 GLES_FBOList *result = data->framebuffers; 224 while ((result) && ((result->w != w) || (result->h != h)) ) { 225 result = result->next; 226 } 227 if (result == NULL) { 228 result = SDL_malloc(sizeof(GLES_FBOList)); 229 result->w = w; 230 result->h = h; 231 data->glGenFramebuffersOES(1, &result->FBO); 232 result->next = data->framebuffers; 233 data->framebuffers = result; 234 } 235 return result; 236} 237 238 239static int 240GLES_ActivateRenderer(SDL_Renderer * renderer) 241{ 242 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 243 244 if (SDL_CurrentContext != data->context) { 245 if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) { 246 return -1; 247 } 248 SDL_CurrentContext = data->context; 249 250 GLES_UpdateViewport(renderer); 251 } 252 return 0; 253} 254 255/* This is called if we need to invalidate all of the SDL OpenGL state */ 256static void 257GLES_ResetState(SDL_Renderer *renderer) 258{ 259 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 260 261 if (SDL_CurrentContext == data->context) { 262 GLES_UpdateViewport(renderer); 263 } else { 264 GLES_ActivateRenderer(renderer); 265 } 266 267 data->current.color = 0xffffffff; 268 data->current.blendMode = SDL_BLENDMODE_INVALID; 269 data->current.tex_coords = SDL_FALSE; 270 271 data->glDisable(GL_DEPTH_TEST); 272 data->glDisable(GL_CULL_FACE); 273 274 data->glMatrixMode(GL_MODELVIEW); 275 data->glLoadIdentity(); 276 277 data->glEnableClientState(GL_VERTEX_ARRAY); 278 data->glDisableClientState(GL_TEXTURE_COORD_ARRAY); 279} 280 281SDL_Renderer * 282GLES_CreateRenderer(SDL_Window * window, Uint32 flags) 283{ 284 285 SDL_Renderer *renderer; 286 GLES_RenderData *data; 287 GLint value; 288 Uint32 window_flags; 289 int profile_mask = 0, major = 0, minor = 0; 290 SDL_bool changed_window = SDL_FALSE; 291 292 SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); 293 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); 294 SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); 295 296 window_flags = SDL_GetWindowFlags(window); 297 if (!(window_flags & SDL_WINDOW_OPENGL) || 298 profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { 299 300 changed_window = SDL_TRUE; 301 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); 302 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); 303 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); 304 305 if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { 306 goto error; 307 } 308 } 309 310 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); 311 if (!renderer) { 312 SDL_OutOfMemory(); 313 goto error; 314 } 315 316 data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data)); 317 if (!data) { 318 GLES_DestroyRenderer(renderer); 319 SDL_OutOfMemory(); 320 goto error; 321 } 322 323 renderer->WindowEvent = GLES_WindowEvent; 324 renderer->GetOutputSize = GLES_GetOutputSize; 325 renderer->SupportsBlendMode = GLES_SupportsBlendMode; 326 renderer->CreateTexture = GLES_CreateTexture; 327 renderer->UpdateTexture = GLES_UpdateTexture; 328 renderer->LockTexture = GLES_LockTexture; 329 renderer->UnlockTexture = GLES_UnlockTexture; 330 renderer->SetRenderTarget = GLES_SetRenderTarget; 331 renderer->UpdateViewport = GLES_UpdateViewport; 332 renderer->UpdateClipRect = GLES_UpdateClipRect; 333 renderer->RenderClear = GLES_RenderClear; 334 renderer->RenderDrawPoints = GLES_RenderDrawPoints; 335 renderer->RenderDrawLines = GLES_RenderDrawLines; 336 renderer->RenderFillRects = GLES_RenderFillRects; 337 renderer->RenderCopy = GLES_RenderCopy; 338 renderer->RenderCopyEx = GLES_RenderCopyEx; 339 renderer->RenderReadPixels = GLES_RenderReadPixels; 340 renderer->RenderPresent = GLES_RenderPresent; 341 renderer->DestroyTexture = GLES_DestroyTexture; 342 renderer->DestroyRenderer = GLES_DestroyRenderer; 343 renderer->GL_BindTexture = GLES_BindTexture; 344 renderer->GL_UnbindTexture = GLES_UnbindTexture; 345 renderer->info = GLES_RenderDriver.info; 346 renderer->info.flags = SDL_RENDERER_ACCELERATED; 347 renderer->driverdata = data; 348 renderer->window = window; 349 350 data->context = SDL_GL_CreateContext(window); 351 if (!data->context) { 352 GLES_DestroyRenderer(renderer); 353 goto error; 354 } 355 if (SDL_GL_MakeCurrent(window, data->context) < 0) { 356 GLES_DestroyRenderer(renderer); 357 goto error; 358 } 359 360 if (GLES_LoadFunctions(data) < 0) { 361 GLES_DestroyRenderer(renderer); 362 goto error; 363 } 364 365 if (flags & SDL_RENDERER_PRESENTVSYNC) { 366 SDL_GL_SetSwapInterval(1); 367 } else { 368 SDL_GL_SetSwapInterval(0); 369 } 370 if (SDL_GL_GetSwapInterval() > 0) { 371 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; 372 } 373 374 value = 0; 375 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); 376 renderer->info.max_texture_width = value; 377 value = 0; 378 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); 379 renderer->info.max_texture_height = value; 380 381 /* Android does not report GL_OES_framebuffer_object but the functionality seems to be there anyway */ 382 if (SDL_GL_ExtensionSupported("GL_OES_framebuffer_object") || data->glGenFramebuffersOES) { 383 data->GL_OES_framebuffer_object_supported = SDL_TRUE; 384 renderer->info.flags |= SDL_RENDERER_TARGETTEXTURE; 385 386 value = 0; 387 data->glGetIntegerv(GL_FRAMEBUFFER_BINDING_OES, &value); 388 data->window_framebuffer = (GLuint)value; 389 } 390 data->framebuffers = NULL; 391 392 if (SDL_GL_ExtensionSupported("GL_OES_blend_func_separate")) { 393 data->GL_OES_blend_func_separate_supported = SDL_TRUE; 394 } 395 if (SDL_GL_ExtensionSupported("GL_OES_blend_equation_separate")) { 396 data->GL_OES_blend_equation_separate_supported = SDL_TRUE; 397 } 398 if (SDL_GL_ExtensionSupported("GL_OES_blend_subtract")) { 399 data->GL_OES_blend_subtract_supported = SDL_TRUE; 400 } 401 402 /* Set up parameters for rendering */ 403 GLES_ResetState(renderer); 404 405 return renderer; 406 407error: 408 if (changed_window) { 409 /* Uh oh, better try to put it back... */ 410 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); 411 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); 412 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); 413 SDL_RecreateWindow(window, window_flags); 414 } 415 return NULL; 416} 417 418static void 419GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) 420{ 421 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 422 423 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED || 424 event->event == SDL_WINDOWEVENT_SHOWN || 425 event->event == SDL_WINDOWEVENT_HIDDEN) { 426 /* Rebind the context to the window area and update matrices */ 427 SDL_CurrentContext = NULL; 428 } 429 430 if (event->event == SDL_WINDOWEVENT_MINIMIZED) { 431 /* According to Apple documentation, we need to finish drawing NOW! */ 432 data->glFinish(); 433 } 434} 435 436static int 437GLES_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) 438{ 439 SDL_GL_GetDrawableSize(renderer->window, w, h); 440 return 0; 441} 442 443static GLenum GetBlendFunc(SDL_BlendFactor factor) 444{ 445 switch (factor) { 446 case SDL_BLENDFACTOR_ZERO: 447 return GL_ZERO; 448 case SDL_BLENDFACTOR_ONE: 449 return GL_ONE; 450 case SDL_BLENDFACTOR_SRC_COLOR: 451 return GL_SRC_COLOR; 452 case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR: 453 return GL_ONE_MINUS_SRC_COLOR; 454 case SDL_BLENDFACTOR_SRC_ALPHA: 455 return GL_SRC_ALPHA; 456 case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: 457 return GL_ONE_MINUS_SRC_ALPHA; 458 case SDL_BLENDFACTOR_DST_COLOR: 459 return GL_DST_COLOR; 460 case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR: 461 return GL_ONE_MINUS_DST_COLOR; 462 case SDL_BLENDFACTOR_DST_ALPHA: 463 return GL_DST_ALPHA; 464 case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA: 465 return GL_ONE_MINUS_DST_ALPHA; 466 default: 467 return GL_INVALID_ENUM; 468 } 469} 470 471static GLenum GetBlendEquation(SDL_BlendOperation operation) 472{ 473 switch (operation) { 474 case SDL_BLENDOPERATION_ADD: 475 return GL_FUNC_ADD_OES; 476 case SDL_BLENDOPERATION_SUBTRACT: 477 return GL_FUNC_SUBTRACT_OES; 478 case SDL_BLENDOPERATION_REV_SUBTRACT: 479 return GL_FUNC_REVERSE_SUBTRACT_OES; 480 default: 481 return GL_INVALID_ENUM; 482 } 483} 484 485static SDL_bool 486GLES_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) 487{ 488 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 489 SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode); 490 SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode); 491 SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode); 492 SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode); 493 SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode); 494 SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode); 495 496 if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM || 497 GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM || 498 GetBlendEquation(colorOperation) == GL_INVALID_ENUM || 499 GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM || 500 GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM || 501 GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) { 502 return SDL_FALSE; 503 } 504 if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->GL_OES_blend_func_separate_supported) { 505 return SDL_FALSE; 506 } 507 if (colorOperation != alphaOperation && !data->GL_OES_blend_equation_separate_supported) { 508 return SDL_FALSE; 509 } 510 if (colorOperation != SDL_BLENDOPERATION_ADD && !data->GL_OES_blend_subtract_supported) { 511 return SDL_FALSE; 512 } 513 return SDL_TRUE; 514} 515 516static SDL_INLINE int 517power_of_2(int input) 518{ 519 int value = 1; 520 521 while (value < input) { 522 value <<= 1; 523 } 524 return value; 525} 526 527static int 528GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) 529{ 530 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; 531 GLES_TextureData *data; 532 GLint internalFormat; 533 GLenum format, type; 534 int texture_w, texture_h; 535 GLenum scaleMode; 536 GLenum result; 537 538 GLES_ActivateRenderer(renderer); 539 540 switch (texture->format) { 541 case SDL_PIXELFORMAT_ABGR8888: 542 internalFormat = GL_RGBA; 543 format = GL_RGBA; 544 type = GL_UNSIGNED_BYTE; 545 break; 546 default: 547 return SDL_SetError("Texture format not supported"); 548 } 549 550 data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data)); 551 if (!data) { 552 return SDL_OutOfMemory(); 553 } 554 555 if (texture->access == SDL_TEXTUREACCESS_STREAMING) { 556 data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); 557 data->pixels = SDL_calloc(1, texture->h * data->pitch); 558 if (!data->pixels) { 559 SDL_free(data); 560 return SDL_OutOfMemory(); 561 } 562 } 563 564 565 if (texture->access == SDL_TEXTUREACCESS_TARGET) { 566 if (!renderdata->GL_OES_framebuffer_object_supported) { 567 SDL_free(data); 568 return SDL_SetError("GL_OES_framebuffer_object not supported"); 569 } 570 data->fbo = GLES_GetFBO(renderer->driverdata, texture->w, texture->h); 571 } else { 572 data->fbo = NULL; 573 } 574 575 576 renderdata->glGetError(); 577 renderdata->glEnable(GL_TEXTURE_2D); 578 renderdata->glGenTextures(1, &data->texture); 579 result = renderdata->glGetError(); 580 if (result != GL_NO_ERROR) { 581 SDL_free(data); 582 return GLES_SetError("glGenTextures()", result); 583 } 584 585 data->type = GL_TEXTURE_2D; 586 /* no NPOV textures allowed in OpenGL ES (yet) */ 587 texture_w = power_of_2(texture->w); 588 texture_h = power_of_2(texture->h); 589 data->texw = (GLfloat) texture->w / texture_w; 590 data->texh = (GLfloat) texture->h / texture_h; 591 592 data->format = format; 593 data->formattype = type; 594 scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; 595 renderdata->glBindTexture(data->type, data->texture); 596 renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, scaleMode); 597 renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, scaleMode); 598 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 599 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 600 601 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, 602 texture_h, 0, format, type, NULL); 603 renderdata->glDisable(GL_TEXTURE_2D); 604 605 result = renderdata->glGetError(); 606 if (result != GL_NO_ERROR) { 607 SDL_free(data); 608 return GLES_SetError("glTexImage2D()", result); 609 } 610 611 texture->driverdata = data; 612 return 0; 613} 614 615static int 616GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, 617 const SDL_Rect * rect, const void *pixels, int pitch) 618{ 619 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; 620 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; 621 Uint8 *blob = NULL; 622 Uint8 *src; 623 int srcPitch; 624 int y; 625 626 GLES_ActivateRenderer(renderer); 627 628 /* Bail out if we're supposed to update an empty rectangle */ 629 if (rect->w <= 0 || rect->h <= 0) { 630 return 0; 631 } 632 633 /* Reformat the texture data into a tightly packed array */ 634 srcPitch = rect->w * SDL_BYTESPERPIXEL(texture->format); 635 src = (Uint8 *)pixels; 636 if (pitch != srcPitch) { 637 blob = (Uint8 *)SDL_malloc(srcPitch * rect->h); 638 if (!blob) { 639 return SDL_OutOfMemory(); 640 } 641 src = blob; 642 for (y = 0; y < rect->h; ++y) { 643 SDL_memcpy(src, pixels, srcPitch); 644 src += srcPitch; 645 pixels = (Uint8 *)pixels + pitch; 646 } 647 src = blob; 648 } 649 650 /* Create a texture subimage with the supplied data */ 651 renderdata->glGetError(); 652 renderdata->glEnable(data->type); 653 renderdata->glBindTexture(data->type, data->texture); 654 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 655 renderdata->glTexSubImage2D(data->type, 656 0, 657 rect->x, 658 rect->y, 659 rect->w, 660 rect->h, 661 data->format, 662 data->formattype, 663 src); 664 renderdata->glDisable(data->type); 665 SDL_free(blob); 666 667 if (renderdata->glGetError() != GL_NO_ERROR) { 668 return SDL_SetError("Failed to update texture"); 669 } 670 return 0; 671} 672 673static int 674GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, 675 const SDL_Rect * rect, void **pixels, int *pitch) 676{ 677 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; 678 679 *pixels = 680 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch + 681 rect->x * SDL_BYTESPERPIXEL(texture->format)); 682 *pitch = data->pitch; 683 return 0; 684} 685 686static void 687GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) 688{ 689 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; 690 SDL_Rect rect; 691 692 /* We do whole texture updates, at least for now */ 693 rect.x = 0; 694 rect.y = 0; 695 rect.w = texture->w; 696 rect.h = texture->h; 697 GLES_UpdateTexture(renderer, texture, &rect, data->pixels, data->pitch); 698} 699 700static int 701GLES_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) 702{ 703 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 704 GLES_TextureData *texturedata = NULL; 705 GLenum status; 706 707 if (!data->GL_OES_framebuffer_object_supported) { 708 return SDL_SetError("Can't enable render target support in this renderer"); 709 } 710 711 if (texture == NULL) { 712 data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, data->window_framebuffer); 713 return 0; 714 } 715 716 texturedata = (GLES_TextureData *) texture->driverdata; 717 data->glBindFramebufferOES(GL_FRAMEBUFFER_OES, texturedata->fbo->FBO); 718 /* TODO: check if texture pixel format allows this operation */ 719 data->glFramebufferTexture2DOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, texturedata->type, texturedata->texture, 0); 720 /* Check FBO status */ 721 status = data->glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES); 722 if (status != GL_FRAMEBUFFER_COMPLETE_OES) { 723 return SDL_SetError("glFramebufferTexture2DOES() failed"); 724 } 725 return 0; 726} 727 728static int 729GLES_UpdateViewport(SDL_Renderer * renderer) 730{ 731 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 732 733 if (SDL_CurrentContext != data->context) { 734 /* We'll update the viewport after we rebind the context */ 735 return 0; 736 } 737 738 if (renderer->target) { 739 data->glViewport(renderer->viewport.x, renderer->viewport.y, 740 renderer->viewport.w, renderer->viewport.h); 741 } else { 742 int w, h; 743 744 SDL_GL_GetDrawableSize(renderer->window, &w, &h); 745 data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h), 746 renderer->viewport.w, renderer->viewport.h); 747 } 748 749 data->glMatrixMode(GL_PROJECTION); 750 data->glLoadIdentity(); 751 if (renderer->viewport.w && renderer->viewport.h) { 752 if (renderer->target) { 753 data->glOrthof((GLfloat) 0, 754 (GLfloat) renderer->viewport.w, 755 (GLfloat) 0, 756 (GLfloat) renderer->viewport.h, 757 0.0, 1.0); 758 } else { 759 data->glOrthof((GLfloat) 0, 760 (GLfloat) renderer->viewport.w, 761 (GLfloat) renderer->viewport.h, 762 (GLfloat) 0, 763 0.0, 1.0); 764 } 765 } 766 data->glMatrixMode(GL_MODELVIEW); 767 768 return 0; 769} 770 771static int 772GLES_UpdateClipRect(SDL_Renderer * renderer) 773{ 774 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 775 776 if (SDL_CurrentContext != data->context) { 777 /* We'll update the clip rect after we rebind the context */ 778 return 0; 779 } 780 781 if (renderer->clipping_enabled) { 782 const SDL_Rect *rect = &renderer->clip_rect; 783 data->glEnable(GL_SCISSOR_TEST); 784 if (renderer->target) { 785 data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h); 786 } else { 787 int w, h; 788 789 SDL_GL_GetDrawableSize(renderer->window, &w, &h); 790 data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h); 791 } 792 } else { 793 data->glDisable(GL_SCISSOR_TEST); 794 } 795 return 0; 796} 797 798static void 799GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a) 800{ 801 Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b); 802 803 if (color != data->current.color) { 804 data->glColor4f((GLfloat) r * inv255f, 805 (GLfloat) g * inv255f, 806 (GLfloat) b * inv255f, 807 (GLfloat) a * inv255f); 808 data->current.color = color; 809 } 810} 811 812static void 813GLES_SetBlendMode(GLES_RenderData * data, SDL_BlendMode blendMode) 814{ 815 if (blendMode != data->current.blendMode) { 816 if (blendMode == SDL_BLENDMODE_NONE) { 817 data->glDisable(GL_BLEND); 818 } else { 819 data->glEnable(GL_BLEND); 820 if (data->GL_OES_blend_func_separate_supported) { 821 data->glBlendFuncSeparateOES(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)), 822 GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)), 823 GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)), 824 GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode))); 825 } else { 826 data->glBlendFunc(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)), 827 GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode))); 828 } 829 if (data->GL_OES_blend_equation_separate_supported) { 830 data->glBlendEquationSeparateOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)), 831 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode))); 832 } else if (data->GL_OES_blend_subtract_supported) { 833 data->glBlendEquationOES(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode))); 834 } 835 } 836 data->current.blendMode = blendMode; 837 } 838} 839 840static void 841GLES_SetTexCoords(GLES_RenderData * data, SDL_bool enabled) 842{ 843 if (enabled != data->current.tex_coords) { 844 if (enabled) { 845 data->glEnableClientState(GL_TEXTURE_COORD_ARRAY); 846 } else { 847 data->glDisableClientState(GL_TEXTURE_COORD_ARRAY); 848 } 849 data->current.tex_coords = enabled; 850 } 851} 852 853static void 854GLES_SetDrawingState(SDL_Renderer * renderer) 855{ 856 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 857 858 GLES_ActivateRenderer(renderer); 859 860 GLES_SetColor(data, (GLfloat) renderer->r, 861 (GLfloat) renderer->g, 862 (GLfloat) renderer->b, 863 (GLfloat) renderer->a); 864 865 GLES_SetBlendMode(data, renderer->blendMode); 866 867 GLES_SetTexCoords(data, SDL_FALSE); 868} 869 870static int 871GLES_RenderClear(SDL_Renderer * renderer) 872{ 873 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 874 875 GLES_ActivateRenderer(renderer); 876 877 data->glClearColor((GLfloat) renderer->r * inv255f, 878 (GLfloat) renderer->g * inv255f, 879 (GLfloat) renderer->b * inv255f, 880 (GLfloat) renderer->a * inv255f); 881 882 if (renderer->clipping_enabled) { 883 data->glDisable(GL_SCISSOR_TEST); 884 } 885 886 data->glClear(GL_COLOR_BUFFER_BIT); 887 888 if (renderer->clipping_enabled) { 889 data->glEnable(GL_SCISSOR_TEST); 890 } 891 892 return 0; 893} 894 895static int 896GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_FPoint * points, 897 int count) 898{ 899 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 900 GLfloat *vertices; 901 int idx; 902 903 GLES_SetDrawingState(renderer); 904 905 /* Emit the specified vertices as points */ 906 vertices = SDL_stack_alloc(GLfloat, count * 2); 907 for (idx = 0; idx < count; ++idx) { 908 GLfloat x = points[idx].x + 0.5f; 909 GLfloat y = points[idx].y + 0.5f; 910 911 vertices[idx * 2] = x; 912 vertices[(idx * 2) + 1] = y; 913 } 914 915 data->glVertexPointer(2, GL_FLOAT, 0, vertices); 916 data->glDrawArrays(GL_POINTS, 0, count); 917 SDL_stack_free(vertices); 918 return 0; 919} 920 921static int 922GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_FPoint * points, 923 int count) 924{ 925 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 926 GLfloat *vertices; 927 int idx; 928 929 GLES_SetDrawingState(renderer); 930 931 /* Emit a line strip including the specified vertices */ 932 vertices = SDL_stack_alloc(GLfloat, count * 2); 933 for (idx = 0; idx < count; ++idx) { 934 GLfloat x = points[idx].x + 0.5f; 935 GLfloat y = points[idx].y + 0.5f; 936 937 vertices[idx * 2] = x; 938 vertices[(idx * 2) + 1] = y; 939 } 940 941 data->glVertexPointer(2, GL_FLOAT, 0, vertices); 942 if (count > 2 && 943 points[0].x == points[count-1].x && points[0].y == points[count-1].y) { 944 /* GL_LINE_LOOP takes care of the final segment */ 945 --count; 946 data->glDrawArrays(GL_LINE_LOOP, 0, count); 947 } else { 948 data->glDrawArrays(GL_LINE_STRIP, 0, count); 949 /* We need to close the endpoint of the line */ 950 data->glDrawArrays(GL_POINTS, count-1, 1); 951 } 952 SDL_stack_free(vertices); 953 954 return 0; 955} 956 957static int 958GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_FRect * rects, 959 int count) 960{ 961 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 962 int i; 963 964 GLES_SetDrawingState(renderer); 965 966 for (i = 0; i < count; ++i) { 967 const SDL_FRect *rect = &rects[i]; 968 GLfloat minx = rect->x; 969 GLfloat maxx = rect->x + rect->w; 970 GLfloat miny = rect->y; 971 GLfloat maxy = rect->y + rect->h; 972 GLfloat vertices[8]; 973 vertices[0] = minx; 974 vertices[1] = miny; 975 vertices[2] = maxx; 976 vertices[3] = miny; 977 vertices[4] = minx; 978 vertices[5] = maxy; 979 vertices[6] = maxx; 980 vertices[7] = maxy; 981 982 data->glVertexPointer(2, GL_FLOAT, 0, vertices); 983 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 984 } 985 986 return 0; 987} 988 989static int 990GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, 991 const SDL_Rect * srcrect, const SDL_FRect * dstrect) 992{ 993 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 994 GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; 995 GLfloat minx, miny, maxx, maxy; 996 GLfloat minu, maxu, minv, maxv; 997 GLfloat vertices[8]; 998 GLfloat texCoords[8]; 999 1000 GLES_ActivateRenderer(renderer); 1001 1002 data->glEnable(GL_TEXTURE_2D); 1003 1004 data->glBindTexture(texturedata->type, texturedata->texture); 1005 1006 if (texture->modMode) { 1007 GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a); 1008 } else { 1009 GLES_SetColor(data, 255, 255, 255, 255); 1010 } 1011 1012 GLES_SetBlendMode(data, texture->blendMode); 1013 1014 GLES_SetTexCoords(data, SDL_TRUE); 1015 1016 minx = dstrect->x; 1017 miny = dstrect->y; 1018 maxx = dstrect->x + dstrect->w; 1019 maxy = dstrect->y + dstrect->h; 1020 1021 minu = (GLfloat) srcrect->x / texture->w; 1022 minu *= texturedata->texw; 1023 maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; 1024 maxu *= texturedata->texw; 1025 minv = (GLfloat) srcrect->y / texture->h; 1026 minv *= texturedata->texh; 1027 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; 1028 maxv *= texturedata->texh; 1029 1030 vertices[0] = minx; 1031 vertices[1] = miny; 1032 vertices[2] = maxx; 1033 vertices[3] = miny; 1034 vertices[4] = minx; 1035 vertices[5] = maxy; 1036 vertices[6] = maxx; 1037 vertices[7] = maxy; 1038 1039 texCoords[0] = minu; 1040 texCoords[1] = minv; 1041 texCoords[2] = maxu; 1042 texCoords[3] = minv; 1043 texCoords[4] = minu; 1044 texCoords[5] = maxv; 1045 texCoords[6] = maxu; 1046 texCoords[7] = maxv; 1047 1048 data->glVertexPointer(2, GL_FLOAT, 0, vertices); 1049 data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); 1050 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1051 1052 data->glDisable(GL_TEXTURE_2D); 1053 1054 return 0; 1055} 1056 1057static int 1058GLES_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 1059 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 1060 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) 1061{ 1062 1063 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 1064 GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; 1065 GLfloat minx, miny, maxx, maxy; 1066 GLfloat minu, maxu, minv, maxv; 1067 GLfloat centerx, centery; 1068 GLfloat vertices[8]; 1069 GLfloat texCoords[8]; 1070 1071 1072 GLES_ActivateRenderer(renderer); 1073 1074 data->glEnable(GL_TEXTURE_2D); 1075 1076 data->glBindTexture(texturedata->type, texturedata->texture); 1077 1078 if (texture->modMode) { 1079 GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a); 1080 } else { 1081 GLES_SetColor(data, 255, 255, 255, 255); 1082 } 1083 1084 GLES_SetBlendMode(data, texture->blendMode); 1085 1086 GLES_SetTexCoords(data, SDL_TRUE); 1087 1088 centerx = center->x; 1089 centery = center->y; 1090 1091 /* Rotate and translate */ 1092 data->glPushMatrix(); 1093 data->glTranslatef(dstrect->x + centerx, dstrect->y + centery, 0.0f); 1094 data->glRotatef((GLfloat)angle, 0.0f, 0.0f, 1.0f); 1095 1096 if (flip & SDL_FLIP_HORIZONTAL) { 1097 minx = dstrect->w - centerx; 1098 maxx = -centerx; 1099 } else { 1100 minx = -centerx; 1101 maxx = dstrect->w - centerx; 1102 } 1103 1104 if (flip & SDL_FLIP_VERTICAL) { 1105 miny = dstrect->h - centery; 1106 maxy = -centery; 1107 } else { 1108 miny = -centery; 1109 maxy = dstrect->h - centery; 1110 } 1111 1112 minu = (GLfloat) srcrect->x / texture->w; 1113 minu *= texturedata->texw; 1114 maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; 1115 maxu *= texturedata->texw; 1116 minv = (GLfloat) srcrect->y / texture->h; 1117 minv *= texturedata->texh; 1118 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; 1119 maxv *= texturedata->texh; 1120 1121 vertices[0] = minx; 1122 vertices[1] = miny; 1123 vertices[2] = maxx; 1124 vertices[3] = miny; 1125 vertices[4] = minx; 1126 vertices[5] = maxy; 1127 vertices[6] = maxx; 1128 vertices[7] = maxy; 1129 1130 texCoords[0] = minu; 1131 texCoords[1] = minv; 1132 texCoords[2] = maxu; 1133 texCoords[3] = minv; 1134 texCoords[4] = minu; 1135 texCoords[5] = maxv; 1136 texCoords[6] = maxu; 1137 texCoords[7] = maxv; 1138 data->glVertexPointer(2, GL_FLOAT, 0, vertices); 1139 data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); 1140 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1141 data->glPopMatrix(); 1142 data->glDisable(GL_TEXTURE_2D); 1143 1144 return 0; 1145} 1146 1147static int 1148GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 1149 Uint32 pixel_format, void * pixels, int pitch) 1150{ 1151 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 1152 Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; 1153 void *temp_pixels; 1154 int temp_pitch; 1155 Uint8 *src, *dst, *tmp; 1156 int w, h, length, rows; 1157 int status; 1158 1159 GLES_ActivateRenderer(renderer); 1160 1161 temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); 1162 temp_pixels = SDL_malloc(rect->h * temp_pitch); 1163 if (!temp_pixels) { 1164 return SDL_OutOfMemory(); 1165 } 1166 1167 SDL_GetRendererOutputSize(renderer, &w, &h); 1168 1169 data->glPixelStorei(GL_PACK_ALIGNMENT, 1); 1170 1171 data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h, 1172 rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels); 1173 1174 /* Flip the rows to be top-down if necessary */ 1175 if (!renderer->target) { 1176 length = rect->w * SDL_BYTESPERPIXEL(temp_format); 1177 src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; 1178 dst = (Uint8*)temp_pixels; 1179 tmp = SDL_stack_alloc(Uint8, length); 1180 rows = rect->h / 2; 1181 while (rows--) { 1182 SDL_memcpy(tmp, dst, length); 1183 SDL_memcpy(dst, src, length); 1184 SDL_memcpy(src, tmp, length); 1185 dst += temp_pitch; 1186 src -= temp_pitch; 1187 } 1188 SDL_stack_free(tmp); 1189 } 1190 1191 status = SDL_ConvertPixels(rect->w, rect->h, 1192 temp_format, temp_pixels, temp_pitch, 1193 pixel_format, pixels, pitch); 1194 SDL_free(temp_pixels); 1195 1196 return status; 1197} 1198 1199static void 1200GLES_RenderPresent(SDL_Renderer * renderer) 1201{ 1202 GLES_ActivateRenderer(renderer); 1203 1204 SDL_GL_SwapWindow(renderer->window); 1205} 1206 1207static void 1208GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) 1209{ 1210 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; 1211 1212 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; 1213 1214 GLES_ActivateRenderer(renderer); 1215 1216 if (!data) { 1217 return; 1218 } 1219 if (data->texture) { 1220 renderdata->glDeleteTextures(1, &data->texture); 1221 } 1222 SDL_free(data->pixels); 1223 SDL_free(data); 1224 texture->driverdata = NULL; 1225} 1226 1227static void 1228GLES_DestroyRenderer(SDL_Renderer * renderer) 1229{ 1230 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 1231 1232 if (data) { 1233 if (data->context) { 1234 while (data->framebuffers) { 1235 GLES_FBOList *nextnode = data->framebuffers->next; 1236 data->glDeleteFramebuffersOES(1, &data->framebuffers->FBO); 1237 SDL_free(data->framebuffers); 1238 data->framebuffers = nextnode; 1239 } 1240 SDL_GL_DeleteContext(data->context); 1241 } 1242 SDL_free(data); 1243 } 1244 SDL_free(renderer); 1245} 1246 1247static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) 1248{ 1249 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 1250 GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; 1251 GLES_ActivateRenderer(renderer); 1252 1253 data->glEnable(GL_TEXTURE_2D); 1254 data->glBindTexture(texturedata->type, texturedata->texture); 1255 1256 if (texw) { 1257 *texw = (float)texturedata->texw; 1258 } 1259 if (texh) { 1260 *texh = (float)texturedata->texh; 1261 } 1262 1263 return 0; 1264} 1265 1266static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) 1267{ 1268 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; 1269 GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; 1270 GLES_ActivateRenderer(renderer); 1271 data->glDisable(texturedata->type); 1272 1273 return 0; 1274} 1275 1276#endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */ 1277 1278/* vi: set ts=4 sw=4 expandtab: */ 1279
[FILE END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.