SDL_render_gles2.c 78 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any damages
  6. arising from the use of this software.
  7. Permission is granted to anyone to use this software for any purpose,
  8. including commercial applications, and to alter it and redistribute it
  9. freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you must not
  11. claim that you wrote the original software. If you use this software
  12. in a product, an acknowledgment in the product documentation would be
  13. appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and must not be
  15. misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include "SDL_internal.h"
  19. #ifdef SDL_VIDEO_RENDER_OGL_ES2
  20. #include "../../video/SDL_sysvideo.h" // For SDL_RecreateWindow
  21. #include <SDL3/SDL_opengles2.h>
  22. #include "../SDL_sysrender.h"
  23. #include "../../video/SDL_pixels_c.h"
  24. #include "SDL_shaders_gles2.h"
  25. /* WebGL doesn't offer client-side arrays, so use Vertex Buffer Objects
  26. on Emscripten, which converts GLES2 into WebGL calls.
  27. In all other cases, attempt to use client-side arrays, as they tend to
  28. be dramatically faster when not batching, and about the same when
  29. we are. */
  30. #ifdef SDL_PLATFORM_EMSCRIPTEN
  31. #define USE_VERTEX_BUFFER_OBJECTS 1
  32. #else
  33. #define USE_VERTEX_BUFFER_OBJECTS 0
  34. #endif
  35. /* To prevent unnecessary window recreation,
  36. * these should match the defaults selected in SDL_GL_ResetAttributes
  37. */
  38. #define RENDERER_CONTEXT_MAJOR 2
  39. #define RENDERER_CONTEXT_MINOR 0
  40. /*************************************************************************************************
  41. * Context structures *
  42. *************************************************************************************************/
  43. typedef struct GLES2_FBOList GLES2_FBOList;
  44. struct GLES2_FBOList
  45. {
  46. Uint32 w, h;
  47. GLuint FBO;
  48. GLES2_FBOList *next;
  49. };
  50. typedef struct GLES2_TextureData
  51. {
  52. GLuint texture;
  53. bool texture_external;
  54. GLenum texture_type;
  55. GLenum pixel_format;
  56. GLenum pixel_type;
  57. void *pixel_data;
  58. int pitch;
  59. #ifdef SDL_HAVE_YUV
  60. // YUV texture support
  61. bool yuv;
  62. bool nv12;
  63. GLuint texture_v;
  64. GLuint texture_v_external;
  65. GLuint texture_u;
  66. GLuint texture_u_external;
  67. #endif
  68. GLES2_FBOList *fbo;
  69. } GLES2_TextureData;
  70. typedef enum
  71. {
  72. GLES2_ATTRIBUTE_POSITION = 0,
  73. GLES2_ATTRIBUTE_COLOR = 1,
  74. GLES2_ATTRIBUTE_TEXCOORD = 2,
  75. } GLES2_Attribute;
  76. typedef enum
  77. {
  78. GLES2_UNIFORM_PROJECTION,
  79. GLES2_UNIFORM_TEXTURE,
  80. GLES2_UNIFORM_TEXTURE_U,
  81. GLES2_UNIFORM_TEXTURE_V,
  82. GLES2_UNIFORM_OFFSET,
  83. GLES2_UNIFORM_MATRIX,
  84. NUM_GLES2_UNIFORMS
  85. } GLES2_Uniform;
  86. static const char *GLES2_UniformNames[] = {
  87. "u_projection",
  88. "u_texture",
  89. "u_texture_u",
  90. "u_texture_v",
  91. "u_offset",
  92. "u_matrix"
  93. };
  94. SDL_COMPILE_TIME_ASSERT(GLES2_UniformNames, SDL_arraysize(GLES2_UniformNames) == NUM_GLES2_UNIFORMS);
  95. typedef struct GLES2_ProgramCacheEntry
  96. {
  97. GLuint id;
  98. GLuint vertex_shader;
  99. GLuint fragment_shader;
  100. GLuint uniform_locations[NUM_GLES2_UNIFORMS];
  101. GLfloat projection[4][4];
  102. const float *shader_params;
  103. struct GLES2_ProgramCacheEntry *prev;
  104. struct GLES2_ProgramCacheEntry *next;
  105. } GLES2_ProgramCacheEntry;
  106. typedef struct GLES2_ProgramCache
  107. {
  108. int count;
  109. GLES2_ProgramCacheEntry *head;
  110. GLES2_ProgramCacheEntry *tail;
  111. } GLES2_ProgramCache;
  112. typedef enum
  113. {
  114. GLES2_IMAGESOURCE_INVALID,
  115. GLES2_IMAGESOURCE_SOLID,
  116. GLES2_IMAGESOURCE_TEXTURE_ABGR,
  117. GLES2_IMAGESOURCE_TEXTURE_ARGB,
  118. GLES2_IMAGESOURCE_TEXTURE_RGB,
  119. GLES2_IMAGESOURCE_TEXTURE_BGR,
  120. GLES2_IMAGESOURCE_TEXTURE_YUV,
  121. GLES2_IMAGESOURCE_TEXTURE_NV12,
  122. GLES2_IMAGESOURCE_TEXTURE_NV21,
  123. GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES
  124. } GLES2_ImageSource;
  125. typedef struct
  126. {
  127. SDL_Rect viewport;
  128. bool viewport_dirty;
  129. SDL_Texture *texture;
  130. SDL_Texture *target;
  131. SDL_BlendMode blend;
  132. bool cliprect_enabled_dirty;
  133. bool cliprect_enabled;
  134. bool cliprect_dirty;
  135. SDL_Rect cliprect;
  136. bool texturing;
  137. bool texturing_dirty;
  138. SDL_FColor clear_color;
  139. bool clear_color_dirty;
  140. int drawablew;
  141. int drawableh;
  142. GLES2_ProgramCacheEntry *program;
  143. const float *shader_params;
  144. GLfloat projection[4][4];
  145. } GLES2_DrawStateCache;
  146. typedef struct GLES2_RenderData
  147. {
  148. SDL_GLContext context;
  149. bool debug_enabled;
  150. bool GL_EXT_blend_minmax_supported;
  151. #define SDL_PROC(ret, func, params) ret (APIENTRY *func) params;
  152. #include "SDL_gles2funcs.h"
  153. #undef SDL_PROC
  154. GLES2_FBOList *framebuffers;
  155. GLuint window_framebuffer;
  156. GLuint shader_id_cache[GLES2_SHADER_COUNT];
  157. GLES2_ProgramCache program_cache;
  158. Uint8 clear_r, clear_g, clear_b, clear_a;
  159. #if USE_VERTEX_BUFFER_OBJECTS
  160. GLuint vertex_buffers[8];
  161. size_t vertex_buffer_size[8];
  162. int current_vertex_buffer;
  163. #endif
  164. GLES2_DrawStateCache drawstate;
  165. GLES2_ShaderIncludeType texcoord_precision_hint;
  166. } GLES2_RenderData;
  167. #define GLES2_MAX_CACHED_PROGRAMS 8
  168. static const char *GL_TranslateError(GLenum error)
  169. {
  170. #define GL_ERROR_TRANSLATE(e) \
  171. case e: \
  172. return #e;
  173. switch (error) {
  174. GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
  175. GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
  176. GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
  177. GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
  178. GL_ERROR_TRANSLATE(GL_NO_ERROR)
  179. default:
  180. return "UNKNOWN";
  181. }
  182. #undef GL_ERROR_TRANSLATE
  183. }
  184. static void GL_ClearErrors(SDL_Renderer *renderer)
  185. {
  186. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  187. if (!data->debug_enabled) {
  188. return;
  189. }
  190. while (data->glGetError() != GL_NO_ERROR) {
  191. // continue;
  192. }
  193. }
  194. static bool GL_CheckAllErrors(const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
  195. {
  196. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  197. bool result = true;
  198. if (!data->debug_enabled) {
  199. return true;
  200. }
  201. // check gl errors (can return multiple errors)
  202. for (;;) {
  203. GLenum error = data->glGetError();
  204. if (error != GL_NO_ERROR) {
  205. if (!prefix || prefix[0] == '\0') {
  206. prefix = "generic";
  207. }
  208. SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
  209. result = false;
  210. } else {
  211. break;
  212. }
  213. }
  214. return result;
  215. }
  216. #if 0
  217. #define GL_CheckError(prefix, renderer)
  218. #else
  219. #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION)
  220. #endif
  221. /*************************************************************************************************
  222. * Renderer state APIs *
  223. *************************************************************************************************/
  224. static bool GLES2_LoadFunctions(GLES2_RenderData *data)
  225. {
  226. #ifdef SDL_VIDEO_DRIVER_UIKIT
  227. #define __SDL_NOGETPROCADDR__
  228. #elif defined(SDL_VIDEO_DRIVER_ANDROID)
  229. #define __SDL_NOGETPROCADDR__
  230. #endif
  231. #if defined __SDL_NOGETPROCADDR__
  232. #define SDL_PROC(ret, func, params) data->func = func;
  233. #else
  234. #define SDL_PROC(ret, func, params) \
  235. do { \
  236. data->func = (ret (APIENTRY *) params)SDL_GL_GetProcAddress(#func); \
  237. if (!data->func) { \
  238. return SDL_SetError("Couldn't load GLES2 function %s: %s", #func, SDL_GetError()); \
  239. } \
  240. } while (0);
  241. #endif // __SDL_NOGETPROCADDR__
  242. #include "SDL_gles2funcs.h"
  243. #undef SDL_PROC
  244. return true;
  245. }
  246. static GLES2_FBOList *GLES2_GetFBO(GLES2_RenderData *data, Uint32 w, Uint32 h)
  247. {
  248. GLES2_FBOList *result = data->framebuffers;
  249. while ((result) && ((result->w != w) || (result->h != h))) {
  250. result = result->next;
  251. }
  252. if (!result) {
  253. result = (GLES2_FBOList *)SDL_malloc(sizeof(GLES2_FBOList));
  254. result->w = w;
  255. result->h = h;
  256. data->glGenFramebuffers(1, &result->FBO);
  257. result->next = data->framebuffers;
  258. data->framebuffers = result;
  259. }
  260. return result;
  261. }
  262. static bool GLES2_ActivateRenderer(SDL_Renderer *renderer)
  263. {
  264. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  265. if (SDL_GL_GetCurrentContext() != data->context) {
  266. // Null out the current program to ensure we set it again
  267. data->drawstate.program = NULL;
  268. if (!SDL_GL_MakeCurrent(renderer->window, data->context)) {
  269. return false;
  270. }
  271. }
  272. GL_ClearErrors(renderer);
  273. return true;
  274. }
  275. static void GLES2_WindowEvent(SDL_Renderer *renderer, const SDL_WindowEvent *event)
  276. {
  277. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  278. if (event->type == SDL_EVENT_WINDOW_MINIMIZED) {
  279. // According to Apple documentation, we need to finish drawing NOW!
  280. data->glFinish();
  281. }
  282. }
  283. static GLenum GetBlendFunc(SDL_BlendFactor factor)
  284. {
  285. switch (factor) {
  286. case SDL_BLENDFACTOR_ZERO:
  287. return GL_ZERO;
  288. case SDL_BLENDFACTOR_ONE:
  289. return GL_ONE;
  290. case SDL_BLENDFACTOR_SRC_COLOR:
  291. return GL_SRC_COLOR;
  292. case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR:
  293. return GL_ONE_MINUS_SRC_COLOR;
  294. case SDL_BLENDFACTOR_SRC_ALPHA:
  295. return GL_SRC_ALPHA;
  296. case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA:
  297. return GL_ONE_MINUS_SRC_ALPHA;
  298. case SDL_BLENDFACTOR_DST_COLOR:
  299. return GL_DST_COLOR;
  300. case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR:
  301. return GL_ONE_MINUS_DST_COLOR;
  302. case SDL_BLENDFACTOR_DST_ALPHA:
  303. return GL_DST_ALPHA;
  304. case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA:
  305. return GL_ONE_MINUS_DST_ALPHA;
  306. default:
  307. return GL_INVALID_ENUM;
  308. }
  309. }
  310. static GLenum GetBlendEquation(SDL_BlendOperation operation)
  311. {
  312. switch (operation) {
  313. case SDL_BLENDOPERATION_ADD:
  314. return GL_FUNC_ADD;
  315. case SDL_BLENDOPERATION_SUBTRACT:
  316. return GL_FUNC_SUBTRACT;
  317. case SDL_BLENDOPERATION_REV_SUBTRACT:
  318. return GL_FUNC_REVERSE_SUBTRACT;
  319. case SDL_BLENDOPERATION_MINIMUM:
  320. return GL_MIN_EXT;
  321. case SDL_BLENDOPERATION_MAXIMUM:
  322. return GL_MAX_EXT;
  323. default:
  324. return GL_INVALID_ENUM;
  325. }
  326. }
  327. static bool GLES2_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMode)
  328. {
  329. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  330. SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode);
  331. SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode);
  332. SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode);
  333. SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode);
  334. SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode);
  335. SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode);
  336. if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM ||
  337. GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM ||
  338. GetBlendEquation(colorOperation) == GL_INVALID_ENUM ||
  339. GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM ||
  340. GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM ||
  341. GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) {
  342. return false;
  343. }
  344. if (colorOperation == SDL_BLENDOPERATION_MINIMUM && !data->GL_EXT_blend_minmax_supported) {
  345. return false;
  346. }
  347. if (colorOperation == SDL_BLENDOPERATION_MAXIMUM && !data->GL_EXT_blend_minmax_supported) {
  348. return false;
  349. }
  350. return true;
  351. }
  352. static GLES2_ProgramCacheEntry *GLES2_CacheProgram(GLES2_RenderData *data, GLuint vertex, GLuint fragment)
  353. {
  354. GLES2_ProgramCacheEntry *entry;
  355. GLint linkSuccessful;
  356. int i;
  357. // Check if we've already cached this program
  358. entry = data->program_cache.head;
  359. while (entry) {
  360. if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) {
  361. break;
  362. }
  363. entry = entry->next;
  364. }
  365. if (entry) {
  366. if (data->program_cache.head != entry) {
  367. if (entry->next) {
  368. entry->next->prev = entry->prev;
  369. }
  370. if (entry->prev) {
  371. entry->prev->next = entry->next;
  372. }
  373. entry->prev = NULL;
  374. entry->next = data->program_cache.head;
  375. data->program_cache.head->prev = entry;
  376. data->program_cache.head = entry;
  377. }
  378. return entry;
  379. }
  380. // Create a program cache entry
  381. entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
  382. if (!entry) {
  383. return NULL;
  384. }
  385. entry->vertex_shader = vertex;
  386. entry->fragment_shader = fragment;
  387. // Create the program and link it
  388. entry->id = data->glCreateProgram();
  389. data->glAttachShader(entry->id, vertex);
  390. data->glAttachShader(entry->id, fragment);
  391. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
  392. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_COLOR, "a_color");
  393. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
  394. data->glLinkProgram(entry->id);
  395. data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
  396. if (!linkSuccessful) {
  397. data->glDeleteProgram(entry->id);
  398. SDL_free(entry);
  399. SDL_SetError("Failed to link shader program");
  400. return NULL;
  401. }
  402. // Predetermine locations of uniform variables
  403. for (i = 0; i < NUM_GLES2_UNIFORMS; ++i) {
  404. entry->uniform_locations[i] = data->glGetUniformLocation(entry->id, GLES2_UniformNames[i]);
  405. }
  406. data->glUseProgram(entry->id);
  407. if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] != -1) {
  408. data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); // always texture unit 2.
  409. }
  410. if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] != -1) {
  411. data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); // always texture unit 1.
  412. }
  413. if (entry->uniform_locations[GLES2_UNIFORM_TEXTURE] != -1) {
  414. data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); // always texture unit 0.
  415. }
  416. if (entry->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
  417. data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
  418. }
  419. // Cache the linked program
  420. if (data->program_cache.head) {
  421. entry->next = data->program_cache.head;
  422. data->program_cache.head->prev = entry;
  423. } else {
  424. data->program_cache.tail = entry;
  425. }
  426. data->program_cache.head = entry;
  427. ++data->program_cache.count;
  428. // Evict the last entry from the cache if we exceed the limit
  429. if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS) {
  430. data->glDeleteProgram(data->program_cache.tail->id);
  431. data->program_cache.tail = data->program_cache.tail->prev;
  432. if (data->program_cache.tail) {
  433. SDL_free(data->program_cache.tail->next);
  434. data->program_cache.tail->next = NULL;
  435. }
  436. --data->program_cache.count;
  437. }
  438. return entry;
  439. }
  440. static GLuint GLES2_CacheShader(GLES2_RenderData *data, GLES2_ShaderType type, GLenum shader_type)
  441. {
  442. GLuint id = 0;
  443. GLint compileSuccessful = GL_FALSE;
  444. int attempt, num_src;
  445. const GLchar *shader_src_list[3];
  446. const GLchar *shader_body = GLES2_GetShader(type);
  447. if (!shader_body) {
  448. SDL_SetError("No shader body src");
  449. return true;
  450. }
  451. for (attempt = 0; attempt < 2 && !compileSuccessful; ++attempt) {
  452. num_src = 0;
  453. shader_src_list[num_src++] = GLES2_GetShaderPrologue(type);
  454. if (shader_type == GL_FRAGMENT_SHADER) {
  455. if (attempt == 0) {
  456. shader_src_list[num_src++] = GLES2_GetShaderInclude(data->texcoord_precision_hint);
  457. } else {
  458. shader_src_list[num_src++] = GLES2_GetShaderInclude(GLES2_SHADER_FRAGMENT_INCLUDE_UNDEF_PRECISION);
  459. }
  460. }
  461. shader_src_list[num_src++] = shader_body;
  462. SDL_assert(num_src <= SDL_arraysize(shader_src_list));
  463. #ifdef DEBUG_PRINT_SHADERS
  464. {
  465. int i;
  466. char *message = NULL;
  467. SDL_asprintf(&message, "Compiling shader:\n");
  468. for (i = 0; i < num_src; ++i) {
  469. char *last_message = message;
  470. SDL_asprintf(&message, "%s%s", last_message, shader_src_list[i]);
  471. SDL_free(last_message);
  472. }
  473. SDL_Log("%s", message);
  474. SDL_free(message);
  475. }
  476. #endif
  477. // Compile
  478. id = data->glCreateShader(shader_type);
  479. data->glShaderSource(id, num_src, shader_src_list, NULL);
  480. data->glCompileShader(id);
  481. data->glGetShaderiv(id, GL_COMPILE_STATUS, &compileSuccessful);
  482. }
  483. if (!compileSuccessful) {
  484. char *info = NULL;
  485. int length = 0;
  486. data->glGetShaderiv(id, GL_INFO_LOG_LENGTH, &length);
  487. if (length > 0) {
  488. info = (char *)SDL_malloc(length);
  489. if (info) {
  490. data->glGetShaderInfoLog(id, length, &length, info);
  491. }
  492. }
  493. if (info) {
  494. SDL_SetError("Failed to load the shader %d: %s", type, info);
  495. SDL_free(info);
  496. } else {
  497. SDL_SetError("Failed to load the shader %d", type);
  498. }
  499. data->glDeleteShader(id);
  500. return true;
  501. }
  502. // Cache
  503. data->shader_id_cache[(Uint32)type] = id;
  504. return id;
  505. }
  506. static bool GLES2_CacheShaders(GLES2_RenderData *data)
  507. {
  508. int shader;
  509. data->texcoord_precision_hint = GLES2_GetTexCoordPrecisionEnumFromHint();
  510. for (shader = 0; shader < GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES; ++shader) {
  511. GLenum shader_type;
  512. if (shader == GLES2_SHADER_VERTEX_DEFAULT) {
  513. shader_type = GL_VERTEX_SHADER;
  514. } else {
  515. shader_type = GL_FRAGMENT_SHADER;
  516. }
  517. if (!GLES2_CacheShader(data, (GLES2_ShaderType)shader, shader_type)) {
  518. return false;
  519. }
  520. }
  521. return true;
  522. }
  523. static bool GLES2_SelectProgram(GLES2_RenderData *data, GLES2_ImageSource source, SDL_Colorspace colorspace)
  524. {
  525. GLuint vertex;
  526. GLuint fragment;
  527. GLES2_ShaderType vtype, ftype;
  528. GLES2_ProgramCacheEntry *program;
  529. const float *shader_params = NULL;
  530. // Select an appropriate shader pair for the specified modes
  531. vtype = GLES2_SHADER_VERTEX_DEFAULT;
  532. switch (source) {
  533. case GLES2_IMAGESOURCE_SOLID:
  534. ftype = GLES2_SHADER_FRAGMENT_SOLID;
  535. break;
  536. case GLES2_IMAGESOURCE_TEXTURE_ABGR:
  537. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR;
  538. break;
  539. case GLES2_IMAGESOURCE_TEXTURE_ARGB:
  540. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB;
  541. break;
  542. case GLES2_IMAGESOURCE_TEXTURE_RGB:
  543. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB;
  544. break;
  545. case GLES2_IMAGESOURCE_TEXTURE_BGR:
  546. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR;
  547. break;
  548. #ifdef SDL_HAVE_YUV
  549. case GLES2_IMAGESOURCE_TEXTURE_YUV:
  550. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV;
  551. shader_params = SDL_GetYCbCRtoRGBConversionMatrix(colorspace, 0, 0, 8);
  552. if (!shader_params) {
  553. SDL_SetError("Unsupported YUV colorspace");
  554. goto fault;
  555. }
  556. break;
  557. case GLES2_IMAGESOURCE_TEXTURE_NV12:
  558. if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
  559. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RG;
  560. } else {
  561. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV12_RA;
  562. }
  563. shader_params = SDL_GetYCbCRtoRGBConversionMatrix(colorspace, 0, 0, 8);
  564. if (!shader_params) {
  565. SDL_SetError("Unsupported YUV colorspace");
  566. goto fault;
  567. }
  568. break;
  569. case GLES2_IMAGESOURCE_TEXTURE_NV21:
  570. if (SDL_GetHintBoolean("SDL_RENDER_OPENGL_NV12_RG_SHADER", false)) {
  571. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_RG;
  572. } else {
  573. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_NV21_RA;
  574. }
  575. shader_params = SDL_GetYCbCRtoRGBConversionMatrix(colorspace, 0, 0, 8);
  576. if (!shader_params) {
  577. SDL_SetError("Unsupported YUV colorspace");
  578. goto fault;
  579. }
  580. break;
  581. #endif // SDL_HAVE_YUV
  582. case GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES:
  583. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES;
  584. break;
  585. default:
  586. goto fault;
  587. }
  588. // Load the requested shaders
  589. vertex = data->shader_id_cache[(Uint32)vtype];
  590. if (!vertex) {
  591. vertex = GLES2_CacheShader(data, vtype, GL_VERTEX_SHADER);
  592. if (!vertex) {
  593. goto fault;
  594. }
  595. }
  596. fragment = data->shader_id_cache[(Uint32)ftype];
  597. if (!fragment) {
  598. fragment = GLES2_CacheShader(data, ftype, GL_FRAGMENT_SHADER);
  599. if (!fragment) {
  600. goto fault;
  601. }
  602. }
  603. // Check if we need to change programs at all
  604. if (data->drawstate.program &&
  605. data->drawstate.program->vertex_shader == vertex &&
  606. data->drawstate.program->fragment_shader == fragment &&
  607. data->drawstate.program->shader_params == shader_params) {
  608. return true;
  609. }
  610. // Generate a matching program
  611. program = GLES2_CacheProgram(data, vertex, fragment);
  612. if (!program) {
  613. goto fault;
  614. }
  615. // Select that program in OpenGL
  616. data->glUseProgram(program->id);
  617. if (shader_params && shader_params != program->shader_params) {
  618. // YUV shader params are Yoffset, 0, Rcoeff, 0, Gcoeff, 0, Bcoeff, 0
  619. if (program->uniform_locations[GLES2_UNIFORM_OFFSET] != -1) {
  620. data->glUniform3f(program->uniform_locations[GLES2_UNIFORM_OFFSET], shader_params[0], shader_params[1], shader_params[2]);
  621. }
  622. if (program->uniform_locations[GLES2_UNIFORM_MATRIX] != -1) {
  623. GLfloat matrix[3 * 3];
  624. matrix[0 * 3 + 0] = shader_params[4];
  625. matrix[0 * 3 + 1] = shader_params[5];
  626. matrix[0 * 3 + 2] = shader_params[6];
  627. matrix[1 * 3 + 0] = shader_params[8];
  628. matrix[1 * 3 + 1] = shader_params[9];
  629. matrix[1 * 3 + 2] = shader_params[10];
  630. matrix[2 * 3 + 0] = shader_params[12];
  631. matrix[2 * 3 + 1] = shader_params[13];
  632. matrix[2 * 3 + 2] = shader_params[14];
  633. data->glUniformMatrix3fv(program->uniform_locations[GLES2_UNIFORM_MATRIX], 1, GL_FALSE, matrix);
  634. }
  635. program->shader_params = shader_params;
  636. }
  637. // Set the current program
  638. data->drawstate.program = program;
  639. // Clean up and return
  640. return true;
  641. fault:
  642. data->drawstate.program = NULL;
  643. return false;
  644. }
  645. static bool GLES2_QueueNoOp(SDL_Renderer *renderer, SDL_RenderCommand *cmd)
  646. {
  647. return true; // nothing to do in this backend.
  648. }
  649. static bool GLES2_QueueDrawPoints(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
  650. {
  651. const bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
  652. SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
  653. int i;
  654. SDL_FColor color = cmd->data.draw.color;
  655. const float color_scale = cmd->data.draw.color_scale;
  656. if (!verts) {
  657. return false;
  658. }
  659. color.r *= color_scale;
  660. color.g *= color_scale;
  661. color.b *= color_scale;
  662. if (colorswap) {
  663. float r = color.r;
  664. color.r = color.b;
  665. color.b = r;
  666. }
  667. cmd->data.draw.count = count;
  668. for (i = 0; i < count; i++) {
  669. verts->position.x = 0.5f + points[i].x;
  670. verts->position.y = 0.5f + points[i].y;
  671. verts->color = color;
  672. verts++;
  673. }
  674. return true;
  675. }
  676. static bool GLES2_QueueDrawLines(SDL_Renderer *renderer, SDL_RenderCommand *cmd, const SDL_FPoint *points, int count)
  677. {
  678. const bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
  679. int i;
  680. GLfloat prevx, prevy;
  681. SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
  682. SDL_FColor color = cmd->data.draw.color;
  683. const float color_scale = cmd->data.draw.color_scale;
  684. if (!verts) {
  685. return false;
  686. }
  687. color.r *= color_scale;
  688. color.g *= color_scale;
  689. color.b *= color_scale;
  690. if (colorswap) {
  691. float r = color.r;
  692. color.r = color.b;
  693. color.b = r;
  694. }
  695. cmd->data.draw.count = count;
  696. // 0.5f offset to hit the center of the pixel.
  697. prevx = 0.5f + points->x;
  698. prevy = 0.5f + points->y;
  699. verts->position.x = prevx;
  700. verts->position.y = prevy;
  701. verts->color = color;
  702. verts++;
  703. /* bump the end of each line segment out a quarter of a pixel, to provoke
  704. the diamond-exit rule. Without this, you won't just drop the last
  705. pixel of the last line segment, but you might also drop pixels at the
  706. edge of any given line segment along the way too. */
  707. for (i = 1; i < count; i++) {
  708. const GLfloat xstart = prevx;
  709. const GLfloat ystart = prevy;
  710. const GLfloat xend = points[i].x + 0.5f; // 0.5f to hit pixel center.
  711. const GLfloat yend = points[i].y + 0.5f;
  712. // bump a little in the direction we are moving in.
  713. const GLfloat deltax = xend - xstart;
  714. const GLfloat deltay = yend - ystart;
  715. const GLfloat angle = SDL_atan2f(deltay, deltax);
  716. prevx = xend + (SDL_cosf(angle) * 0.25f);
  717. prevy = yend + (SDL_sinf(angle) * 0.25f);
  718. verts->position.x = prevx;
  719. verts->position.y = prevy;
  720. verts->color = color;
  721. verts++;
  722. }
  723. return true;
  724. }
  725. static bool GLES2_QueueGeometry(SDL_Renderer *renderer, SDL_RenderCommand *cmd, SDL_Texture *texture,
  726. const float *xy, int xy_stride, const SDL_FColor *color, int color_stride, const float *uv, int uv_stride,
  727. int num_vertices, const void *indices, int num_indices, int size_indices,
  728. float scale_x, float scale_y)
  729. {
  730. int i;
  731. const bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
  732. int count = indices ? num_indices : num_vertices;
  733. const float color_scale = cmd->data.draw.color_scale;
  734. cmd->data.draw.count = count;
  735. size_indices = indices ? size_indices : 0;
  736. if (texture) {
  737. SDL_Vertex *verts = (SDL_Vertex *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
  738. if (!verts) {
  739. return false;
  740. }
  741. for (i = 0; i < count; i++) {
  742. int j;
  743. float *xy_;
  744. SDL_FColor col_;
  745. float *uv_;
  746. if (size_indices == 4) {
  747. j = ((const Uint32 *)indices)[i];
  748. } else if (size_indices == 2) {
  749. j = ((const Uint16 *)indices)[i];
  750. } else if (size_indices == 1) {
  751. j = ((const Uint8 *)indices)[i];
  752. } else {
  753. j = i;
  754. }
  755. xy_ = (float *)((char *)xy + j * xy_stride);
  756. col_ = *(SDL_FColor *)((char *)color + j * color_stride);
  757. uv_ = (float *)((char *)uv + j * uv_stride);
  758. verts->position.x = xy_[0] * scale_x;
  759. verts->position.y = xy_[1] * scale_y;
  760. col_.r *= color_scale;
  761. col_.g *= color_scale;
  762. col_.b *= color_scale;
  763. if (colorswap) {
  764. float r = col_.r;
  765. col_.r = col_.b;
  766. col_.b = r;
  767. }
  768. verts->color = col_;
  769. verts->tex_coord.x = uv_[0];
  770. verts->tex_coord.y = uv_[1];
  771. verts++;
  772. }
  773. } else {
  774. SDL_VertexSolid *verts = (SDL_VertexSolid *)SDL_AllocateRenderVertices(renderer, count * sizeof(*verts), 0, &cmd->data.draw.first);
  775. if (!verts) {
  776. return false;
  777. }
  778. for (i = 0; i < count; i++) {
  779. int j;
  780. float *xy_;
  781. SDL_FColor col_;
  782. if (size_indices == 4) {
  783. j = ((const Uint32 *)indices)[i];
  784. } else if (size_indices == 2) {
  785. j = ((const Uint16 *)indices)[i];
  786. } else if (size_indices == 1) {
  787. j = ((const Uint8 *)indices)[i];
  788. } else {
  789. j = i;
  790. }
  791. xy_ = (float *)((char *)xy + j * xy_stride);
  792. col_ = *(SDL_FColor *)((char *)color + j * color_stride);
  793. verts->position.x = xy_[0] * scale_x;
  794. verts->position.y = xy_[1] * scale_y;
  795. col_.r *= color_scale;
  796. col_.g *= color_scale;
  797. col_.b *= color_scale;
  798. if (colorswap) {
  799. float r = col_.r;
  800. col_.r = col_.b;
  801. col_.b = r;
  802. }
  803. verts->color = col_;
  804. verts++;
  805. }
  806. }
  807. return true;
  808. }
  809. static bool SetDrawState(GLES2_RenderData *data, const SDL_RenderCommand *cmd, const GLES2_ImageSource imgsrc, void *vertices)
  810. {
  811. SDL_Texture *texture = cmd->data.draw.texture;
  812. const SDL_BlendMode blend = cmd->data.draw.blend;
  813. GLES2_ProgramCacheEntry *program;
  814. int stride;
  815. SDL_assert((texture != NULL) == (imgsrc != GLES2_IMAGESOURCE_SOLID));
  816. if (data->drawstate.viewport_dirty) {
  817. const SDL_Rect *viewport = &data->drawstate.viewport;
  818. data->glViewport(viewport->x,
  819. data->drawstate.target ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h),
  820. viewport->w, viewport->h);
  821. if (viewport->w && viewport->h) {
  822. data->drawstate.projection[0][0] = 2.0f / viewport->w;
  823. data->drawstate.projection[1][1] = (data->drawstate.target ? 2.0f : -2.0f) / viewport->h;
  824. data->drawstate.projection[3][1] = data->drawstate.target ? -1.0f : 1.0f;
  825. }
  826. data->drawstate.viewport_dirty = false;
  827. }
  828. if (data->drawstate.cliprect_enabled_dirty) {
  829. if (!data->drawstate.cliprect_enabled) {
  830. data->glDisable(GL_SCISSOR_TEST);
  831. } else {
  832. data->glEnable(GL_SCISSOR_TEST);
  833. }
  834. data->drawstate.cliprect_enabled_dirty = false;
  835. }
  836. if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) {
  837. const SDL_Rect *viewport = &data->drawstate.viewport;
  838. const SDL_Rect *rect = &data->drawstate.cliprect;
  839. data->glScissor(viewport->x + rect->x,
  840. data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h,
  841. rect->w, rect->h);
  842. data->drawstate.cliprect_dirty = false;
  843. }
  844. if (data->drawstate.texturing_dirty || ((texture != NULL) != data->drawstate.texturing)) {
  845. if (!texture) {
  846. data->glDisableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD);
  847. data->drawstate.texturing = false;
  848. } else {
  849. data->glEnableVertexAttribArray((GLenum)GLES2_ATTRIBUTE_TEXCOORD);
  850. data->drawstate.texturing = true;
  851. }
  852. data->drawstate.texturing_dirty = false;
  853. }
  854. if (texture) {
  855. stride = sizeof(SDL_Vertex);
  856. } else {
  857. stride = sizeof(SDL_VertexSolid);
  858. }
  859. if (texture) {
  860. SDL_Vertex *verts = (SDL_Vertex *)(((Uint8 *)vertices) + cmd->data.draw.first);
  861. data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->tex_coord);
  862. }
  863. if (!GLES2_SelectProgram(data, imgsrc, texture ? texture->colorspace : SDL_COLORSPACE_SRGB)) {
  864. return false;
  865. }
  866. program = data->drawstate.program;
  867. if (program->uniform_locations[GLES2_UNIFORM_PROJECTION] != -1) {
  868. if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof(data->drawstate.projection)) != 0) {
  869. data->glUniformMatrix4fv(program->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection);
  870. SDL_memcpy(program->projection, data->drawstate.projection, sizeof(data->drawstate.projection));
  871. }
  872. }
  873. if (blend != data->drawstate.blend) {
  874. if (blend == SDL_BLENDMODE_NONE) {
  875. data->glDisable(GL_BLEND);
  876. } else {
  877. data->glEnable(GL_BLEND);
  878. data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)),
  879. GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)),
  880. GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)),
  881. GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend)));
  882. data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)),
  883. GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend)));
  884. }
  885. data->drawstate.blend = blend;
  886. }
  887. // all drawing commands use this
  888. {
  889. SDL_VertexSolid *verts = (SDL_VertexSolid *)(((Uint8 *)vertices) + cmd->data.draw.first);
  890. data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, stride, (const GLvoid *)&verts->position);
  891. data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_FLOAT, GL_TRUE /* Normalized */, stride, (const GLvoid *)&verts->color);
  892. }
  893. return true;
  894. }
  895. static bool SetTextureAddressMode(GLES2_RenderData *data, GLenum textype, SDL_TextureAddressMode addressMode)
  896. {
  897. switch (addressMode) {
  898. case SDL_TEXTURE_ADDRESS_CLAMP:
  899. data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  900. data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  901. break;
  902. case SDL_TEXTURE_ADDRESS_WRAP:
  903. data->glTexParameteri(textype, GL_TEXTURE_WRAP_S, GL_REPEAT);
  904. data->glTexParameteri(textype, GL_TEXTURE_WRAP_T, GL_REPEAT);
  905. break;
  906. default:
  907. return SDL_SetError("Unknown texture address mode: %d", addressMode);
  908. }
  909. return true;
  910. }
  911. static bool SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd, void *vertices)
  912. {
  913. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  914. GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  915. SDL_Texture *texture = cmd->data.draw.texture;
  916. int ret;
  917. // Pick an appropriate shader
  918. if (renderer->target) {
  919. // Check if we need to do color mapping between the source and render target textures
  920. if (renderer->target->format != texture->format) {
  921. switch (texture->format) {
  922. case SDL_PIXELFORMAT_BGRA32:
  923. switch (renderer->target->format) {
  924. case SDL_PIXELFORMAT_RGBA32:
  925. case SDL_PIXELFORMAT_RGBX32:
  926. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  927. break;
  928. case SDL_PIXELFORMAT_BGRX32:
  929. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  930. break;
  931. default:
  932. break;
  933. }
  934. break;
  935. case SDL_PIXELFORMAT_RGBA32:
  936. switch (renderer->target->format) {
  937. case SDL_PIXELFORMAT_BGRA32:
  938. case SDL_PIXELFORMAT_BGRX32:
  939. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  940. break;
  941. case SDL_PIXELFORMAT_RGBX32:
  942. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  943. break;
  944. default:
  945. break;
  946. }
  947. break;
  948. case SDL_PIXELFORMAT_BGRX32:
  949. switch (renderer->target->format) {
  950. case SDL_PIXELFORMAT_RGBA32:
  951. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  952. break;
  953. case SDL_PIXELFORMAT_BGRA32:
  954. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  955. break;
  956. case SDL_PIXELFORMAT_RGBX32:
  957. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  958. break;
  959. default:
  960. break;
  961. }
  962. break;
  963. case SDL_PIXELFORMAT_RGBX32:
  964. switch (renderer->target->format) {
  965. case SDL_PIXELFORMAT_RGBA32:
  966. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  967. break;
  968. case SDL_PIXELFORMAT_BGRA32:
  969. sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  970. break;
  971. case SDL_PIXELFORMAT_BGRX32:
  972. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  973. break;
  974. default:
  975. break;
  976. }
  977. break;
  978. #ifdef SDL_HAVE_YUV
  979. case SDL_PIXELFORMAT_IYUV:
  980. case SDL_PIXELFORMAT_YV12:
  981. sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  982. break;
  983. case SDL_PIXELFORMAT_NV12:
  984. sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
  985. break;
  986. case SDL_PIXELFORMAT_NV21:
  987. sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
  988. break;
  989. #endif
  990. case SDL_PIXELFORMAT_EXTERNAL_OES:
  991. sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
  992. break;
  993. default:
  994. return SDL_SetError("Unsupported texture format");
  995. }
  996. } else {
  997. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; // Texture formats match, use the non color mapping shader (even if the formats are not ABGR)
  998. }
  999. } else {
  1000. switch (texture->format) {
  1001. case SDL_PIXELFORMAT_BGRA32:
  1002. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1003. break;
  1004. case SDL_PIXELFORMAT_RGBA32:
  1005. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1006. break;
  1007. case SDL_PIXELFORMAT_BGRX32:
  1008. sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1009. break;
  1010. case SDL_PIXELFORMAT_RGBX32:
  1011. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1012. break;
  1013. #ifdef SDL_HAVE_YUV
  1014. case SDL_PIXELFORMAT_IYUV:
  1015. case SDL_PIXELFORMAT_YV12:
  1016. sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  1017. break;
  1018. case SDL_PIXELFORMAT_NV12:
  1019. sourceType = GLES2_IMAGESOURCE_TEXTURE_NV12;
  1020. break;
  1021. case SDL_PIXELFORMAT_NV21:
  1022. sourceType = GLES2_IMAGESOURCE_TEXTURE_NV21;
  1023. break;
  1024. #endif
  1025. case SDL_PIXELFORMAT_EXTERNAL_OES:
  1026. sourceType = GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES;
  1027. break;
  1028. default:
  1029. return SDL_SetError("Unsupported texture format");
  1030. }
  1031. }
  1032. ret = SetDrawState(data, cmd, sourceType, vertices);
  1033. if (texture != data->drawstate.texture) {
  1034. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1035. #ifdef SDL_HAVE_YUV
  1036. if (tdata->yuv) {
  1037. data->glActiveTexture(GL_TEXTURE2);
  1038. data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1039. if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
  1040. return false;
  1041. }
  1042. data->glActiveTexture(GL_TEXTURE1);
  1043. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1044. if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
  1045. return false;
  1046. }
  1047. data->glActiveTexture(GL_TEXTURE0);
  1048. } else if (tdata->nv12) {
  1049. data->glActiveTexture(GL_TEXTURE1);
  1050. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1051. if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
  1052. return false;
  1053. }
  1054. data->glActiveTexture(GL_TEXTURE0);
  1055. }
  1056. #endif
  1057. data->glBindTexture(tdata->texture_type, tdata->texture);
  1058. if (!SetTextureAddressMode(data, tdata->texture_type, cmd->data.draw.texture_address_mode)) {
  1059. return false;
  1060. }
  1061. data->drawstate.texture = texture;
  1062. }
  1063. return ret;
  1064. }
  1065. static void GLES2_InvalidateCachedState(SDL_Renderer *renderer)
  1066. {
  1067. GLES2_DrawStateCache *cache = &((GLES2_RenderData *)renderer->internal)->drawstate;
  1068. cache->viewport_dirty = true;
  1069. cache->texture = NULL;
  1070. cache->blend = SDL_BLENDMODE_INVALID;
  1071. cache->cliprect_enabled_dirty = true;
  1072. cache->cliprect_dirty = true;
  1073. cache->texturing_dirty = true;
  1074. cache->clear_color_dirty = true;
  1075. cache->drawablew = 0;
  1076. cache->drawableh = 0;
  1077. cache->program = NULL;
  1078. }
  1079. static bool GLES2_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
  1080. {
  1081. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1082. const bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_BGRA32 || renderer->target->format == SDL_PIXELFORMAT_BGRX32));
  1083. #if USE_VERTEX_BUFFER_OBJECTS
  1084. const int vboidx = data->current_vertex_buffer;
  1085. const GLuint vbo = data->vertex_buffers[vboidx];
  1086. #endif
  1087. if (!GLES2_ActivateRenderer(renderer)) {
  1088. return false;
  1089. }
  1090. data->drawstate.target = renderer->target;
  1091. if (!data->drawstate.target) {
  1092. int w, h;
  1093. SDL_GetWindowSizeInPixels(renderer->window, &w, &h);
  1094. if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
  1095. data->drawstate.viewport_dirty = true; // if the window dimensions changed, invalidate the current viewport, etc.
  1096. data->drawstate.cliprect_dirty = true;
  1097. data->drawstate.drawablew = w;
  1098. data->drawstate.drawableh = h;
  1099. }
  1100. }
  1101. #if USE_VERTEX_BUFFER_OBJECTS
  1102. // upload the new VBO data for this set of commands.
  1103. data->glBindBuffer(GL_ARRAY_BUFFER, vbo);
  1104. if (data->vertex_buffer_size[vboidx] < vertsize) {
  1105. data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_STREAM_DRAW);
  1106. data->vertex_buffer_size[vboidx] = vertsize;
  1107. } else {
  1108. data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices);
  1109. }
  1110. // cycle through a few VBOs so the GL has some time with the data before we replace it.
  1111. data->current_vertex_buffer++;
  1112. if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) {
  1113. data->current_vertex_buffer = 0;
  1114. }
  1115. vertices = NULL; // attrib pointers will be offsets into the VBO.
  1116. #endif
  1117. while (cmd) {
  1118. switch (cmd->command) {
  1119. case SDL_RENDERCMD_SETDRAWCOLOR:
  1120. {
  1121. break;
  1122. }
  1123. case SDL_RENDERCMD_SETVIEWPORT:
  1124. {
  1125. SDL_Rect *viewport = &data->drawstate.viewport;
  1126. if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
  1127. SDL_copyp(viewport, &cmd->data.viewport.rect);
  1128. data->drawstate.viewport_dirty = true;
  1129. data->drawstate.cliprect_dirty = true;
  1130. }
  1131. break;
  1132. }
  1133. case SDL_RENDERCMD_SETCLIPRECT:
  1134. {
  1135. const SDL_Rect *rect = &cmd->data.cliprect.rect;
  1136. if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
  1137. data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
  1138. data->drawstate.cliprect_enabled_dirty = true;
  1139. }
  1140. if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {
  1141. SDL_copyp(&data->drawstate.cliprect, rect);
  1142. data->drawstate.cliprect_dirty = true;
  1143. }
  1144. break;
  1145. }
  1146. case SDL_RENDERCMD_CLEAR:
  1147. {
  1148. const float r = (colorswap ? cmd->data.color.color.b : cmd->data.color.color.r) * cmd->data.color.color_scale;
  1149. const float g = cmd->data.color.color.g * cmd->data.color.color_scale;
  1150. const float b = (colorswap ? cmd->data.color.color.r : cmd->data.color.color.b) * cmd->data.color.color_scale;
  1151. const float a = cmd->data.color.color.a;
  1152. if (data->drawstate.clear_color_dirty ||
  1153. (r != data->drawstate.clear_color.r) ||
  1154. (g != data->drawstate.clear_color.g) ||
  1155. (b != data->drawstate.clear_color.b) ||
  1156. (a != data->drawstate.clear_color.a)) {
  1157. data->glClearColor(r, g, b, a);
  1158. data->drawstate.clear_color.r = r;
  1159. data->drawstate.clear_color.g = g;
  1160. data->drawstate.clear_color.b = b;
  1161. data->drawstate.clear_color.a = a;
  1162. data->drawstate.clear_color_dirty = false;
  1163. }
  1164. if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) {
  1165. data->glDisable(GL_SCISSOR_TEST);
  1166. data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled;
  1167. }
  1168. data->glClear(GL_COLOR_BUFFER_BIT);
  1169. break;
  1170. }
  1171. case SDL_RENDERCMD_FILL_RECTS: // unused
  1172. break;
  1173. case SDL_RENDERCMD_COPY: // unused
  1174. break;
  1175. case SDL_RENDERCMD_COPY_EX: // unused
  1176. break;
  1177. case SDL_RENDERCMD_DRAW_LINES:
  1178. {
  1179. if (SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID, vertices)) {
  1180. size_t count = cmd->data.draw.count;
  1181. if (count > 2) {
  1182. // joined lines cannot be grouped
  1183. data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)count);
  1184. } else {
  1185. // let's group non joined lines
  1186. SDL_RenderCommand *finalcmd = cmd;
  1187. SDL_RenderCommand *nextcmd = cmd->next;
  1188. SDL_BlendMode thisblend = cmd->data.draw.blend;
  1189. while (nextcmd) {
  1190. const SDL_RenderCommandType nextcmdtype = nextcmd->command;
  1191. if (nextcmdtype != SDL_RENDERCMD_DRAW_LINES) {
  1192. break; // can't go any further on this draw call, different render command up next.
  1193. } else if (nextcmd->data.draw.count != 2) {
  1194. break; // can't go any further on this draw call, those are joined lines
  1195. } else if (nextcmd->data.draw.blend != thisblend) {
  1196. break; // can't go any further on this draw call, different blendmode copy up next.
  1197. } else {
  1198. finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
  1199. count += nextcmd->data.draw.count;
  1200. }
  1201. nextcmd = nextcmd->next;
  1202. }
  1203. data->glDrawArrays(GL_LINES, 0, (GLsizei)count);
  1204. cmd = finalcmd; // skip any copy commands we just combined in here.
  1205. }
  1206. }
  1207. break;
  1208. }
  1209. case SDL_RENDERCMD_DRAW_POINTS:
  1210. case SDL_RENDERCMD_GEOMETRY:
  1211. {
  1212. /* as long as we have the same copy command in a row, with the
  1213. same texture, we can combine them all into a single draw call. */
  1214. SDL_Texture *thistexture = cmd->data.draw.texture;
  1215. SDL_BlendMode thisblend = cmd->data.draw.blend;
  1216. const SDL_RenderCommandType thiscmdtype = cmd->command;
  1217. SDL_RenderCommand *finalcmd = cmd;
  1218. SDL_RenderCommand *nextcmd = cmd->next;
  1219. size_t count = cmd->data.draw.count;
  1220. int ret;
  1221. while (nextcmd) {
  1222. const SDL_RenderCommandType nextcmdtype = nextcmd->command;
  1223. if (nextcmdtype != thiscmdtype) {
  1224. break; // can't go any further on this draw call, different render command up next.
  1225. } else if (nextcmd->data.draw.texture != thistexture || nextcmd->data.draw.blend != thisblend) {
  1226. break; // can't go any further on this draw call, different texture/blendmode copy up next.
  1227. } else {
  1228. finalcmd = nextcmd; // we can combine copy operations here. Mark this one as the furthest okay command.
  1229. count += nextcmd->data.draw.count;
  1230. }
  1231. nextcmd = nextcmd->next;
  1232. }
  1233. if (thistexture) {
  1234. ret = SetCopyState(renderer, cmd, vertices);
  1235. } else {
  1236. ret = SetDrawState(data, cmd, GLES2_IMAGESOURCE_SOLID, vertices);
  1237. }
  1238. if (ret) {
  1239. int op = GL_TRIANGLES; // SDL_RENDERCMD_GEOMETRY
  1240. if (thiscmdtype == SDL_RENDERCMD_DRAW_POINTS) {
  1241. op = GL_POINTS;
  1242. }
  1243. data->glDrawArrays(op, 0, (GLsizei)count);
  1244. }
  1245. cmd = finalcmd; // skip any copy commands we just combined in here.
  1246. break;
  1247. }
  1248. case SDL_RENDERCMD_NO_OP:
  1249. break;
  1250. }
  1251. cmd = cmd->next;
  1252. }
  1253. return GL_CheckError("", renderer);
  1254. }
  1255. static void GLES2_DestroyRenderer(SDL_Renderer *renderer)
  1256. {
  1257. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1258. // Deallocate everything
  1259. if (data) {
  1260. GLES2_ActivateRenderer(renderer);
  1261. {
  1262. int i;
  1263. for (i = 0; i < GLES2_SHADER_COUNT; i++) {
  1264. GLuint id = data->shader_id_cache[i];
  1265. if (id) {
  1266. data->glDeleteShader(id);
  1267. }
  1268. }
  1269. }
  1270. {
  1271. GLES2_ProgramCacheEntry *entry;
  1272. GLES2_ProgramCacheEntry *next;
  1273. entry = data->program_cache.head;
  1274. while (entry) {
  1275. data->glDeleteProgram(entry->id);
  1276. next = entry->next;
  1277. SDL_free(entry);
  1278. entry = next;
  1279. }
  1280. }
  1281. if (data->context) {
  1282. while (data->framebuffers) {
  1283. GLES2_FBOList *nextnode = data->framebuffers->next;
  1284. data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
  1285. GL_CheckError("", renderer);
  1286. SDL_free(data->framebuffers);
  1287. data->framebuffers = nextnode;
  1288. }
  1289. #if USE_VERTEX_BUFFER_OBJECTS
  1290. data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
  1291. GL_CheckError("", renderer);
  1292. #endif
  1293. SDL_GL_DestroyContext(data->context);
  1294. }
  1295. SDL_free(data);
  1296. }
  1297. }
  1298. static bool GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props)
  1299. {
  1300. GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->internal;
  1301. GLES2_TextureData *data;
  1302. GLenum format;
  1303. GLenum type;
  1304. GLenum scaleMode;
  1305. GLES2_ActivateRenderer(renderer);
  1306. renderdata->drawstate.texture = NULL; // we trash this state.
  1307. // Determine the corresponding GLES texture format params
  1308. switch (texture->format) {
  1309. case SDL_PIXELFORMAT_BGRA32:
  1310. case SDL_PIXELFORMAT_RGBA32:
  1311. case SDL_PIXELFORMAT_BGRX32:
  1312. case SDL_PIXELFORMAT_RGBX32:
  1313. format = GL_RGBA;
  1314. type = GL_UNSIGNED_BYTE;
  1315. break;
  1316. #ifdef SDL_HAVE_YUV
  1317. case SDL_PIXELFORMAT_IYUV:
  1318. case SDL_PIXELFORMAT_YV12:
  1319. case SDL_PIXELFORMAT_NV12:
  1320. case SDL_PIXELFORMAT_NV21:
  1321. format = GL_LUMINANCE;
  1322. type = GL_UNSIGNED_BYTE;
  1323. break;
  1324. #endif
  1325. #ifdef GL_TEXTURE_EXTERNAL_OES
  1326. case SDL_PIXELFORMAT_EXTERNAL_OES:
  1327. format = GL_NONE;
  1328. type = GL_NONE;
  1329. break;
  1330. #endif
  1331. default:
  1332. return SDL_SetError("Texture format not supported");
  1333. }
  1334. if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES &&
  1335. texture->access != SDL_TEXTUREACCESS_STATIC) {
  1336. return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES");
  1337. }
  1338. // Allocate a texture struct
  1339. data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
  1340. if (!data) {
  1341. return false;
  1342. }
  1343. data->texture = 0;
  1344. #ifdef GL_TEXTURE_EXTERNAL_OES
  1345. data->texture_type = (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES) ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
  1346. #else
  1347. data->texture_type = GL_TEXTURE_2D;
  1348. #endif
  1349. data->pixel_format = format;
  1350. data->pixel_type = type;
  1351. #ifdef SDL_HAVE_YUV
  1352. data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
  1353. data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21));
  1354. data->texture_u = 0;
  1355. data->texture_v = 0;
  1356. #endif
  1357. scaleMode = (texture->scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
  1358. // Allocate a blob for image renderdata
  1359. if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  1360. size_t size;
  1361. data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
  1362. size = (size_t)texture->h * data->pitch;
  1363. #ifdef SDL_HAVE_YUV
  1364. if (data->yuv) {
  1365. // Need to add size for the U and V planes
  1366. size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
  1367. } else if (data->nv12) {
  1368. // Need to add size for the U/V plane
  1369. size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2);
  1370. }
  1371. #endif
  1372. data->pixel_data = SDL_calloc(1, size);
  1373. if (!data->pixel_data) {
  1374. SDL_free(data);
  1375. return false;
  1376. }
  1377. }
  1378. // Allocate the texture
  1379. GL_CheckError("", renderer);
  1380. #ifdef SDL_HAVE_YUV
  1381. if (data->yuv) {
  1382. data->texture_v = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER, 0);
  1383. if (data->texture_v) {
  1384. data->texture_v_external = true;
  1385. } else {
  1386. renderdata->glGenTextures(1, &data->texture_v);
  1387. if (!GL_CheckError("glGenTexures()", renderer)) {
  1388. return false;
  1389. }
  1390. }
  1391. renderdata->glActiveTexture(GL_TEXTURE2);
  1392. renderdata->glBindTexture(data->texture_type, data->texture_v);
  1393. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1394. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1395. renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
  1396. SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER, data->texture_v);
  1397. data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER, 0);
  1398. if (data->texture_u) {
  1399. data->texture_u_external = true;
  1400. } else {
  1401. renderdata->glGenTextures(1, &data->texture_u);
  1402. if (!GL_CheckError("glGenTexures()", renderer)) {
  1403. return false;
  1404. }
  1405. }
  1406. renderdata->glActiveTexture(GL_TEXTURE1);
  1407. renderdata->glBindTexture(data->texture_type, data->texture_u);
  1408. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1409. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1410. renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL);
  1411. if (!GL_CheckError("glTexImage2D()", renderer)) {
  1412. return false;
  1413. }
  1414. SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER, data->texture_u);
  1415. if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
  1416. return SDL_SetError("Unsupported YUV colorspace");
  1417. }
  1418. } else if (data->nv12) {
  1419. data->texture_u = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER, 0);
  1420. if (data->texture_u) {
  1421. data->texture_u_external = true;
  1422. } else {
  1423. renderdata->glGenTextures(1, &data->texture_u);
  1424. if (!GL_CheckError("glGenTexures()", renderer)) {
  1425. return false;
  1426. }
  1427. }
  1428. renderdata->glActiveTexture(GL_TEXTURE1);
  1429. renderdata->glBindTexture(data->texture_type, data->texture_u);
  1430. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1431. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1432. 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);
  1433. if (!GL_CheckError("glTexImage2D()", renderer)) {
  1434. return false;
  1435. }
  1436. SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER, data->texture_u);
  1437. if (!SDL_GetYCbCRtoRGBConversionMatrix(texture->colorspace, texture->w, texture->h, 8)) {
  1438. return SDL_SetError("Unsupported YUV colorspace");
  1439. }
  1440. }
  1441. #endif
  1442. data->texture = (GLuint)SDL_GetNumberProperty(create_props, SDL_PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER, 0);
  1443. if (data->texture) {
  1444. data->texture_external = true;
  1445. } else {
  1446. renderdata->glGenTextures(1, &data->texture);
  1447. if (!GL_CheckError("glGenTexures()", renderer)) {
  1448. return false;
  1449. }
  1450. }
  1451. texture->internal = data;
  1452. renderdata->glActiveTexture(GL_TEXTURE0);
  1453. renderdata->glBindTexture(data->texture_type, data->texture);
  1454. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  1455. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  1456. if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) {
  1457. renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
  1458. if (!GL_CheckError("glTexImage2D()", renderer)) {
  1459. return false;
  1460. }
  1461. }
  1462. SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER, data->texture);
  1463. SDL_SetNumberProperty(SDL_GetTextureProperties(texture), SDL_PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER, data->texture_type);
  1464. if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  1465. data->fbo = GLES2_GetFBO((GLES2_RenderData *)renderer->internal, texture->w, texture->h);
  1466. } else {
  1467. data->fbo = NULL;
  1468. }
  1469. return GL_CheckError("", renderer);
  1470. }
  1471. static bool GLES2_TexSubImage2D(GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp)
  1472. {
  1473. Uint8 *blob = NULL;
  1474. Uint8 *src;
  1475. size_t src_pitch;
  1476. int y;
  1477. if ((width == 0) || (height == 0) || (bpp == 0)) {
  1478. return true; // nothing to do
  1479. }
  1480. // Reformat the texture data into a tightly packed array
  1481. src_pitch = (size_t)width * bpp;
  1482. src = (Uint8 *)pixels;
  1483. if ((size_t)pitch != src_pitch) {
  1484. blob = (Uint8 *)SDL_malloc(src_pitch * height);
  1485. if (!blob) {
  1486. return false;
  1487. }
  1488. src = blob;
  1489. for (y = 0; y < height; ++y) {
  1490. SDL_memcpy(src, pixels, src_pitch);
  1491. src += src_pitch;
  1492. pixels = (Uint8 *)pixels + pitch;
  1493. }
  1494. src = blob;
  1495. }
  1496. data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
  1497. if (blob) {
  1498. SDL_free(blob);
  1499. }
  1500. return true;
  1501. }
  1502. static bool GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  1503. const void *pixels, int pitch)
  1504. {
  1505. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1506. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1507. GLES2_ActivateRenderer(renderer);
  1508. // Bail out if we're supposed to update an empty rectangle
  1509. if (rect->w <= 0 || rect->h <= 0) {
  1510. return true;
  1511. }
  1512. data->drawstate.texture = NULL; // we trash this state.
  1513. // Create a texture subimage with the supplied data
  1514. data->glBindTexture(tdata->texture_type, tdata->texture);
  1515. GLES2_TexSubImage2D(data, tdata->texture_type,
  1516. rect->x,
  1517. rect->y,
  1518. rect->w,
  1519. rect->h,
  1520. tdata->pixel_format,
  1521. tdata->pixel_type,
  1522. pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
  1523. #ifdef SDL_HAVE_YUV
  1524. if (tdata->yuv) {
  1525. // Skip to the correct offset into the next texture
  1526. pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
  1527. if (texture->format == SDL_PIXELFORMAT_YV12) {
  1528. data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1529. } else {
  1530. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1531. }
  1532. GLES2_TexSubImage2D(data, tdata->texture_type,
  1533. rect->x / 2,
  1534. rect->y / 2,
  1535. (rect->w + 1) / 2,
  1536. (rect->h + 1) / 2,
  1537. tdata->pixel_format,
  1538. tdata->pixel_type,
  1539. pixels, (pitch + 1) / 2, 1);
  1540. // Skip to the correct offset into the next texture
  1541. pixels = (const void *)((const Uint8 *)pixels + ((rect->h + 1) / 2) * ((pitch + 1) / 2));
  1542. if (texture->format == SDL_PIXELFORMAT_YV12) {
  1543. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1544. } else {
  1545. data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1546. }
  1547. GLES2_TexSubImage2D(data, tdata->texture_type,
  1548. rect->x / 2,
  1549. rect->y / 2,
  1550. (rect->w + 1) / 2,
  1551. (rect->h + 1) / 2,
  1552. tdata->pixel_format,
  1553. tdata->pixel_type,
  1554. pixels, (pitch + 1) / 2, 1);
  1555. } else if (tdata->nv12) {
  1556. // Skip to the correct offset into the next texture
  1557. pixels = (const void *)((const Uint8 *)pixels + rect->h * pitch);
  1558. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1559. GLES2_TexSubImage2D(data, tdata->texture_type,
  1560. rect->x / 2,
  1561. rect->y / 2,
  1562. (rect->w + 1) / 2,
  1563. (rect->h + 1) / 2,
  1564. GL_LUMINANCE_ALPHA,
  1565. GL_UNSIGNED_BYTE,
  1566. pixels, 2 * ((pitch + 1) / 2), 2);
  1567. }
  1568. #endif
  1569. return GL_CheckError("glTexSubImage2D()", renderer);
  1570. }
  1571. #ifdef SDL_HAVE_YUV
  1572. static bool GLES2_UpdateTextureYUV(SDL_Renderer *renderer, SDL_Texture *texture,
  1573. const SDL_Rect *rect,
  1574. const Uint8 *Yplane, int Ypitch,
  1575. const Uint8 *Uplane, int Upitch,
  1576. const Uint8 *Vplane, int Vpitch)
  1577. {
  1578. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1579. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1580. GLES2_ActivateRenderer(renderer);
  1581. // Bail out if we're supposed to update an empty rectangle
  1582. if (rect->w <= 0 || rect->h <= 0) {
  1583. return true;
  1584. }
  1585. data->drawstate.texture = NULL; // we trash this state.
  1586. data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1587. GLES2_TexSubImage2D(data, tdata->texture_type,
  1588. rect->x / 2,
  1589. rect->y / 2,
  1590. (rect->w + 1) / 2,
  1591. (rect->h + 1) / 2,
  1592. tdata->pixel_format,
  1593. tdata->pixel_type,
  1594. Vplane, Vpitch, 1);
  1595. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1596. GLES2_TexSubImage2D(data, tdata->texture_type,
  1597. rect->x / 2,
  1598. rect->y / 2,
  1599. (rect->w + 1) / 2,
  1600. (rect->h + 1) / 2,
  1601. tdata->pixel_format,
  1602. tdata->pixel_type,
  1603. Uplane, Upitch, 1);
  1604. data->glBindTexture(tdata->texture_type, tdata->texture);
  1605. GLES2_TexSubImage2D(data, tdata->texture_type,
  1606. rect->x,
  1607. rect->y,
  1608. rect->w,
  1609. rect->h,
  1610. tdata->pixel_format,
  1611. tdata->pixel_type,
  1612. Yplane, Ypitch, 1);
  1613. return GL_CheckError("glTexSubImage2D()", renderer);
  1614. }
  1615. static bool GLES2_UpdateTextureNV(SDL_Renderer *renderer, SDL_Texture *texture,
  1616. const SDL_Rect *rect,
  1617. const Uint8 *Yplane, int Ypitch,
  1618. const Uint8 *UVplane, int UVpitch)
  1619. {
  1620. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1621. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1622. GLES2_ActivateRenderer(renderer);
  1623. // Bail out if we're supposed to update an empty rectangle
  1624. if (rect->w <= 0 || rect->h <= 0) {
  1625. return true;
  1626. }
  1627. data->drawstate.texture = NULL; // we trash this state.
  1628. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1629. GLES2_TexSubImage2D(data, tdata->texture_type,
  1630. rect->x / 2,
  1631. rect->y / 2,
  1632. (rect->w + 1) / 2,
  1633. (rect->h + 1) / 2,
  1634. GL_LUMINANCE_ALPHA,
  1635. GL_UNSIGNED_BYTE,
  1636. UVplane, UVpitch, 2);
  1637. data->glBindTexture(tdata->texture_type, tdata->texture);
  1638. GLES2_TexSubImage2D(data, tdata->texture_type,
  1639. rect->x,
  1640. rect->y,
  1641. rect->w,
  1642. rect->h,
  1643. tdata->pixel_format,
  1644. tdata->pixel_type,
  1645. Yplane, Ypitch, 1);
  1646. return GL_CheckError("glTexSubImage2D()", renderer);
  1647. }
  1648. #endif
  1649. static bool GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  1650. void **pixels, int *pitch)
  1651. {
  1652. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1653. // Retrieve the buffer/pitch for the specified region
  1654. *pixels = (Uint8 *)tdata->pixel_data +
  1655. (tdata->pitch * rect->y) +
  1656. (rect->x * SDL_BYTESPERPIXEL(texture->format));
  1657. *pitch = tdata->pitch;
  1658. return true;
  1659. }
  1660. static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  1661. {
  1662. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1663. SDL_Rect rect;
  1664. // We do whole texture updates, at least for now
  1665. rect.x = 0;
  1666. rect.y = 0;
  1667. rect.w = texture->w;
  1668. rect.h = texture->h;
  1669. GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
  1670. }
  1671. static void GLES2_SetTextureScaleMode(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ScaleMode scaleMode)
  1672. {
  1673. GLES2_RenderData *renderdata = (GLES2_RenderData *)renderer->internal;
  1674. GLES2_TextureData *data = (GLES2_TextureData *)texture->internal;
  1675. GLenum glScaleMode = (scaleMode == SDL_SCALEMODE_NEAREST) ? GL_NEAREST : GL_LINEAR;
  1676. #ifdef SDL_HAVE_YUV
  1677. if (data->yuv) {
  1678. renderdata->glActiveTexture(GL_TEXTURE2);
  1679. renderdata->glBindTexture(data->texture_type, data->texture_v);
  1680. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1681. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1682. renderdata->glActiveTexture(GL_TEXTURE1);
  1683. renderdata->glBindTexture(data->texture_type, data->texture_u);
  1684. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1685. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1686. } else if (data->nv12) {
  1687. renderdata->glActiveTexture(GL_TEXTURE1);
  1688. renderdata->glBindTexture(data->texture_type, data->texture_u);
  1689. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1690. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1691. }
  1692. #endif
  1693. renderdata->glActiveTexture(GL_TEXTURE0);
  1694. renderdata->glBindTexture(data->texture_type, data->texture);
  1695. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode);
  1696. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode);
  1697. }
  1698. static bool GLES2_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
  1699. {
  1700. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1701. GLES2_TextureData *texturedata = NULL;
  1702. GLenum status;
  1703. data->drawstate.viewport_dirty = true;
  1704. if (!texture) {
  1705. data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
  1706. } else {
  1707. texturedata = (GLES2_TextureData *)texture->internal;
  1708. data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
  1709. // TODO: check if texture pixel format allows this operation
  1710. data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
  1711. // Check FBO status
  1712. status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  1713. if (status != GL_FRAMEBUFFER_COMPLETE) {
  1714. return SDL_SetError("glFramebufferTexture2D() failed");
  1715. }
  1716. }
  1717. return true;
  1718. }
  1719. static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  1720. {
  1721. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1722. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->internal;
  1723. GLES2_ActivateRenderer(renderer);
  1724. if (data->drawstate.texture == texture) {
  1725. data->drawstate.texture = NULL;
  1726. }
  1727. if (data->drawstate.target == texture) {
  1728. data->drawstate.target = NULL;
  1729. }
  1730. // Destroy the texture
  1731. if (tdata) {
  1732. if (tdata->texture && !tdata->texture_external) {
  1733. data->glDeleteTextures(1, &tdata->texture);
  1734. }
  1735. #ifdef SDL_HAVE_YUV
  1736. if (tdata->texture_v && !tdata->texture_v_external) {
  1737. data->glDeleteTextures(1, &tdata->texture_v);
  1738. }
  1739. if (tdata->texture_u && !tdata->texture_u_external) {
  1740. data->glDeleteTextures(1, &tdata->texture_u);
  1741. }
  1742. #endif
  1743. SDL_free(tdata->pixel_data);
  1744. SDL_free(tdata);
  1745. texture->internal = NULL;
  1746. }
  1747. }
  1748. static SDL_Surface *GLES2_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect)
  1749. {
  1750. GLES2_RenderData *data = (GLES2_RenderData *)renderer->internal;
  1751. SDL_PixelFormat format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_RGBA32;
  1752. SDL_Surface *surface;
  1753. surface = SDL_CreateSurface(rect->w, rect->h, format);
  1754. if (!surface) {
  1755. return NULL;
  1756. }
  1757. int y = rect->y;
  1758. if (!renderer->target) {
  1759. int w, h;
  1760. SDL_GetRenderOutputSize(renderer, &w, &h);
  1761. y = (h - y) - rect->h;
  1762. }
  1763. data->glReadPixels(rect->x, y, rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
  1764. if (!GL_CheckError("glReadPixels()", renderer)) {
  1765. SDL_DestroySurface(surface);
  1766. return NULL;
  1767. }
  1768. // Flip the rows to be top-down if necessary
  1769. if (!renderer->target) {
  1770. SDL_FlipSurface(surface, SDL_FLIP_VERTICAL);
  1771. }
  1772. return surface;
  1773. }
  1774. static bool GLES2_RenderPresent(SDL_Renderer *renderer)
  1775. {
  1776. // Tell the video driver to swap buffers
  1777. return SDL_GL_SwapWindow(renderer->window);
  1778. }
  1779. static bool GLES2_SetVSync(SDL_Renderer *renderer, const int vsync)
  1780. {
  1781. int interval = 0;
  1782. if (!SDL_GL_SetSwapInterval(vsync)) {
  1783. return false;
  1784. }
  1785. if (!SDL_GL_GetSwapInterval(&interval)) {
  1786. return false;
  1787. }
  1788. if (interval != vsync) {
  1789. return SDL_Unsupported();
  1790. }
  1791. return true;
  1792. }
  1793. /*************************************************************************************************
  1794. * Renderer instantiation *
  1795. *************************************************************************************************/
  1796. static bool GLES2_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, SDL_PropertiesID create_props)
  1797. {
  1798. GLES2_RenderData *data = NULL;
  1799. SDL_WindowFlags window_flags = 0; // -Wconditional-uninitialized
  1800. GLint window_framebuffer;
  1801. GLint value;
  1802. int profile_mask = 0, major = 0, minor = 0;
  1803. bool changed_window = false;
  1804. if (!SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask)) {
  1805. goto error;
  1806. }
  1807. if (!SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major)) {
  1808. goto error;
  1809. }
  1810. if (!SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor)) {
  1811. goto error;
  1812. }
  1813. SDL_SyncWindow(window);
  1814. window_flags = SDL_GetWindowFlags(window);
  1815. // OpenGL ES 3.0 is a superset of OpenGL ES 2.0
  1816. if (!(window_flags & SDL_WINDOW_OPENGL) ||
  1817. profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major < RENDERER_CONTEXT_MAJOR) {
  1818. changed_window = true;
  1819. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
  1820. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
  1821. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
  1822. if (!SDL_RecreateWindow(window, (window_flags & ~(SDL_WINDOW_VULKAN | SDL_WINDOW_METAL)) | SDL_WINDOW_OPENGL)) {
  1823. goto error;
  1824. }
  1825. }
  1826. SDL_SetupRendererColorspace(renderer, create_props);
  1827. if (renderer->output_colorspace != SDL_COLORSPACE_SRGB) {
  1828. SDL_SetError("Unsupported output colorspace");
  1829. goto error;
  1830. }
  1831. data = (GLES2_RenderData *)SDL_calloc(1, sizeof(GLES2_RenderData));
  1832. if (!data) {
  1833. goto error;
  1834. }
  1835. renderer->internal = data;
  1836. GLES2_InvalidateCachedState(renderer);
  1837. renderer->window = window;
  1838. renderer->name = GLES2_RenderDriver.name;
  1839. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA32);
  1840. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA32);
  1841. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX32);
  1842. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX32);
  1843. // Create an OpenGL ES 2.0 context
  1844. data->context = SDL_GL_CreateContext(window);
  1845. if (!data->context) {
  1846. goto error;
  1847. }
  1848. if (!SDL_GL_MakeCurrent(window, data->context)) {
  1849. goto error;
  1850. }
  1851. if (!GLES2_LoadFunctions(data)) {
  1852. goto error;
  1853. }
  1854. if (!GLES2_CacheShaders(data)) {
  1855. goto error;
  1856. }
  1857. // Check for debug output support
  1858. if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) &&
  1859. (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
  1860. data->debug_enabled = true;
  1861. }
  1862. value = 0;
  1863. data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  1864. SDL_SetNumberProperty(SDL_GetRendererProperties(renderer), SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, value);
  1865. #if USE_VERTEX_BUFFER_OBJECTS
  1866. // we keep a few of these and cycle through them, so data can live for a few frames.
  1867. data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers);
  1868. #endif
  1869. data->framebuffers = NULL;
  1870. data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
  1871. data->window_framebuffer = (GLuint)window_framebuffer;
  1872. // Populate the function pointers for the module
  1873. renderer->WindowEvent = GLES2_WindowEvent;
  1874. renderer->SupportsBlendMode = GLES2_SupportsBlendMode;
  1875. renderer->CreateTexture = GLES2_CreateTexture;
  1876. renderer->UpdateTexture = GLES2_UpdateTexture;
  1877. #ifdef SDL_HAVE_YUV
  1878. renderer->UpdateTextureYUV = GLES2_UpdateTextureYUV;
  1879. renderer->UpdateTextureNV = GLES2_UpdateTextureNV;
  1880. #endif
  1881. renderer->LockTexture = GLES2_LockTexture;
  1882. renderer->UnlockTexture = GLES2_UnlockTexture;
  1883. renderer->SetTextureScaleMode = GLES2_SetTextureScaleMode;
  1884. renderer->SetRenderTarget = GLES2_SetRenderTarget;
  1885. renderer->QueueSetViewport = GLES2_QueueNoOp;
  1886. renderer->QueueSetDrawColor = GLES2_QueueNoOp;
  1887. renderer->QueueDrawPoints = GLES2_QueueDrawPoints;
  1888. renderer->QueueDrawLines = GLES2_QueueDrawLines;
  1889. renderer->QueueGeometry = GLES2_QueueGeometry;
  1890. renderer->InvalidateCachedState = GLES2_InvalidateCachedState;
  1891. renderer->RunCommandQueue = GLES2_RunCommandQueue;
  1892. renderer->RenderReadPixels = GLES2_RenderReadPixels;
  1893. renderer->RenderPresent = GLES2_RenderPresent;
  1894. renderer->DestroyTexture = GLES2_DestroyTexture;
  1895. renderer->DestroyRenderer = GLES2_DestroyRenderer;
  1896. renderer->SetVSync = GLES2_SetVSync;
  1897. #ifdef SDL_HAVE_YUV
  1898. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_YV12);
  1899. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_IYUV);
  1900. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV12);
  1901. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_NV21);
  1902. #endif
  1903. #ifdef GL_TEXTURE_EXTERNAL_OES
  1904. if (GLES2_CacheShader(data, GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES, GL_FRAGMENT_SHADER)) {
  1905. SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_EXTERNAL_OES);
  1906. }
  1907. #endif
  1908. if (SDL_GL_ExtensionSupported("GL_EXT_blend_minmax")) {
  1909. data->GL_EXT_blend_minmax_supported = true;
  1910. }
  1911. // Set up parameters for rendering
  1912. data->glDisable(GL_DEPTH_TEST);
  1913. data->glDisable(GL_CULL_FACE);
  1914. data->glActiveTexture(GL_TEXTURE0);
  1915. data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  1916. data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  1917. data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
  1918. data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_COLOR);
  1919. data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1920. data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
  1921. data->drawstate.clear_color.r = 1.0f;
  1922. data->drawstate.clear_color.g = 1.0f;
  1923. data->drawstate.clear_color.b = 1.0f;
  1924. data->drawstate.clear_color.a = 1.0f;
  1925. data->drawstate.projection[3][0] = -1.0f;
  1926. data->drawstate.projection[3][3] = 1.0f;
  1927. GL_CheckError("", renderer);
  1928. return true;
  1929. error:
  1930. if (changed_window) {
  1931. // Uh oh, better try to put it back...
  1932. char *error = SDL_strdup(SDL_GetError());
  1933. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
  1934. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
  1935. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
  1936. SDL_RecreateWindow(window, window_flags);
  1937. SDL_SetError("%s", error);
  1938. SDL_free(error);
  1939. }
  1940. return false;
  1941. }
  1942. SDL_RenderDriver GLES2_RenderDriver = {
  1943. GLES2_CreateRenderer, "opengles2"
  1944. };
  1945. #endif // SDL_VIDEO_RENDER_OGL_ES2