Atlas - SDL_render_gles2.c
Home / ext / SDL2 / src / render / opengles2 Lines: 4 | Size: 79457 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_ES2 && !SDL_RENDER_DISABLED 24 25#include "SDL_assert.h" 26#include "SDL_hints.h" 27#include "SDL_opengles2.h" 28#include "../SDL_sysrender.h" 29#include "../../video/SDL_blit.h" 30#include "SDL_shaders_gles2.h" 31 32/* !!! FIXME: Emscripten makes these into WebGL calls, and WebGL doesn't offer 33 !!! FIXME: client-side arrays (without an Emscripten compatibility hack, 34 !!! FIXME: at least), but the current VBO code here is dramatically 35 !!! FIXME: slower on actual iOS devices, even though the iOS Simulator 36 !!! FIXME: is okay. Some time after 2.0.4 ships, we should revisit this, 37 !!! FIXME: fix the performance bottleneck, and make everything use VBOs. 38*/ 39#ifdef __EMSCRIPTEN__ 40#define SDL_GLES2_USE_VBOS 1 41#else 42#define SDL_GLES2_USE_VBOS 0 43#endif 44 45/* To prevent unnecessary window recreation, 46 * these should match the defaults selected in SDL_GL_ResetAttributes 47 */ 48#define RENDERER_CONTEXT_MAJOR 2 49#define RENDERER_CONTEXT_MINOR 0 50 51/* Used to re-create the window with OpenGL ES capability */ 52extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); 53 54/************************************************************************************************* 55 * Bootstrap data * 56 *************************************************************************************************/ 57 58static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags); 59 60SDL_RenderDriver GLES2_RenderDriver = { 61 GLES2_CreateRenderer, 62 { 63 "opengles2", 64 (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), 65 4, 66 { 67 SDL_PIXELFORMAT_ARGB8888, 68 SDL_PIXELFORMAT_ABGR8888, 69 SDL_PIXELFORMAT_RGB888, 70 SDL_PIXELFORMAT_BGR888 71 }, 72 0, 73 0 74 } 75}; 76 77/************************************************************************************************* 78 * Context structures * 79 *************************************************************************************************/ 80 81typedef struct GLES2_FBOList GLES2_FBOList; 82 83struct GLES2_FBOList 84{ 85 Uint32 w, h; 86 GLuint FBO; 87 GLES2_FBOList *next; 88}; 89 90typedef struct GLES2_TextureData 91{ 92 GLenum texture; 93 GLenum texture_type; 94 GLenum pixel_format; 95 GLenum pixel_type; 96 void *pixel_data; 97 int pitch; 98 /* YUV texture support */ 99 SDL_bool yuv; 100 SDL_bool nv12; 101 GLenum texture_v; 102 GLenum texture_u; 103 GLES2_FBOList *fbo; 104} GLES2_TextureData; 105 106typedef struct GLES2_ShaderCacheEntry 107{ 108 GLuint id; 109 GLES2_ShaderType type; 110 const GLES2_ShaderInstance *instance; 111 int references; 112 Uint8 modulation_r, modulation_g, modulation_b, modulation_a; 113 struct GLES2_ShaderCacheEntry *prev; 114 struct GLES2_ShaderCacheEntry *next; 115} GLES2_ShaderCacheEntry; 116 117typedef struct GLES2_ShaderCache 118{ 119 int count; 120 GLES2_ShaderCacheEntry *head; 121} GLES2_ShaderCache; 122 123typedef struct GLES2_ProgramCacheEntry 124{ 125 GLuint id; 126 GLES2_ShaderCacheEntry *vertex_shader; 127 GLES2_ShaderCacheEntry *fragment_shader; 128 GLuint uniform_locations[16]; 129 Uint8 color_r, color_g, color_b, color_a; 130 Uint8 modulation_r, modulation_g, modulation_b, modulation_a; 131 GLfloat projection[4][4]; 132 struct GLES2_ProgramCacheEntry *prev; 133 struct GLES2_ProgramCacheEntry *next; 134} GLES2_ProgramCacheEntry; 135 136typedef struct GLES2_ProgramCache 137{ 138 int count; 139 GLES2_ProgramCacheEntry *head; 140 GLES2_ProgramCacheEntry *tail; 141} GLES2_ProgramCache; 142 143typedef enum 144{ 145 GLES2_ATTRIBUTE_POSITION = 0, 146 GLES2_ATTRIBUTE_TEXCOORD = 1, 147 GLES2_ATTRIBUTE_ANGLE = 2, 148 GLES2_ATTRIBUTE_CENTER = 3, 149} GLES2_Attribute; 150 151typedef enum 152{ 153 GLES2_UNIFORM_PROJECTION, 154 GLES2_UNIFORM_TEXTURE, 155 GLES2_UNIFORM_MODULATION, 156 GLES2_UNIFORM_COLOR, 157 GLES2_UNIFORM_TEXTURE_U, 158 GLES2_UNIFORM_TEXTURE_V 159} GLES2_Uniform; 160 161typedef enum 162{ 163 GLES2_IMAGESOURCE_SOLID, 164 GLES2_IMAGESOURCE_TEXTURE_ABGR, 165 GLES2_IMAGESOURCE_TEXTURE_ARGB, 166 GLES2_IMAGESOURCE_TEXTURE_RGB, 167 GLES2_IMAGESOURCE_TEXTURE_BGR, 168 GLES2_IMAGESOURCE_TEXTURE_YUV, 169 GLES2_IMAGESOURCE_TEXTURE_NV12, 170 GLES2_IMAGESOURCE_TEXTURE_NV21, 171 GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES 172} GLES2_ImageSource; 173 174typedef struct GLES2_DriverContext 175{ 176 SDL_GLContext *context; 177 178 SDL_bool debug_enabled; 179 180 struct { 181 SDL_BlendMode blendMode; 182 SDL_bool tex_coords; 183 } current; 184 185#define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; 186#include "SDL_gles2funcs.h" 187#undef SDL_PROC 188 GLES2_FBOList *framebuffers; 189 GLuint window_framebuffer; 190 191 int shader_format_count; 192 GLenum *shader_formats; 193 GLES2_ShaderCache shader_cache; 194 GLES2_ProgramCache program_cache; 195 GLES2_ProgramCacheEntry *current_program; 196 Uint8 clear_r, clear_g, clear_b, clear_a; 197 198#if SDL_GLES2_USE_VBOS 199 GLuint vertex_buffers[4]; 200 GLsizeiptr vertex_buffer_size[4]; 201#endif 202} GLES2_DriverContext; 203 204#define GLES2_MAX_CACHED_PROGRAMS 8 205 206 207SDL_FORCE_INLINE const char* 208GL_TranslateError (GLenum error) 209{ 210#define GL_ERROR_TRANSLATE(e) case e: return #e; 211 switch (error) { 212 GL_ERROR_TRANSLATE(GL_INVALID_ENUM) 213 GL_ERROR_TRANSLATE(GL_INVALID_VALUE) 214 GL_ERROR_TRANSLATE(GL_INVALID_OPERATION) 215 GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY) 216 GL_ERROR_TRANSLATE(GL_NO_ERROR) 217 default: 218 return "UNKNOWN"; 219} 220#undef GL_ERROR_TRANSLATE 221} 222 223SDL_FORCE_INLINE void 224GL_ClearErrors(SDL_Renderer *renderer) 225{ 226 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata; 227 228 if (!data->debug_enabled) { 229 return; 230 } 231 while (data->glGetError() != GL_NO_ERROR) { 232 continue; 233 } 234} 235 236SDL_FORCE_INLINE int 237GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function) 238{ 239 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata; 240 int ret = 0; 241 242 if (!data->debug_enabled) { 243 return 0; 244 } 245 /* check gl errors (can return multiple errors) */ 246 for (;;) { 247 GLenum error = data->glGetError(); 248 if (error != GL_NO_ERROR) { 249 if (prefix == NULL || prefix[0] == '\0') { 250 prefix = "generic"; 251 } 252 SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error); 253 ret = -1; 254 } else { 255 break; 256 } 257 } 258 return ret; 259} 260 261#if 0 262#define GL_CheckError(prefix, renderer) 263#else 264#define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION) 265#endif 266 267 268/************************************************************************************************* 269 * Renderer state APIs * 270 *************************************************************************************************/ 271 272static int GLES2_ActivateRenderer(SDL_Renderer *renderer); 273static void GLES2_WindowEvent(SDL_Renderer * renderer, 274 const SDL_WindowEvent *event); 275static int GLES2_UpdateViewport(SDL_Renderer * renderer); 276static void GLES2_DestroyRenderer(SDL_Renderer *renderer); 277static int GLES2_SetOrthographicProjection(SDL_Renderer *renderer); 278 279 280static SDL_GLContext SDL_CurrentContext = NULL; 281 282static int GLES2_LoadFunctions(GLES2_DriverContext * data) 283{ 284#if SDL_VIDEO_DRIVER_UIKIT 285#define __SDL_NOGETPROCADDR__ 286#elif SDL_VIDEO_DRIVER_ANDROID 287#define __SDL_NOGETPROCADDR__ 288#elif SDL_VIDEO_DRIVER_PANDORA 289#define __SDL_NOGETPROCADDR__ 290#endif 291 292#if defined __SDL_NOGETPROCADDR__ 293#define SDL_PROC(ret,func,params) data->func=func; 294#else 295#define SDL_PROC(ret,func,params) \ 296 do { \ 297 data->func = SDL_GL_GetProcAddress(#func); \ 298 if ( ! data->func ) { \ 299 return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \ 300 } \ 301 } while ( 0 ); 302#endif /* __SDL_NOGETPROCADDR__ */ 303 304#include "SDL_gles2funcs.h" 305#undef SDL_PROC 306 return 0; 307} 308 309static GLES2_FBOList * 310GLES2_GetFBO(GLES2_DriverContext *data, Uint32 w, Uint32 h) 311{ 312 GLES2_FBOList *result = data->framebuffers; 313 while ((result) && ((result->w != w) || (result->h != h)) ) { 314 result = result->next; 315 } 316 if (result == NULL) { 317 result = SDL_malloc(sizeof(GLES2_FBOList)); 318 result->w = w; 319 result->h = h; 320 data->glGenFramebuffers(1, &result->FBO); 321 result->next = data->framebuffers; 322 data->framebuffers = result; 323 } 324 return result; 325} 326 327static int 328GLES2_ActivateRenderer(SDL_Renderer * renderer) 329{ 330 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 331 332 if (SDL_CurrentContext != data->context) { 333 /* Null out the current program to ensure we set it again */ 334 data->current_program = NULL; 335 336 if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) { 337 return -1; 338 } 339 SDL_CurrentContext = data->context; 340 341 GLES2_UpdateViewport(renderer); 342 } 343 344 GL_ClearErrors(renderer); 345 346 return 0; 347} 348 349static void 350GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) 351{ 352 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 353 354 if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED || 355 event->event == SDL_WINDOWEVENT_SHOWN || 356 event->event == SDL_WINDOWEVENT_HIDDEN) { 357 /* Rebind the context to the window area */ 358 SDL_CurrentContext = NULL; 359 } 360 361 if (event->event == SDL_WINDOWEVENT_MINIMIZED) { 362 /* According to Apple documentation, we need to finish drawing NOW! */ 363 data->glFinish(); 364 } 365} 366 367static int 368GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) 369{ 370 SDL_GL_GetDrawableSize(renderer->window, w, h); 371 return 0; 372} 373 374static GLenum GetBlendFunc(SDL_BlendFactor factor) 375{ 376 switch (factor) { 377 case SDL_BLENDFACTOR_ZERO: 378 return GL_ZERO; 379 case SDL_BLENDFACTOR_ONE: 380 return GL_ONE; 381 case SDL_BLENDFACTOR_SRC_COLOR: 382 return GL_SRC_COLOR; 383 case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR: 384 return GL_ONE_MINUS_SRC_COLOR; 385 case SDL_BLENDFACTOR_SRC_ALPHA: 386 return GL_SRC_ALPHA; 387 case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: 388 return GL_ONE_MINUS_SRC_ALPHA; 389 case SDL_BLENDFACTOR_DST_COLOR: 390 return GL_DST_COLOR; 391 case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR: 392 return GL_ONE_MINUS_DST_COLOR; 393 case SDL_BLENDFACTOR_DST_ALPHA: 394 return GL_DST_ALPHA; 395 case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA: 396 return GL_ONE_MINUS_DST_ALPHA; 397 default: 398 return GL_INVALID_ENUM; 399 } 400} 401 402static GLenum GetBlendEquation(SDL_BlendOperation operation) 403{ 404 switch (operation) { 405 case SDL_BLENDOPERATION_ADD: 406 return GL_FUNC_ADD; 407 case SDL_BLENDOPERATION_SUBTRACT: 408 return GL_FUNC_SUBTRACT; 409 case SDL_BLENDOPERATION_REV_SUBTRACT: 410 return GL_FUNC_REVERSE_SUBTRACT; 411 default: 412 return GL_INVALID_ENUM; 413 } 414} 415 416static SDL_bool 417GLES2_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) 418{ 419 SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode); 420 SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode); 421 SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode); 422 SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode); 423 SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode); 424 SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode); 425 426 if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM || 427 GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM || 428 GetBlendEquation(colorOperation) == GL_INVALID_ENUM || 429 GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM || 430 GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM || 431 GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) { 432 return SDL_FALSE; 433 } 434 return SDL_TRUE; 435} 436 437static int 438GLES2_UpdateViewport(SDL_Renderer * renderer) 439{ 440 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 441 442 if (SDL_CurrentContext != data->context) { 443 /* We'll update the viewport after we rebind the context */ 444 return 0; 445 } 446 447 if (renderer->target) { 448 data->glViewport(renderer->viewport.x, renderer->viewport.y, 449 renderer->viewport.w, renderer->viewport.h); 450 } else { 451 int w, h; 452 453 SDL_GL_GetDrawableSize(renderer->window, &w, &h); 454 data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h), 455 renderer->viewport.w, renderer->viewport.h); 456 } 457 458 if (data->current_program) { 459 GLES2_SetOrthographicProjection(renderer); 460 } 461 return GL_CheckError("", renderer); 462} 463 464static int 465GLES2_UpdateClipRect(SDL_Renderer * renderer) 466{ 467 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 468 469 if (SDL_CurrentContext != data->context) { 470 /* We'll update the clip rect after we rebind the context */ 471 return 0; 472 } 473 474 if (renderer->clipping_enabled) { 475 const SDL_Rect *rect = &renderer->clip_rect; 476 data->glEnable(GL_SCISSOR_TEST); 477 if (renderer->target) { 478 data->glScissor(renderer->viewport.x + rect->x, renderer->viewport.y + rect->y, rect->w, rect->h); 479 } else { 480 int w, h; 481 482 SDL_GL_GetDrawableSize(renderer->window, &w, &h); 483 data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h); 484 } 485 } else { 486 data->glDisable(GL_SCISSOR_TEST); 487 } 488 return 0; 489} 490 491static void 492GLES2_DestroyRenderer(SDL_Renderer *renderer) 493{ 494 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 495 496 /* Deallocate everything */ 497 if (data) { 498 GLES2_ActivateRenderer(renderer); 499 500 { 501 GLES2_ShaderCacheEntry *entry; 502 GLES2_ShaderCacheEntry *next; 503 entry = data->shader_cache.head; 504 while (entry) { 505 data->glDeleteShader(entry->id); 506 next = entry->next; 507 SDL_free(entry); 508 entry = next; 509 } 510 } 511 { 512 GLES2_ProgramCacheEntry *entry; 513 GLES2_ProgramCacheEntry *next; 514 entry = data->program_cache.head; 515 while (entry) { 516 data->glDeleteProgram(entry->id); 517 next = entry->next; 518 SDL_free(entry); 519 entry = next; 520 } 521 } 522 if (data->context) { 523 while (data->framebuffers) { 524 GLES2_FBOList *nextnode = data->framebuffers->next; 525 data->glDeleteFramebuffers(1, &data->framebuffers->FBO); 526 GL_CheckError("", renderer); 527 SDL_free(data->framebuffers); 528 data->framebuffers = nextnode; 529 } 530 SDL_GL_DeleteContext(data->context); 531 } 532 SDL_free(data->shader_formats); 533 SDL_free(data); 534 } 535 SDL_free(renderer); 536} 537 538/************************************************************************************************* 539 * Texture APIs * 540 *************************************************************************************************/ 541 542static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture); 543static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, 544 const void *pixels, int pitch); 545static int GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, 546 const SDL_Rect * rect, 547 const Uint8 *Yplane, int Ypitch, 548 const Uint8 *Uplane, int Upitch, 549 const Uint8 *Vplane, int Vpitch); 550static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, 551 void **pixels, int *pitch); 552static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture); 553static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); 554static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture); 555 556static int 557GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) 558{ 559 GLES2_DriverContext *renderdata = (GLES2_DriverContext *)renderer->driverdata; 560 GLES2_TextureData *data; 561 GLenum format; 562 GLenum type; 563 GLenum scaleMode; 564 565 GLES2_ActivateRenderer(renderer); 566 567 /* Determine the corresponding GLES texture format params */ 568 switch (texture->format) 569 { 570 case SDL_PIXELFORMAT_ARGB8888: 571 case SDL_PIXELFORMAT_ABGR8888: 572 case SDL_PIXELFORMAT_RGB888: 573 case SDL_PIXELFORMAT_BGR888: 574 format = GL_RGBA; 575 type = GL_UNSIGNED_BYTE; 576 break; 577 case SDL_PIXELFORMAT_IYUV: 578 case SDL_PIXELFORMAT_YV12: 579 case SDL_PIXELFORMAT_NV12: 580 case SDL_PIXELFORMAT_NV21: 581 format = GL_LUMINANCE; 582 type = GL_UNSIGNED_BYTE; 583 break; 584#ifdef GL_TEXTURE_EXTERNAL_OES 585 case SDL_PIXELFORMAT_EXTERNAL_OES: 586 format = GL_NONE; 587 type = GL_NONE; 588 break; 589#endif 590 default: 591 return SDL_SetError("Texture format not supported"); 592 } 593 594 if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES && 595 texture->access != SDL_TEXTUREACCESS_STATIC) { 596 return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES"); 597 } 598 599 /* Allocate a texture struct */ 600 data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData)); 601 if (!data) { 602 return SDL_OutOfMemory(); 603 } 604 data->texture = 0; 605#ifdef GL_TEXTURE_EXTERNAL_OES 606 data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D; 607#else 608 data->texture_type = GL_TEXTURE_2D; 609#endif 610 data->pixel_format = format; 611 data->pixel_type = type; 612 data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12)); 613 data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21)); 614 data->texture_u = 0; 615 data->texture_v = 0; 616 scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; 617 618 /* Allocate a blob for image renderdata */ 619 if (texture->access == SDL_TEXTUREACCESS_STREAMING) { 620 size_t size; 621 data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); 622 size = texture->h * data->pitch; 623 if (data->yuv) { 624 /* Need to add size for the U and V planes */ 625 size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2); 626 } 627 if (data->nv12) { 628 /* Need to add size for the U/V plane */ 629 size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2); 630 } 631 data->pixel_data = SDL_calloc(1, size); 632 if (!data->pixel_data) { 633 SDL_free(data); 634 return SDL_OutOfMemory(); 635 } 636 } 637 638 /* Allocate the texture */ 639 GL_CheckError("", renderer); 640 641 if (data->yuv) { 642 renderdata->glGenTextures(1, &data->texture_v); 643 if (GL_CheckError("glGenTexures()", renderer) < 0) { 644 return -1; 645 } 646 renderdata->glActiveTexture(GL_TEXTURE2); 647 renderdata->glBindTexture(data->texture_type, data->texture_v); 648 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); 649 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); 650 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 651 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 652 renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); 653 654 renderdata->glGenTextures(1, &data->texture_u); 655 if (GL_CheckError("glGenTexures()", renderer) < 0) { 656 return -1; 657 } 658 renderdata->glActiveTexture(GL_TEXTURE1); 659 renderdata->glBindTexture(data->texture_type, data->texture_u); 660 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); 661 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); 662 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 663 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 664 renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); 665 if (GL_CheckError("glTexImage2D()", renderer) < 0) { 666 return -1; 667 } 668 } 669 670 if (data->nv12) { 671 renderdata->glGenTextures(1, &data->texture_u); 672 if (GL_CheckError("glGenTexures()", renderer) < 0) { 673 return -1; 674 } 675 renderdata->glActiveTexture(GL_TEXTURE1); 676 renderdata->glBindTexture(data->texture_type, data->texture_u); 677 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); 678 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); 679 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 680 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 681 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); 682 if (GL_CheckError("glTexImage2D()", renderer) < 0) { 683 return -1; 684 } 685 } 686 687 renderdata->glGenTextures(1, &data->texture); 688 if (GL_CheckError("glGenTexures()", renderer) < 0) { 689 return -1; 690 } 691 texture->driverdata = data; 692 renderdata->glActiveTexture(GL_TEXTURE0); 693 renderdata->glBindTexture(data->texture_type, data->texture); 694 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); 695 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); 696 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 697 renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 698 if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { 699 renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); 700 if (GL_CheckError("glTexImage2D()", renderer) < 0) { 701 return -1; 702 } 703 } 704 705 if (texture->access == SDL_TEXTUREACCESS_TARGET) { 706 data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h); 707 } else { 708 data->fbo = NULL; 709 } 710 711 return GL_CheckError("", renderer); 712} 713 714static int 715GLES2_TexSubImage2D(GLES2_DriverContext *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp) 716{ 717 Uint8 *blob = NULL; 718 Uint8 *src; 719 int src_pitch; 720 int y; 721 722 if ((width == 0) || (height == 0) || (bpp == 0)) { 723 return 0; /* nothing to do */ 724 } 725 726 /* Reformat the texture data into a tightly packed array */ 727 src_pitch = width * bpp; 728 src = (Uint8 *)pixels; 729 if (pitch != src_pitch) { 730 blob = (Uint8 *)SDL_malloc(src_pitch * height); 731 if (!blob) { 732 return SDL_OutOfMemory(); 733 } 734 src = blob; 735 for (y = 0; y < height; ++y) 736 { 737 SDL_memcpy(src, pixels, src_pitch); 738 src += src_pitch; 739 pixels = (Uint8 *)pixels + pitch; 740 } 741 src = blob; 742 } 743 744 data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src); 745 if (blob) { 746 SDL_free(blob); 747 } 748 return 0; 749} 750 751static int 752GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, 753 const void *pixels, int pitch) 754{ 755 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 756 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; 757 758 GLES2_ActivateRenderer(renderer); 759 760 /* Bail out if we're supposed to update an empty rectangle */ 761 if (rect->w <= 0 || rect->h <= 0) { 762 return 0; 763 } 764 765 /* Create a texture subimage with the supplied data */ 766 data->glBindTexture(tdata->texture_type, tdata->texture); 767 GLES2_TexSubImage2D(data, tdata->texture_type, 768 rect->x, 769 rect->y, 770 rect->w, 771 rect->h, 772 tdata->pixel_format, 773 tdata->pixel_type, 774 pixels, pitch, SDL_BYTESPERPIXEL(texture->format)); 775 776 if (tdata->yuv) { 777 /* Skip to the correct offset into the next texture */ 778 pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); 779 if (texture->format == SDL_PIXELFORMAT_YV12) { 780 data->glBindTexture(tdata->texture_type, tdata->texture_v); 781 } else { 782 data->glBindTexture(tdata->texture_type, tdata->texture_u); 783 } 784 GLES2_TexSubImage2D(data, tdata->texture_type, 785 rect->x / 2, 786 rect->y / 2, 787 (rect->w + 1) / 2, 788 (rect->h + 1) / 2, 789 tdata->pixel_format, 790 tdata->pixel_type, 791 pixels, (pitch + 1) / 2, 1); 792 793 794 /* Skip to the correct offset into the next texture */ 795 pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2)); 796 if (texture->format == SDL_PIXELFORMAT_YV12) { 797 data->glBindTexture(tdata->texture_type, tdata->texture_u); 798 } else { 799 data->glBindTexture(tdata->texture_type, tdata->texture_v); 800 } 801 GLES2_TexSubImage2D(data, tdata->texture_type, 802 rect->x / 2, 803 rect->y / 2, 804 (rect->w + 1) / 2, 805 (rect->h + 1) / 2, 806 tdata->pixel_format, 807 tdata->pixel_type, 808 pixels, (pitch + 1) / 2, 1); 809 } 810 811 if (tdata->nv12) { 812 /* Skip to the correct offset into the next texture */ 813 pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); 814 data->glBindTexture(tdata->texture_type, tdata->texture_u); 815 GLES2_TexSubImage2D(data, tdata->texture_type, 816 rect->x / 2, 817 rect->y / 2, 818 (rect->w + 1) / 2, 819 (rect->h + 1) / 2, 820 GL_LUMINANCE_ALPHA, 821 GL_UNSIGNED_BYTE, 822 pixels, 2 * ((pitch + 1) / 2), 2); 823 } 824 825 return GL_CheckError("glTexSubImage2D()", renderer); 826} 827 828static int 829GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, 830 const SDL_Rect * rect, 831 const Uint8 *Yplane, int Ypitch, 832 const Uint8 *Uplane, int Upitch, 833 const Uint8 *Vplane, int Vpitch) 834{ 835 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 836 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; 837 838 GLES2_ActivateRenderer(renderer); 839 840 /* Bail out if we're supposed to update an empty rectangle */ 841 if (rect->w <= 0 || rect->h <= 0) { 842 return 0; 843 } 844 845 data->glBindTexture(tdata->texture_type, tdata->texture_v); 846 GLES2_TexSubImage2D(data, tdata->texture_type, 847 rect->x / 2, 848 rect->y / 2, 849 (rect->w + 1) / 2, 850 (rect->h + 1) / 2, 851 tdata->pixel_format, 852 tdata->pixel_type, 853 Vplane, Vpitch, 1); 854 855 data->glBindTexture(tdata->texture_type, tdata->texture_u); 856 GLES2_TexSubImage2D(data, tdata->texture_type, 857 rect->x / 2, 858 rect->y / 2, 859 (rect->w + 1) / 2, 860 (rect->h + 1) / 2, 861 tdata->pixel_format, 862 tdata->pixel_type, 863 Uplane, Upitch, 1); 864 865 data->glBindTexture(tdata->texture_type, tdata->texture); 866 GLES2_TexSubImage2D(data, tdata->texture_type, 867 rect->x, 868 rect->y, 869 rect->w, 870 rect->h, 871 tdata->pixel_format, 872 tdata->pixel_type, 873 Yplane, Ypitch, 1); 874 875 return GL_CheckError("glTexSubImage2D()", renderer); 876} 877 878static int 879GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, 880 void **pixels, int *pitch) 881{ 882 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; 883 884 /* Retrieve the buffer/pitch for the specified region */ 885 *pixels = (Uint8 *)tdata->pixel_data + 886 (tdata->pitch * rect->y) + 887 (rect->x * SDL_BYTESPERPIXEL(texture->format)); 888 *pitch = tdata->pitch; 889 890 return 0; 891} 892 893static void 894GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) 895{ 896 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; 897 SDL_Rect rect; 898 899 /* We do whole texture updates, at least for now */ 900 rect.x = 0; 901 rect.y = 0; 902 rect.w = texture->w; 903 rect.h = texture->h; 904 GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch); 905} 906 907static int 908GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) 909{ 910 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata; 911 GLES2_TextureData *texturedata = NULL; 912 GLenum status; 913 914 if (texture == NULL) { 915 data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer); 916 } else { 917 texturedata = (GLES2_TextureData *) texture->driverdata; 918 data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO); 919 /* TODO: check if texture pixel format allows this operation */ 920 data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0); 921 /* Check FBO status */ 922 status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER); 923 if (status != GL_FRAMEBUFFER_COMPLETE) { 924 return SDL_SetError("glFramebufferTexture2D() failed"); 925 } 926 } 927 return 0; 928} 929 930static void 931GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) 932{ 933 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 934 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; 935 936 GLES2_ActivateRenderer(renderer); 937 938 /* Destroy the texture */ 939 if (tdata) { 940 data->glDeleteTextures(1, &tdata->texture); 941 if (tdata->texture_v) { 942 data->glDeleteTextures(1, &tdata->texture_v); 943 } 944 if (tdata->texture_u) { 945 data->glDeleteTextures(1, &tdata->texture_u); 946 } 947 SDL_free(tdata->pixel_data); 948 SDL_free(tdata); 949 texture->driverdata = NULL; 950 } 951} 952 953/************************************************************************************************* 954 * Shader management functions * 955 *************************************************************************************************/ 956 957static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type); 958static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry); 959static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer, 960 GLES2_ShaderCacheEntry *vertex, 961 GLES2_ShaderCacheEntry *fragment); 962static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int h); 963 964static GLES2_ProgramCacheEntry * 965GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex, 966 GLES2_ShaderCacheEntry *fragment) 967{ 968 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 969 GLES2_ProgramCacheEntry *entry; 970 GLES2_ShaderCacheEntry *shaderEntry; 971 GLint linkSuccessful; 972 973 /* Check if we've already cached this program */ 974 entry = data->program_cache.head; 975 while (entry) { 976 if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) { 977 break; 978 } 979 entry = entry->next; 980 } 981 if (entry) { 982 if (data->program_cache.head != entry) { 983 if (entry->next) { 984 entry->next->prev = entry->prev; 985 } 986 if (entry->prev) { 987 entry->prev->next = entry->next; 988 } 989 entry->prev = NULL; 990 entry->next = data->program_cache.head; 991 data->program_cache.head->prev = entry; 992 data->program_cache.head = entry; 993 } 994 return entry; 995 } 996 997 /* Create a program cache entry */ 998 entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry)); 999 if (!entry) { 1000 SDL_OutOfMemory(); 1001 return NULL; 1002 } 1003 entry->vertex_shader = vertex; 1004 entry->fragment_shader = fragment; 1005 1006 /* Create the program and link it */ 1007 entry->id = data->glCreateProgram(); 1008 data->glAttachShader(entry->id, vertex->id); 1009 data->glAttachShader(entry->id, fragment->id); 1010 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position"); 1011 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord"); 1012 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle"); 1013 data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center"); 1014 data->glLinkProgram(entry->id); 1015 data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful); 1016 if (!linkSuccessful) { 1017 data->glDeleteProgram(entry->id); 1018 SDL_free(entry); 1019 SDL_SetError("Failed to link shader program"); 1020 return NULL; 1021 } 1022 1023 /* Predetermine locations of uniform variables */ 1024 entry->uniform_locations[GLES2_UNIFORM_PROJECTION] = 1025 data->glGetUniformLocation(entry->id, "u_projection"); 1026 entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] = 1027 data->glGetUniformLocation(entry->id, "u_texture_v"); 1028 entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] = 1029 data->glGetUniformLocation(entry->id, "u_texture_u"); 1030 entry->uniform_locations[GLES2_UNIFORM_TEXTURE] = 1031 data->glGetUniformLocation(entry->id, "u_texture"); 1032 entry->uniform_locations[GLES2_UNIFORM_MODULATION] = 1033 data->glGetUniformLocation(entry->id, "u_modulation"); 1034 entry->uniform_locations[GLES2_UNIFORM_COLOR] = 1035 data->glGetUniformLocation(entry->id, "u_color"); 1036 1037 entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 255; 1038 entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255; 1039 1040 data->glUseProgram(entry->id); 1041 data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */ 1042 data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */ 1043 data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */ 1044 data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection); 1045 data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f); 1046 data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f); 1047 1048 /* Cache the linked program */ 1049 if (data->program_cache.head) { 1050 entry->next = data->program_cache.head; 1051 data->program_cache.head->prev = entry; 1052 } else { 1053 data->program_cache.tail = entry; 1054 } 1055 data->program_cache.head = entry; 1056 ++data->program_cache.count; 1057 1058 /* Increment the refcount of the shaders we're using */ 1059 ++vertex->references; 1060 ++fragment->references; 1061 1062 /* Evict the last entry from the cache if we exceed the limit */ 1063 if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) { 1064 shaderEntry = data->program_cache.tail->vertex_shader; 1065 if (--shaderEntry->references <= 0) { 1066 GLES2_EvictShader(renderer, shaderEntry); 1067 } 1068 shaderEntry = data->program_cache.tail->fragment_shader; 1069 if (--shaderEntry->references <= 0) { 1070 GLES2_EvictShader(renderer, shaderEntry); 1071 } 1072 data->glDeleteProgram(data->program_cache.tail->id); 1073 data->program_cache.tail = data->program_cache.tail->prev; 1074 SDL_free(data->program_cache.tail->next); 1075 data->program_cache.tail->next = NULL; 1076 --data->program_cache.count; 1077 } 1078 return entry; 1079} 1080 1081static GLES2_ShaderCacheEntry * 1082GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type) 1083{ 1084 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1085 const GLES2_Shader *shader; 1086 const GLES2_ShaderInstance *instance = NULL; 1087 GLES2_ShaderCacheEntry *entry = NULL; 1088 GLint compileSuccessful = GL_FALSE; 1089 int i, j; 1090 1091 /* Find the corresponding shader */ 1092 shader = GLES2_GetShader(type); 1093 if (!shader) { 1094 SDL_SetError("No shader matching the requested characteristics was found"); 1095 return NULL; 1096 } 1097 1098 /* Find a matching shader instance that's supported on this hardware */ 1099 for (i = 0; i < shader->instance_count && !instance; ++i) { 1100 for (j = 0; j < data->shader_format_count && !instance; ++j) { 1101 if (!shader->instances[i]) { 1102 continue; 1103 } 1104 if (shader->instances[i]->format != data->shader_formats[j]) { 1105 continue; 1106 } 1107 instance = shader->instances[i]; 1108 } 1109 } 1110 if (!instance) { 1111 SDL_SetError("The specified shader cannot be loaded on the current platform"); 1112 return NULL; 1113 } 1114 1115 /* Check if we've already cached this shader */ 1116 entry = data->shader_cache.head; 1117 while (entry) { 1118 if (entry->instance == instance) { 1119 break; 1120 } 1121 entry = entry->next; 1122 } 1123 if (entry) { 1124 return entry; 1125 } 1126 1127 /* Create a shader cache entry */ 1128 entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry)); 1129 if (!entry) { 1130 SDL_OutOfMemory(); 1131 return NULL; 1132 } 1133 entry->type = type; 1134 entry->instance = instance; 1135 1136 /* Compile or load the selected shader instance */ 1137 entry->id = data->glCreateShader(instance->type); 1138 if (instance->format == (GLenum)-1) { 1139 data->glShaderSource(entry->id, 1, (const char **)(char *)&instance->data, NULL); 1140 data->glCompileShader(entry->id); 1141 data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful); 1142 } else { 1143 data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length); 1144 compileSuccessful = GL_TRUE; 1145 } 1146 if (!compileSuccessful) { 1147 char *info = NULL; 1148 int length = 0; 1149 1150 data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length); 1151 if (length > 0) { 1152 info = SDL_stack_alloc(char, length); 1153 if (info) { 1154 data->glGetShaderInfoLog(entry->id, length, &length, info); 1155 } 1156 } 1157 if (info) { 1158 SDL_SetError("Failed to load the shader: %s", info); 1159 SDL_stack_free(info); 1160 } else { 1161 SDL_SetError("Failed to load the shader"); 1162 } 1163 data->glDeleteShader(entry->id); 1164 SDL_free(entry); 1165 return NULL; 1166 } 1167 1168 /* Link the shader entry in at the front of the cache */ 1169 if (data->shader_cache.head) { 1170 entry->next = data->shader_cache.head; 1171 data->shader_cache.head->prev = entry; 1172 } 1173 data->shader_cache.head = entry; 1174 ++data->shader_cache.count; 1175 return entry; 1176} 1177 1178static void 1179GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry) 1180{ 1181 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1182 1183 /* Unlink the shader from the cache */ 1184 if (entry->next) { 1185 entry->next->prev = entry->prev; 1186 } 1187 if (entry->prev) { 1188 entry->prev->next = entry->next; 1189 } 1190 if (data->shader_cache.head == entry) { 1191 data->shader_cache.head = entry->next; 1192 } 1193 --data->shader_cache.count; 1194 1195 /* Deallocate the shader */ 1196 data->glDeleteShader(entry->id); 1197 SDL_free(entry); 1198} 1199 1200static int 1201GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, int w, int h) 1202{ 1203 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1204 GLES2_ShaderCacheEntry *vertex = NULL; 1205 GLES2_ShaderCacheEntry *fragment = NULL; 1206 GLES2_ShaderType vtype, ftype; 1207 GLES2_ProgramCacheEntry *program; 1208 1209 /* Select an appropriate shader pair for the specified modes */ 1210 vtype = GLES2_SHADER_VERTEX_DEFAULT; 1211 switch (source) { 1212 case GLES2_IMAGESOURCE_SOLID: 1213 ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC; 1214 break; 1215 case GLES2_IMAGESOURCE_TEXTURE_ABGR: 1216 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC; 1217 break; 1218 case GLES2_IMAGESOURCE_TEXTURE_ARGB: 1219 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC; 1220 break; 1221 case GLES2_IMAGESOURCE_TEXTURE_RGB: 1222 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC; 1223 break; 1224 case GLES2_IMAGESOURCE_TEXTURE_BGR: 1225 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC; 1226 break; 1227 case GLES2_IMAGESOURCE_TEXTURE_YUV: 1228 switch (SDL_GetYUVConversionModeForResolution(w, h)) { 1229 case SDL_YUV_CONVERSION_JPEG: 1230 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG_SRC; 1231 break; 1232 case SDL_YUV_CONVERSION_BT601: 1233 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601_SRC; 1234 break; 1235 case SDL_YUV_CONVERSION_BT709: 1236 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709_SRC; 1237 break; 1238 default: 1239 SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h)); 1240 goto fault; 1241 } 1242 break; 1243 case GLES2_IMAGESOURCE_TEXTURE_NV12: 1244 switch (SDL_GetYUVConversionModeForResolution(w, h)) { 1245 case SDL_YUV_CONVERSION_JPEG: 1246 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG_SRC; 1247 break; 1248 case SDL_YUV_CONVERSION_BT601: 1249 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601_SRC; 1250 break; 1251 case SDL_YUV_CONVERSION_BT709: 1252 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709_SRC; 1253 break; 1254 default: 1255 SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h)); 1256 goto fault; 1257 } 1258 break; 1259 case GLES2_IMAGESOURCE_TEXTURE_NV21: 1260 switch (SDL_GetYUVConversionModeForResolution(w, h)) { 1261 case SDL_YUV_CONVERSION_JPEG: 1262 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC; 1263 break; 1264 case SDL_YUV_CONVERSION_BT601: 1265 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC; 1266 break; 1267 case SDL_YUV_CONVERSION_BT709: 1268 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC; 1269 break; 1270 default: 1271 SDL_SetError("Unsupported YUV conversion mode: %d\n", SDL_GetYUVConversionModeForResolution(w, h)); 1272 goto fault; 1273 } 1274 break; 1275 case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES: 1276 ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC; 1277 break; 1278 default: 1279 goto fault; 1280 } 1281 1282 /* Load the requested shaders */ 1283 vertex = GLES2_CacheShader(renderer, vtype); 1284 if (!vertex) { 1285 goto fault; 1286 } 1287 fragment = GLES2_CacheShader(renderer, ftype); 1288 if (!fragment) { 1289 goto fault; 1290 } 1291 1292 /* Check if we need to change programs at all */ 1293 if (data->current_program && 1294 data->current_program->vertex_shader == vertex && 1295 data->current_program->fragment_shader == fragment) { 1296 return 0; 1297 } 1298 1299 /* Generate a matching program */ 1300 program = GLES2_CacheProgram(renderer, vertex, fragment); 1301 if (!program) { 1302 goto fault; 1303 } 1304 1305 /* Select that program in OpenGL */ 1306 data->glUseProgram(program->id); 1307 1308 /* Set the current program */ 1309 data->current_program = program; 1310 1311 /* Activate an orthographic projection */ 1312 if (GLES2_SetOrthographicProjection(renderer) < 0) { 1313 goto fault; 1314 } 1315 1316 /* Clean up and return */ 1317 return 0; 1318fault: 1319 if (vertex && vertex->references <= 0) { 1320 GLES2_EvictShader(renderer, vertex); 1321 } 1322 if (fragment && fragment->references <= 0) { 1323 GLES2_EvictShader(renderer, fragment); 1324 } 1325 data->current_program = NULL; 1326 return -1; 1327} 1328 1329static int 1330GLES2_SetOrthographicProjection(SDL_Renderer *renderer) 1331{ 1332 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1333 GLfloat projection[4][4]; 1334 1335 if (!renderer->viewport.w || !renderer->viewport.h) { 1336 return 0; 1337 } 1338 1339 /* Prepare an orthographic projection */ 1340 projection[0][0] = 2.0f / renderer->viewport.w; 1341 projection[0][1] = 0.0f; 1342 projection[0][2] = 0.0f; 1343 projection[0][3] = 0.0f; 1344 projection[1][0] = 0.0f; 1345 if (renderer->target) { 1346 projection[1][1] = 2.0f / renderer->viewport.h; 1347 } else { 1348 projection[1][1] = -2.0f / renderer->viewport.h; 1349 } 1350 projection[1][2] = 0.0f; 1351 projection[1][3] = 0.0f; 1352 projection[2][0] = 0.0f; 1353 projection[2][1] = 0.0f; 1354 projection[2][2] = 0.0f; 1355 projection[2][3] = 0.0f; 1356 projection[3][0] = -1.0f; 1357 if (renderer->target) { 1358 projection[3][1] = -1.0f; 1359 } else { 1360 projection[3][1] = 1.0f; 1361 } 1362 projection[3][2] = 0.0f; 1363 projection[3][3] = 1.0f; 1364 1365 /* Set the projection matrix */ 1366 if (SDL_memcmp(data->current_program->projection, projection, sizeof (projection)) != 0) { 1367 const GLuint locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION]; 1368 data->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection); 1369 SDL_memcpy(data->current_program->projection, projection, sizeof (projection)); 1370 } 1371 1372 return 0; 1373} 1374 1375/************************************************************************************************* 1376 * Rendering functions * 1377 *************************************************************************************************/ 1378 1379static const float inv255f = 1.0f / 255.0f; 1380 1381static int GLES2_RenderClear(SDL_Renderer *renderer); 1382static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count); 1383static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count); 1384static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count); 1385static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, 1386 const SDL_FRect *dstrect); 1387static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, 1388 const SDL_Rect * srcrect, const SDL_FRect * dstrect, 1389 const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip); 1390static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 1391 Uint32 pixel_format, void * pixels, int pitch); 1392static void GLES2_RenderPresent(SDL_Renderer *renderer); 1393 1394static SDL_bool 1395CompareColors(Uint8 r1, Uint8 g1, Uint8 b1, Uint8 a1, 1396 Uint8 r2, Uint8 g2, Uint8 b2, Uint8 a2) 1397{ 1398 Uint32 Pixel1, Pixel2; 1399 RGBA8888_FROM_RGBA(Pixel1, r1, g1, b1, a1); 1400 RGBA8888_FROM_RGBA(Pixel2, r2, g2, b2, a2); 1401 return (Pixel1 == Pixel2); 1402} 1403 1404static int 1405GLES2_RenderClear(SDL_Renderer * renderer) 1406{ 1407 Uint8 r, g, b, a; 1408 1409 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1410 1411 GLES2_ActivateRenderer(renderer); 1412 1413 if (!CompareColors(data->clear_r, data->clear_g, data->clear_b, data->clear_a, 1414 renderer->r, renderer->g, renderer->b, renderer->a)) { 1415 1416 /* Select the color to clear with */ 1417 g = renderer->g; 1418 a = renderer->a; 1419 1420 if (renderer->target && 1421 (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || 1422 renderer->target->format == SDL_PIXELFORMAT_RGB888)) { 1423 r = renderer->b; 1424 b = renderer->r; 1425 } else { 1426 r = renderer->r; 1427 b = renderer->b; 1428 } 1429 1430 data->glClearColor((GLfloat) r * inv255f, 1431 (GLfloat) g * inv255f, 1432 (GLfloat) b * inv255f, 1433 (GLfloat) a * inv255f); 1434 data->clear_r = renderer->r; 1435 data->clear_g = renderer->g; 1436 data->clear_b = renderer->b; 1437 data->clear_a = renderer->a; 1438 } 1439 1440 if (renderer->clipping_enabled) { 1441 data->glDisable(GL_SCISSOR_TEST); 1442 } 1443 1444 data->glClear(GL_COLOR_BUFFER_BIT); 1445 1446 if (renderer->clipping_enabled) { 1447 data->glEnable(GL_SCISSOR_TEST); 1448 } 1449 1450 return 0; 1451} 1452 1453static void 1454GLES2_SetBlendMode(GLES2_DriverContext *data, SDL_BlendMode blendMode) 1455{ 1456 if (blendMode != data->current.blendMode) { 1457 if (blendMode == SDL_BLENDMODE_NONE) { 1458 data->glDisable(GL_BLEND); 1459 } else { 1460 data->glEnable(GL_BLEND); 1461 data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blendMode)), 1462 GetBlendFunc(SDL_GetBlendModeDstColorFactor(blendMode)), 1463 GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blendMode)), 1464 GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blendMode))); 1465 data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blendMode)), 1466 GetBlendEquation(SDL_GetBlendModeAlphaOperation(blendMode))); 1467 } 1468 data->current.blendMode = blendMode; 1469 } 1470} 1471 1472static void 1473GLES2_SetTexCoords(GLES2_DriverContext * data, SDL_bool enabled) 1474{ 1475 if (enabled != data->current.tex_coords) { 1476 if (enabled) { 1477 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); 1478 } else { 1479 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); 1480 } 1481 data->current.tex_coords = enabled; 1482 } 1483} 1484 1485static int 1486GLES2_SetDrawingState(SDL_Renderer * renderer) 1487{ 1488 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1489 GLES2_ProgramCacheEntry *program; 1490 Uint8 r, g, b, a; 1491 1492 GLES2_ActivateRenderer(renderer); 1493 1494 GLES2_SetBlendMode(data, renderer->blendMode); 1495 1496 GLES2_SetTexCoords(data, SDL_FALSE); 1497 1498 /* Activate an appropriate shader and set the projection matrix */ 1499 if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, 0, 0) < 0) { 1500 return -1; 1501 } 1502 1503 /* Select the color to draw with */ 1504 g = renderer->g; 1505 a = renderer->a; 1506 1507 if (renderer->target && 1508 (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || 1509 renderer->target->format == SDL_PIXELFORMAT_RGB888)) { 1510 r = renderer->b; 1511 b = renderer->r; 1512 } else { 1513 r = renderer->r; 1514 b = renderer->b; 1515 } 1516 1517 program = data->current_program; 1518 if (!CompareColors(program->color_r, program->color_g, program->color_b, program->color_a, r, g, b, a)) { 1519 /* Select the color to draw with */ 1520 data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f); 1521 program->color_r = r; 1522 program->color_g = g; 1523 program->color_b = b; 1524 program->color_a = a; 1525 } 1526 1527 return 0; 1528} 1529 1530static int 1531GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr, 1532 const void *vertexData, size_t dataSizeInBytes) 1533{ 1534 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1535 1536#if !SDL_GLES2_USE_VBOS 1537 data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData); 1538#else 1539 if (!data->vertex_buffers[attr]) { 1540 data->glGenBuffers(1, &data->vertex_buffers[attr]); 1541 } 1542 1543 data->glBindBuffer(GL_ARRAY_BUFFER, data->vertex_buffers[attr]); 1544 1545 if (data->vertex_buffer_size[attr] < dataSizeInBytes) { 1546 data->glBufferData(GL_ARRAY_BUFFER, dataSizeInBytes, vertexData, GL_STREAM_DRAW); 1547 data->vertex_buffer_size[attr] = dataSizeInBytes; 1548 } else { 1549 data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData); 1550 } 1551 1552 data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0); 1553#endif 1554 1555 return 0; 1556} 1557 1558static int 1559GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count) 1560{ 1561 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1562 GLfloat *vertices; 1563 int idx; 1564 1565 if (GLES2_SetDrawingState(renderer) < 0) { 1566 return -1; 1567 } 1568 1569 /* Emit the specified vertices as points */ 1570 vertices = SDL_stack_alloc(GLfloat, count * 2); 1571 for (idx = 0; idx < count; ++idx) { 1572 GLfloat x = points[idx].x + 0.5f; 1573 GLfloat y = points[idx].y + 0.5f; 1574 1575 vertices[idx * 2] = x; 1576 vertices[(idx * 2) + 1] = y; 1577 } 1578 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/ 1579 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat)); 1580 data->glDrawArrays(GL_POINTS, 0, count); 1581 SDL_stack_free(vertices); 1582 return 0; 1583} 1584 1585static int 1586GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count) 1587{ 1588 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1589 GLfloat *vertices; 1590 int idx; 1591 1592 if (GLES2_SetDrawingState(renderer) < 0) { 1593 return -1; 1594 } 1595 1596 /* Emit a line strip including the specified vertices */ 1597 vertices = SDL_stack_alloc(GLfloat, count * 2); 1598 for (idx = 0; idx < count; ++idx) { 1599 GLfloat x = points[idx].x + 0.5f; 1600 GLfloat y = points[idx].y + 0.5f; 1601 1602 vertices[idx * 2] = x; 1603 vertices[(idx * 2) + 1] = y; 1604 } 1605 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/ 1606 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, count * 2 * sizeof(GLfloat)); 1607 data->glDrawArrays(GL_LINE_STRIP, 0, count); 1608 1609 /* We need to close the endpoint of the line */ 1610 if (count == 2 || 1611 points[0].x != points[count-1].x || points[0].y != points[count-1].y) { 1612 data->glDrawArrays(GL_POINTS, count-1, 1); 1613 } 1614 SDL_stack_free(vertices); 1615 1616 return GL_CheckError("", renderer); 1617} 1618 1619static int 1620GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count) 1621{ 1622 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1623 GLfloat vertices[8]; 1624 int idx; 1625 1626 if (GLES2_SetDrawingState(renderer) < 0) { 1627 return -1; 1628 } 1629 1630 /* Emit a line loop for each rectangle */ 1631 for (idx = 0; idx < count; ++idx) { 1632 const SDL_FRect *rect = &rects[idx]; 1633 1634 GLfloat xMin = rect->x; 1635 GLfloat xMax = (rect->x + rect->w); 1636 GLfloat yMin = rect->y; 1637 GLfloat yMax = (rect->y + rect->h); 1638 1639 vertices[0] = xMin; 1640 vertices[1] = yMin; 1641 vertices[2] = xMax; 1642 vertices[3] = yMin; 1643 vertices[4] = xMin; 1644 vertices[5] = yMax; 1645 vertices[6] = xMax; 1646 vertices[7] = yMax; 1647 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/ 1648 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat)); 1649 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1650 } 1651 return GL_CheckError("", renderer); 1652} 1653 1654static int 1655GLES2_SetupCopy(SDL_Renderer *renderer, SDL_Texture *texture) 1656{ 1657 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1658 GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata; 1659 GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; 1660 GLES2_ProgramCacheEntry *program; 1661 Uint8 r, g, b, a; 1662 1663 /* Activate an appropriate shader and set the projection matrix */ 1664 if (renderer->target) { 1665 /* Check if we need to do color mapping between the source and render target textures */ 1666 if (renderer->target->format != texture->format) { 1667 switch (texture->format) { 1668 case SDL_PIXELFORMAT_ARGB8888: 1669 switch (renderer->target->format) { 1670 case SDL_PIXELFORMAT_ABGR8888: 1671 case SDL_PIXELFORMAT_BGR888: 1672 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; 1673 break; 1674 case SDL_PIXELFORMAT_RGB888: 1675 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; 1676 break; 1677 } 1678 break; 1679 case SDL_PIXELFORMAT_ABGR8888: 1680 switch (renderer->target->format) { 1681 case SDL_PIXELFORMAT_ARGB8888: 1682 case SDL_PIXELFORMAT_RGB888: 1683 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; 1684 break; 1685 case SDL_PIXELFORMAT_BGR888: 1686 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; 1687 break; 1688 } 1689 break; 1690 case SDL_PIXELFORMAT_RGB888: 1691 switch (renderer->target->format) { 1692 case SDL_PIXELFORMAT_ABGR8888: 1693 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; 1694 break; 1695 case SDL_PIXELFORMAT_ARGB8888: 1696 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; 1697 break; 1698 case SDL_PIXELFORMAT_BGR888: 1699 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; 1700 break; 1701 } 1702 break; 1703 case SDL_PIXELFORMAT_BGR888: 1704 switch (renderer->target->format) { 1705 case SDL_PIXELFORMAT_ABGR8888: 1706 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; 1707 break; 1708 case SDL_PIXELFORMAT_ARGB8888: 1709 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB; 1710 break; 1711 case SDL_PIXELFORMAT_RGB888: 1712 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; 1713 break; 1714 } 1715 break; 1716 case SDL_PIXELFORMAT_IYUV: 1717 case SDL_PIXELFORMAT_YV12: 1718 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV; 1719 break; 1720 case SDL_PIXELFORMAT_NV12: 1721 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12; 1722 break; 1723 case SDL_PIXELFORMAT_NV21: 1724 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21; 1725 break; 1726 case SDL_PIXELFORMAT_EXTERNAL_OES: 1727 sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES; 1728 break; 1729 default: 1730 return SDL_SetError("Unsupported texture format"); 1731 } 1732 } else { 1733 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */ 1734 } 1735 } else { 1736 switch (texture->format) { 1737 case SDL_PIXELFORMAT_ARGB8888: 1738 sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; 1739 break; 1740 case SDL_PIXELFORMAT_ABGR8888: 1741 sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; 1742 break; 1743 case SDL_PIXELFORMAT_RGB888: 1744 sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB; 1745 break; 1746 case SDL_PIXELFORMAT_BGR888: 1747 sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; 1748 break; 1749 case SDL_PIXELFORMAT_IYUV: 1750 case SDL_PIXELFORMAT_YV12: 1751 sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV; 1752 break; 1753 case SDL_PIXELFORMAT_NV12: 1754 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12; 1755 break; 1756 case SDL_PIXELFORMAT_NV21: 1757 sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21; 1758 break; 1759 case SDL_PIXELFORMAT_EXTERNAL_OES: 1760 sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES; 1761 break; 1762 default: 1763 return SDL_SetError("Unsupported texture format"); 1764 } 1765 } 1766 1767 if (GLES2_SelectProgram(renderer, sourceType, texture->w, texture->h) < 0) { 1768 return -1; 1769 } 1770 1771 /* Select the target texture */ 1772 if (tdata->yuv) { 1773 data->glActiveTexture(GL_TEXTURE2); 1774 data->glBindTexture(tdata->texture_type, tdata->texture_v); 1775 1776 data->glActiveTexture(GL_TEXTURE1); 1777 data->glBindTexture(tdata->texture_type, tdata->texture_u); 1778 1779 data->glActiveTexture(GL_TEXTURE0); 1780 } 1781 if (tdata->nv12) { 1782 data->glActiveTexture(GL_TEXTURE1); 1783 data->glBindTexture(tdata->texture_type, tdata->texture_u); 1784 1785 data->glActiveTexture(GL_TEXTURE0); 1786 } 1787 data->glBindTexture(tdata->texture_type, tdata->texture); 1788 1789 /* Configure color modulation */ 1790 g = texture->g; 1791 a = texture->a; 1792 1793 if (renderer->target && 1794 (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || 1795 renderer->target->format == SDL_PIXELFORMAT_RGB888)) { 1796 r = texture->b; 1797 b = texture->r; 1798 } else { 1799 r = texture->r; 1800 b = texture->b; 1801 } 1802 1803 program = data->current_program; 1804 1805 if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) { 1806 data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f); 1807 program->modulation_r = r; 1808 program->modulation_g = g; 1809 program->modulation_b = b; 1810 program->modulation_a = a; 1811 } 1812 1813 /* Configure texture blending */ 1814 GLES2_SetBlendMode(data, texture->blendMode); 1815 1816 GLES2_SetTexCoords(data, SDL_TRUE); 1817 return 0; 1818} 1819 1820static int 1821GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, 1822 const SDL_FRect *dstrect) 1823{ 1824 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1825 GLfloat vertices[8]; 1826 GLfloat texCoords[8]; 1827 1828 GLES2_ActivateRenderer(renderer); 1829 1830 if (GLES2_SetupCopy(renderer, texture) < 0) { 1831 return -1; 1832 } 1833 1834 /* Emit the textured quad */ 1835 vertices[0] = dstrect->x; 1836 vertices[1] = dstrect->y; 1837 vertices[2] = (dstrect->x + dstrect->w); 1838 vertices[3] = dstrect->y; 1839 vertices[4] = dstrect->x; 1840 vertices[5] = (dstrect->y + dstrect->h); 1841 vertices[6] = (dstrect->x + dstrect->w); 1842 vertices[7] = (dstrect->y + dstrect->h); 1843 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/ 1844 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat)); 1845 texCoords[0] = srcrect->x / (GLfloat)texture->w; 1846 texCoords[1] = srcrect->y / (GLfloat)texture->h; 1847 texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w; 1848 texCoords[3] = srcrect->y / (GLfloat)texture->h; 1849 texCoords[4] = srcrect->x / (GLfloat)texture->w; 1850 texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h; 1851 texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w; 1852 texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h; 1853 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/ 1854 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat)); 1855 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1856 1857 return GL_CheckError("", renderer); 1858} 1859 1860static int 1861GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect, 1862 const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) 1863{ 1864 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1865 GLfloat vertices[8]; 1866 GLfloat texCoords[8]; 1867 GLfloat translate[8]; 1868 GLfloat fAngle[4]; 1869 GLfloat tmp; 1870 1871 GLES2_ActivateRenderer(renderer); 1872 1873 if (GLES2_SetupCopy(renderer, texture) < 0) { 1874 return -1; 1875 } 1876 1877 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER); 1878 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE); 1879 fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle); 1880 /* Calculate the center of rotation */ 1881 translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x); 1882 translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y); 1883 1884 /* Emit the textured quad */ 1885 vertices[0] = dstrect->x; 1886 vertices[1] = dstrect->y; 1887 vertices[2] = (dstrect->x + dstrect->w); 1888 vertices[3] = dstrect->y; 1889 vertices[4] = dstrect->x; 1890 vertices[5] = (dstrect->y + dstrect->h); 1891 vertices[6] = (dstrect->x + dstrect->w); 1892 vertices[7] = (dstrect->y + dstrect->h); 1893 if (flip & SDL_FLIP_HORIZONTAL) { 1894 tmp = vertices[0]; 1895 vertices[0] = vertices[4] = vertices[2]; 1896 vertices[2] = vertices[6] = tmp; 1897 } 1898 if (flip & SDL_FLIP_VERTICAL) { 1899 tmp = vertices[1]; 1900 vertices[1] = vertices[3] = vertices[5]; 1901 vertices[5] = vertices[7] = tmp; 1902 } 1903 1904 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle); 1905 data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate); 1906 data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/ 1907 1908 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat)); 1909 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat)); 1910 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat)); 1911 1912 texCoords[0] = srcrect->x / (GLfloat)texture->w; 1913 texCoords[1] = srcrect->y / (GLfloat)texture->h; 1914 texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w; 1915 texCoords[3] = srcrect->y / (GLfloat)texture->h; 1916 texCoords[4] = srcrect->x / (GLfloat)texture->w; 1917 texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h; 1918 texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w; 1919 texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h; 1920 /*data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);*/ 1921 GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_TEXCOORD, texCoords, 8 * sizeof(GLfloat)); 1922 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1923 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER); 1924 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE); 1925 1926 return GL_CheckError("", renderer); 1927} 1928 1929static int 1930GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, 1931 Uint32 pixel_format, void * pixels, int pitch) 1932{ 1933 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 1934 Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; 1935 size_t buflen; 1936 void *temp_pixels; 1937 int temp_pitch; 1938 Uint8 *src, *dst, *tmp; 1939 int w, h, length, rows; 1940 int status; 1941 1942 GLES2_ActivateRenderer(renderer); 1943 1944 temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); 1945 buflen = (size_t) (rect->h * temp_pitch); 1946 if (buflen == 0) { 1947 return 0; /* nothing to do. */ 1948 } 1949 1950 temp_pixels = SDL_malloc(buflen); 1951 if (!temp_pixels) { 1952 return SDL_OutOfMemory(); 1953 } 1954 1955 SDL_GetRendererOutputSize(renderer, &w, &h); 1956 1957 data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h, 1958 rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels); 1959 if (GL_CheckError("glReadPixels()", renderer) < 0) { 1960 return -1; 1961 } 1962 1963 /* Flip the rows to be top-down if necessary */ 1964 if (!renderer->target) { 1965 length = rect->w * SDL_BYTESPERPIXEL(temp_format); 1966 src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; 1967 dst = (Uint8*)temp_pixels; 1968 tmp = SDL_stack_alloc(Uint8, length); 1969 rows = rect->h / 2; 1970 while (rows--) { 1971 SDL_memcpy(tmp, dst, length); 1972 SDL_memcpy(dst, src, length); 1973 SDL_memcpy(src, tmp, length); 1974 dst += temp_pitch; 1975 src -= temp_pitch; 1976 } 1977 SDL_stack_free(tmp); 1978 } 1979 1980 status = SDL_ConvertPixels(rect->w, rect->h, 1981 temp_format, temp_pixels, temp_pitch, 1982 pixel_format, pixels, pitch); 1983 SDL_free(temp_pixels); 1984 1985 return status; 1986} 1987 1988static void 1989GLES2_RenderPresent(SDL_Renderer *renderer) 1990{ 1991 GLES2_ActivateRenderer(renderer); 1992 1993 /* Tell the video driver to swap buffers */ 1994 SDL_GL_SwapWindow(renderer->window); 1995} 1996 1997 1998/************************************************************************************************* 1999 * Bind/unbinding of textures 2000 *************************************************************************************************/ 2001static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); 2002static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture); 2003 2004static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) 2005{ 2006 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 2007 GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata; 2008 GLES2_ActivateRenderer(renderer); 2009 2010 data->glBindTexture(texturedata->texture_type, texturedata->texture); 2011 2012 if (texw) { 2013 *texw = 1.0; 2014 } 2015 if (texh) { 2016 *texh = 1.0; 2017 } 2018 2019 return 0; 2020} 2021 2022static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) 2023{ 2024 GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; 2025 GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata; 2026 GLES2_ActivateRenderer(renderer); 2027 2028 data->glBindTexture(texturedata->texture_type, 0); 2029 2030 return 0; 2031} 2032 2033 2034/************************************************************************************************* 2035 * Renderer instantiation * 2036 *************************************************************************************************/ 2037 2038#ifdef ZUNE_HD 2039#define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B 2040#endif 2041 2042static void 2043GLES2_ResetState(SDL_Renderer *renderer) 2044{ 2045 GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata; 2046 2047 if (SDL_CurrentContext == data->context) { 2048 GLES2_UpdateViewport(renderer); 2049 } else { 2050 GLES2_ActivateRenderer(renderer); 2051 } 2052 2053 data->current.blendMode = SDL_BLENDMODE_INVALID; 2054 data->current.tex_coords = SDL_FALSE; 2055 2056 data->glActiveTexture(GL_TEXTURE0); 2057 data->glPixelStorei(GL_PACK_ALIGNMENT, 1); 2058 data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 2059 2060 data->glClearColor((GLfloat) data->clear_r * inv255f, 2061 (GLfloat) data->clear_g * inv255f, 2062 (GLfloat) data->clear_b * inv255f, 2063 (GLfloat) data->clear_a * inv255f); 2064 2065 data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION); 2066 data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); 2067 2068 GL_CheckError("", renderer); 2069} 2070 2071static SDL_Renderer * 2072GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) 2073{ 2074 SDL_Renderer *renderer; 2075 GLES2_DriverContext *data; 2076 GLint nFormats; 2077#ifndef ZUNE_HD 2078 GLboolean hasCompiler; 2079#endif 2080 Uint32 window_flags = 0; /* -Wconditional-uninitialized */ 2081 GLint window_framebuffer; 2082 GLint value; 2083 int profile_mask = 0, major = 0, minor = 0; 2084 SDL_bool changed_window = SDL_FALSE; 2085 2086 if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask) < 0) { 2087 goto error; 2088 } 2089 if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major) < 0) { 2090 goto error; 2091 } 2092 if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor) < 0) { 2093 goto error; 2094 } 2095 2096 window_flags = SDL_GetWindowFlags(window); 2097 /* OpenGL ES 3.0 is a superset of OpenGL ES 2.0 */ 2098 if (!(window_flags & SDL_WINDOW_OPENGL) || 2099 profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) { 2100 2101 changed_window = SDL_TRUE; 2102 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); 2103 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); 2104 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); 2105 2106 if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { 2107 goto error; 2108 } 2109 } 2110 2111 /* Create the renderer struct */ 2112 renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer)); 2113 if (!renderer) { 2114 SDL_OutOfMemory(); 2115 goto error; 2116 } 2117 2118 data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext)); 2119 if (!data) { 2120 GLES2_DestroyRenderer(renderer); 2121 SDL_OutOfMemory(); 2122 goto error; 2123 } 2124 renderer->info = GLES2_RenderDriver.info; 2125 renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); 2126 renderer->driverdata = data; 2127 renderer->window = window; 2128 2129 /* Create an OpenGL ES 2.0 context */ 2130 data->context = SDL_GL_CreateContext(window); 2131 if (!data->context) { 2132 GLES2_DestroyRenderer(renderer); 2133 goto error; 2134 } 2135 if (SDL_GL_MakeCurrent(window, data->context) < 0) { 2136 GLES2_DestroyRenderer(renderer); 2137 goto error; 2138 } 2139 2140 if (GLES2_LoadFunctions(data) < 0) { 2141 GLES2_DestroyRenderer(renderer); 2142 goto error; 2143 } 2144 2145#if __WINRT__ 2146 /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync 2147 * is turned on. Not doing so will freeze the screen's contents to that 2148 * of the first drawn frame. 2149 */ 2150 flags |= SDL_RENDERER_PRESENTVSYNC; 2151#endif 2152 2153 if (flags & SDL_RENDERER_PRESENTVSYNC) { 2154 SDL_GL_SetSwapInterval(1); 2155 } else { 2156 SDL_GL_SetSwapInterval(0); 2157 } 2158 if (SDL_GL_GetSwapInterval() > 0) { 2159 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; 2160 } 2161 2162 /* Check for debug output support */ 2163 if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 && 2164 (value & SDL_GL_CONTEXT_DEBUG_FLAG)) { 2165 data->debug_enabled = SDL_TRUE; 2166 } 2167 2168 value = 0; 2169 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); 2170 renderer->info.max_texture_width = value; 2171 value = 0; 2172 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); 2173 renderer->info.max_texture_height = value; 2174 2175 /* Determine supported shader formats */ 2176 /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */ 2177#ifdef ZUNE_HD 2178 nFormats = 1; 2179#else /* !ZUNE_HD */ 2180 data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats); 2181 data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler); 2182 if (hasCompiler) { 2183 ++nFormats; 2184 } 2185#endif /* ZUNE_HD */ 2186 data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum)); 2187 if (!data->shader_formats) { 2188 GLES2_DestroyRenderer(renderer); 2189 SDL_OutOfMemory(); 2190 goto error; 2191 } 2192 data->shader_format_count = nFormats; 2193#ifdef ZUNE_HD 2194 data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV; 2195#else /* !ZUNE_HD */ 2196 data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats); 2197 if (hasCompiler) { 2198 data->shader_formats[nFormats - 1] = (GLenum)-1; 2199 } 2200#endif /* ZUNE_HD */ 2201 2202 data->framebuffers = NULL; 2203 data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer); 2204 data->window_framebuffer = (GLuint)window_framebuffer; 2205 2206 /* Populate the function pointers for the module */ 2207 renderer->WindowEvent = GLES2_WindowEvent; 2208 renderer->GetOutputSize = GLES2_GetOutputSize; 2209 renderer->SupportsBlendMode = GLES2_SupportsBlendMode; 2210 renderer->CreateTexture = GLES2_CreateTexture; 2211 renderer->UpdateTexture = GLES2_UpdateTexture; 2212 renderer->UpdateTextureYUV = GLES2_UpdateTextureYUV; 2213 renderer->LockTexture = GLES2_LockTexture; 2214 renderer->UnlockTexture = GLES2_UnlockTexture; 2215 renderer->SetRenderTarget = GLES2_SetRenderTarget; 2216 renderer->UpdateViewport = GLES2_UpdateViewport; 2217 renderer->UpdateClipRect = GLES2_UpdateClipRect; 2218 renderer->RenderClear = GLES2_RenderClear; 2219 renderer->RenderDrawPoints = GLES2_RenderDrawPoints; 2220 renderer->RenderDrawLines = GLES2_RenderDrawLines; 2221 renderer->RenderFillRects = GLES2_RenderFillRects; 2222 renderer->RenderCopy = GLES2_RenderCopy; 2223 renderer->RenderCopyEx = GLES2_RenderCopyEx; 2224 renderer->RenderReadPixels = GLES2_RenderReadPixels; 2225 renderer->RenderPresent = GLES2_RenderPresent; 2226 renderer->DestroyTexture = GLES2_DestroyTexture; 2227 renderer->DestroyRenderer = GLES2_DestroyRenderer; 2228 renderer->GL_BindTexture = GLES2_BindTexture; 2229 renderer->GL_UnbindTexture = GLES2_UnbindTexture; 2230 2231 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; 2232 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; 2233 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12; 2234 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21; 2235#ifdef GL_TEXTURE_EXTERNAL_OES 2236 renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_EXTERNAL_OES; 2237#endif 2238 2239 GLES2_ResetState(renderer); 2240 2241 return renderer; 2242 2243error: 2244 if (changed_window) { 2245 /* Uh oh, better try to put it back... */ 2246 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); 2247 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); 2248 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); 2249 SDL_RecreateWindow(window, window_flags); 2250 } 2251 return NULL; 2252} 2253 2254#endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */ 2255 2256/* vi: set ts=4 sw=4 expandtab: */ 2257[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.