SDL_render_gles2.c 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053
  1. /*
  2. Simple DirectMedia Layer
  3. Copyright (C) 1997-2014 Sam Lantinga <[email protected]>
  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. #if SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED
  20. #include "SDL_hints.h"
  21. #include "SDL_opengles2.h"
  22. #include "../SDL_sysrender.h"
  23. #include "../../video/SDL_blit.h"
  24. #include "SDL_shaders_gles2.h"
  25. /* To prevent unnecessary window recreation,
  26. * these should match the defaults selected in SDL_GL_ResetAttributes
  27. */
  28. #define RENDERER_CONTEXT_MAJOR 2
  29. #define RENDERER_CONTEXT_MINOR 0
  30. /* Used to re-create the window with OpenGL ES capability */
  31. extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags);
  32. /*************************************************************************************************
  33. * Bootstrap data *
  34. *************************************************************************************************/
  35. static SDL_Renderer *GLES2_CreateRenderer(SDL_Window *window, Uint32 flags);
  36. SDL_RenderDriver GLES2_RenderDriver = {
  37. GLES2_CreateRenderer,
  38. {
  39. "opengles2",
  40. (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE),
  41. 4,
  42. {
  43. SDL_PIXELFORMAT_ARGB8888,
  44. SDL_PIXELFORMAT_ABGR8888,
  45. SDL_PIXELFORMAT_RGB888,
  46. SDL_PIXELFORMAT_BGR888
  47. },
  48. 0,
  49. 0
  50. }
  51. };
  52. /*************************************************************************************************
  53. * Context structures *
  54. *************************************************************************************************/
  55. typedef struct GLES2_FBOList GLES2_FBOList;
  56. struct GLES2_FBOList
  57. {
  58. Uint32 w, h;
  59. GLuint FBO;
  60. GLES2_FBOList *next;
  61. };
  62. typedef struct GLES2_TextureData
  63. {
  64. GLenum texture;
  65. GLenum texture_type;
  66. GLenum pixel_format;
  67. GLenum pixel_type;
  68. void *pixel_data;
  69. size_t pitch;
  70. /* YV12 texture support */
  71. SDL_bool yuv;
  72. GLenum texture_v;
  73. GLenum texture_u;
  74. GLES2_FBOList *fbo;
  75. } GLES2_TextureData;
  76. typedef struct GLES2_ShaderCacheEntry
  77. {
  78. GLuint id;
  79. GLES2_ShaderType type;
  80. const GLES2_ShaderInstance *instance;
  81. int references;
  82. Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
  83. struct GLES2_ShaderCacheEntry *prev;
  84. struct GLES2_ShaderCacheEntry *next;
  85. } GLES2_ShaderCacheEntry;
  86. typedef struct GLES2_ShaderCache
  87. {
  88. int count;
  89. GLES2_ShaderCacheEntry *head;
  90. } GLES2_ShaderCache;
  91. typedef struct GLES2_ProgramCacheEntry
  92. {
  93. GLuint id;
  94. SDL_BlendMode blend_mode;
  95. GLES2_ShaderCacheEntry *vertex_shader;
  96. GLES2_ShaderCacheEntry *fragment_shader;
  97. GLuint uniform_locations[16];
  98. Uint8 color_r, color_g, color_b, color_a;
  99. Uint8 modulation_r, modulation_g, modulation_b, modulation_a;
  100. GLfloat projection[4][4];
  101. struct GLES2_ProgramCacheEntry *prev;
  102. struct GLES2_ProgramCacheEntry *next;
  103. } GLES2_ProgramCacheEntry;
  104. typedef struct GLES2_ProgramCache
  105. {
  106. int count;
  107. GLES2_ProgramCacheEntry *head;
  108. GLES2_ProgramCacheEntry *tail;
  109. } GLES2_ProgramCache;
  110. typedef enum
  111. {
  112. GLES2_ATTRIBUTE_POSITION = 0,
  113. GLES2_ATTRIBUTE_TEXCOORD = 1,
  114. GLES2_ATTRIBUTE_ANGLE = 2,
  115. GLES2_ATTRIBUTE_CENTER = 3,
  116. } GLES2_Attribute;
  117. typedef enum
  118. {
  119. GLES2_UNIFORM_PROJECTION,
  120. GLES2_UNIFORM_TEXTURE,
  121. GLES2_UNIFORM_MODULATION,
  122. GLES2_UNIFORM_COLOR,
  123. GLES2_UNIFORM_TEXTURE_U,
  124. GLES2_UNIFORM_TEXTURE_V
  125. } GLES2_Uniform;
  126. typedef enum
  127. {
  128. GLES2_IMAGESOURCE_SOLID,
  129. GLES2_IMAGESOURCE_TEXTURE_ABGR,
  130. GLES2_IMAGESOURCE_TEXTURE_ARGB,
  131. GLES2_IMAGESOURCE_TEXTURE_RGB,
  132. GLES2_IMAGESOURCE_TEXTURE_BGR,
  133. GLES2_IMAGESOURCE_TEXTURE_YUV
  134. } GLES2_ImageSource;
  135. typedef struct GLES2_DriverContext
  136. {
  137. SDL_GLContext *context;
  138. SDL_bool debug_enabled;
  139. struct {
  140. int blendMode;
  141. SDL_bool tex_coords;
  142. } current;
  143. #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
  144. #include "SDL_gles2funcs.h"
  145. #undef SDL_PROC
  146. GLES2_FBOList *framebuffers;
  147. GLuint window_framebuffer;
  148. int shader_format_count;
  149. GLenum *shader_formats;
  150. GLES2_ShaderCache shader_cache;
  151. GLES2_ProgramCache program_cache;
  152. GLES2_ProgramCacheEntry *current_program;
  153. Uint8 clear_r, clear_g, clear_b, clear_a;
  154. } GLES2_DriverContext;
  155. #define GLES2_MAX_CACHED_PROGRAMS 8
  156. SDL_FORCE_INLINE const char*
  157. GL_TranslateError (GLenum error)
  158. {
  159. #define GL_ERROR_TRANSLATE(e) case e: return #e;
  160. switch (error) {
  161. GL_ERROR_TRANSLATE(GL_INVALID_ENUM)
  162. GL_ERROR_TRANSLATE(GL_INVALID_VALUE)
  163. GL_ERROR_TRANSLATE(GL_INVALID_OPERATION)
  164. GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY)
  165. GL_ERROR_TRANSLATE(GL_NO_ERROR)
  166. default:
  167. return "UNKNOWN";
  168. }
  169. #undef GL_ERROR_TRANSLATE
  170. }
  171. SDL_FORCE_INLINE void
  172. GL_ClearErrors(SDL_Renderer *renderer)
  173. {
  174. GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  175. if (!data->debug_enabled)
  176. {
  177. return;
  178. }
  179. while (data->glGetError() != GL_NO_ERROR) {
  180. continue;
  181. }
  182. }
  183. SDL_FORCE_INLINE int
  184. GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function)
  185. {
  186. GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  187. int ret = 0;
  188. if (!data->debug_enabled)
  189. {
  190. return 0;
  191. }
  192. /* check gl errors (can return multiple errors) */
  193. for (;;) {
  194. GLenum error = data->glGetError();
  195. if (error != GL_NO_ERROR) {
  196. if (prefix == NULL || prefix[0] == '\0') {
  197. prefix = "generic";
  198. }
  199. SDL_SetError("%s: %s (%d): %s %s (0x%X)", prefix, file, line, function, GL_TranslateError(error), error);
  200. ret = -1;
  201. } else {
  202. break;
  203. }
  204. }
  205. return ret;
  206. }
  207. #if 0
  208. #define GL_CheckError(prefix, renderer)
  209. #elif defined(_MSC_VER)
  210. #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __FUNCTION__)
  211. #else
  212. #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, __FILE__, __LINE__, __PRETTY_FUNCTION__)
  213. #endif
  214. /*************************************************************************************************
  215. * Renderer state APIs *
  216. *************************************************************************************************/
  217. static int GLES2_ActivateRenderer(SDL_Renderer *renderer);
  218. static void GLES2_WindowEvent(SDL_Renderer * renderer,
  219. const SDL_WindowEvent *event);
  220. static int GLES2_UpdateViewport(SDL_Renderer * renderer);
  221. static void GLES2_DestroyRenderer(SDL_Renderer *renderer);
  222. static int GLES2_SetOrthographicProjection(SDL_Renderer *renderer);
  223. static SDL_GLContext SDL_CurrentContext = NULL;
  224. static int GLES2_LoadFunctions(GLES2_DriverContext * data)
  225. {
  226. #if SDL_VIDEO_DRIVER_UIKIT
  227. #define __SDL_NOGETPROCADDR__
  228. #elif SDL_VIDEO_DRIVER_ANDROID
  229. #define __SDL_NOGETPROCADDR__
  230. #elif SDL_VIDEO_DRIVER_PANDORA
  231. #define __SDL_NOGETPROCADDR__
  232. #endif
  233. #if defined __SDL_NOGETPROCADDR__
  234. #define SDL_PROC(ret,func,params) data->func=func;
  235. #else
  236. #define SDL_PROC(ret,func,params) \
  237. do { \
  238. data->func = SDL_GL_GetProcAddress(#func); \
  239. if ( ! data->func ) { \
  240. return SDL_SetError("Couldn't load GLES2 function %s: %s\n", #func, SDL_GetError()); \
  241. } \
  242. } while ( 0 );
  243. #endif /* _SDL_NOGETPROCADDR_ */
  244. #include "SDL_gles2funcs.h"
  245. #undef SDL_PROC
  246. return 0;
  247. }
  248. GLES2_FBOList *
  249. GLES2_GetFBO(GLES2_DriverContext *data, Uint32 w, Uint32 h)
  250. {
  251. GLES2_FBOList *result = data->framebuffers;
  252. while ((result) && ((result->w != w) || (result->h != h)) )
  253. {
  254. result = result->next;
  255. }
  256. if (result == NULL)
  257. {
  258. result = SDL_malloc(sizeof(GLES2_FBOList));
  259. result->w = w;
  260. result->h = h;
  261. data->glGenFramebuffers(1, &result->FBO);
  262. result->next = data->framebuffers;
  263. data->framebuffers = result;
  264. }
  265. return result;
  266. }
  267. static int
  268. GLES2_ActivateRenderer(SDL_Renderer * renderer)
  269. {
  270. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  271. if (SDL_CurrentContext != data->context) {
  272. /* Null out the current program to ensure we set it again */
  273. data->current_program = NULL;
  274. if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) {
  275. return -1;
  276. }
  277. SDL_CurrentContext = data->context;
  278. GLES2_UpdateViewport(renderer);
  279. }
  280. GL_ClearErrors(renderer);
  281. return 0;
  282. }
  283. static void
  284. GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
  285. {
  286. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  287. if (event->event == SDL_WINDOWEVENT_SIZE_CHANGED ||
  288. event->event == SDL_WINDOWEVENT_SHOWN ||
  289. event->event == SDL_WINDOWEVENT_HIDDEN) {
  290. /* Rebind the context to the window area */
  291. SDL_CurrentContext = NULL;
  292. }
  293. if (event->event == SDL_WINDOWEVENT_MINIMIZED) {
  294. /* According to Apple documentation, we need to finish drawing NOW! */
  295. data->glFinish();
  296. }
  297. }
  298. static int
  299. GLES2_UpdateViewport(SDL_Renderer * renderer)
  300. {
  301. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  302. if (SDL_CurrentContext != data->context) {
  303. /* We'll update the viewport after we rebind the context */
  304. return 0;
  305. }
  306. data->glViewport(renderer->viewport.x, renderer->viewport.y,
  307. renderer->viewport.w, renderer->viewport.h);
  308. if (data->current_program) {
  309. GLES2_SetOrthographicProjection(renderer);
  310. }
  311. return GL_CheckError("", renderer);
  312. }
  313. static int
  314. GLES2_UpdateClipRect(SDL_Renderer * renderer)
  315. {
  316. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  317. if (SDL_CurrentContext != data->context) {
  318. /* We'll update the clip rect after we rebind the context */
  319. return 0;
  320. }
  321. if (renderer->clipping_enabled) {
  322. const SDL_Rect *rect = &renderer->clip_rect;
  323. data->glEnable(GL_SCISSOR_TEST);
  324. data->glScissor(rect->x, renderer->viewport.h - rect->y - rect->h, rect->w, rect->h);
  325. } else {
  326. data->glDisable(GL_SCISSOR_TEST);
  327. }
  328. return 0;
  329. }
  330. static void
  331. GLES2_DestroyRenderer(SDL_Renderer *renderer)
  332. {
  333. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  334. /* Deallocate everything */
  335. if (data) {
  336. GLES2_ActivateRenderer(renderer);
  337. {
  338. GLES2_ShaderCacheEntry *entry;
  339. GLES2_ShaderCacheEntry *next;
  340. entry = data->shader_cache.head;
  341. while (entry)
  342. {
  343. data->glDeleteShader(entry->id);
  344. next = entry->next;
  345. SDL_free(entry);
  346. entry = next;
  347. }
  348. }
  349. {
  350. GLES2_ProgramCacheEntry *entry;
  351. GLES2_ProgramCacheEntry *next;
  352. entry = data->program_cache.head;
  353. while (entry) {
  354. data->glDeleteProgram(entry->id);
  355. next = entry->next;
  356. SDL_free(entry);
  357. entry = next;
  358. }
  359. }
  360. if (data->context) {
  361. while (data->framebuffers) {
  362. GLES2_FBOList *nextnode = data->framebuffers->next;
  363. data->glDeleteFramebuffers(1, &data->framebuffers->FBO);
  364. GL_CheckError("", renderer);
  365. SDL_free(data->framebuffers);
  366. data->framebuffers = nextnode;
  367. }
  368. SDL_GL_DeleteContext(data->context);
  369. }
  370. SDL_free(data->shader_formats);
  371. SDL_free(data);
  372. }
  373. SDL_free(renderer);
  374. }
  375. /*************************************************************************************************
  376. * Texture APIs *
  377. *************************************************************************************************/
  378. static int GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture);
  379. static int GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  380. const void *pixels, int pitch);
  381. static int GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
  382. const SDL_Rect * rect,
  383. const Uint8 *Yplane, int Ypitch,
  384. const Uint8 *Uplane, int Upitch,
  385. const Uint8 *Vplane, int Vpitch);
  386. static int GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  387. void **pixels, int *pitch);
  388. static void GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture);
  389. static int GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture);
  390. static void GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture);
  391. static GLenum
  392. GetScaleQuality(void)
  393. {
  394. const char *hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
  395. if (!hint || *hint == '0' || SDL_strcasecmp(hint, "nearest") == 0) {
  396. return GL_NEAREST;
  397. } else {
  398. return GL_LINEAR;
  399. }
  400. }
  401. static int
  402. GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  403. {
  404. GLES2_DriverContext *renderdata = (GLES2_DriverContext *)renderer->driverdata;
  405. GLES2_TextureData *data;
  406. GLenum format;
  407. GLenum type;
  408. GLenum scaleMode;
  409. GLES2_ActivateRenderer(renderer);
  410. /* Determine the corresponding GLES texture format params */
  411. switch (texture->format)
  412. {
  413. case SDL_PIXELFORMAT_ARGB8888:
  414. case SDL_PIXELFORMAT_ABGR8888:
  415. case SDL_PIXELFORMAT_RGB888:
  416. case SDL_PIXELFORMAT_BGR888:
  417. format = GL_RGBA;
  418. type = GL_UNSIGNED_BYTE;
  419. break;
  420. case SDL_PIXELFORMAT_IYUV:
  421. case SDL_PIXELFORMAT_YV12:
  422. format = GL_LUMINANCE;
  423. type = GL_UNSIGNED_BYTE;
  424. break;
  425. default:
  426. return SDL_SetError("Texture format not supported");
  427. }
  428. /* Allocate a texture struct */
  429. data = (GLES2_TextureData *)SDL_calloc(1, sizeof(GLES2_TextureData));
  430. if (!data) {
  431. return SDL_OutOfMemory();
  432. }
  433. data->texture = 0;
  434. data->texture_type = GL_TEXTURE_2D;
  435. data->pixel_format = format;
  436. data->pixel_type = type;
  437. data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12));
  438. data->texture_u = 0;
  439. data->texture_v = 0;
  440. scaleMode = GetScaleQuality();
  441. /* Allocate a blob for image renderdata */
  442. if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
  443. size_t size;
  444. data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
  445. size = texture->h * data->pitch;
  446. if (data->yuv) {
  447. /* Need to add size for the U and V planes */
  448. size += (2 * (texture->h * data->pitch) / 4);
  449. }
  450. data->pixel_data = SDL_calloc(1, size);
  451. if (!data->pixel_data) {
  452. SDL_free(data);
  453. return SDL_OutOfMemory();
  454. }
  455. }
  456. /* Allocate the texture */
  457. GL_CheckError("", renderer);
  458. if (data->yuv) {
  459. renderdata->glGenTextures(1, &data->texture_v);
  460. if (GL_CheckError("glGenTexures()", renderer) < 0) {
  461. return -1;
  462. }
  463. renderdata->glActiveTexture(GL_TEXTURE2);
  464. renderdata->glBindTexture(data->texture_type, data->texture_v);
  465. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  466. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  467. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  468. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  469. renderdata->glTexImage2D(data->texture_type, 0, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
  470. renderdata->glGenTextures(1, &data->texture_u);
  471. if (GL_CheckError("glGenTexures()", renderer) < 0) {
  472. return -1;
  473. }
  474. renderdata->glActiveTexture(GL_TEXTURE1);
  475. renderdata->glBindTexture(data->texture_type, data->texture_u);
  476. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  477. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  478. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  479. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  480. renderdata->glTexImage2D(data->texture_type, 0, format, texture->w / 2, texture->h / 2, 0, format, type, NULL);
  481. if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  482. return -1;
  483. }
  484. }
  485. renderdata->glGenTextures(1, &data->texture);
  486. if (GL_CheckError("glGenTexures()", renderer) < 0) {
  487. return -1;
  488. }
  489. texture->driverdata = data;
  490. renderdata->glActiveTexture(GL_TEXTURE0);
  491. renderdata->glBindTexture(data->texture_type, data->texture);
  492. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode);
  493. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode);
  494. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  495. renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  496. renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL);
  497. if (GL_CheckError("glTexImage2D()", renderer) < 0) {
  498. return -1;
  499. }
  500. if (texture->access == SDL_TEXTUREACCESS_TARGET) {
  501. data->fbo = GLES2_GetFBO(renderer->driverdata, texture->w, texture->h);
  502. } else {
  503. data->fbo = NULL;
  504. }
  505. return GL_CheckError("", renderer);
  506. }
  507. static int
  508. GLES2_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)
  509. {
  510. Uint8 *blob = NULL;
  511. Uint8 *src;
  512. int src_pitch;
  513. int y;
  514. /* Reformat the texture data into a tightly packed array */
  515. src_pitch = width * bpp;
  516. src = (Uint8 *)data;
  517. if (pitch != src_pitch) {
  518. blob = (Uint8 *)SDL_malloc(src_pitch * height);
  519. if (!blob) {
  520. return SDL_OutOfMemory();
  521. }
  522. src = blob;
  523. for (y = 0; y < height; ++y)
  524. {
  525. SDL_memcpy(src, pixels, src_pitch);
  526. src += src_pitch;
  527. pixels = (Uint8 *)pixels + pitch;
  528. }
  529. src = blob;
  530. }
  531. data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src);
  532. if (blob) {
  533. SDL_free(blob);
  534. }
  535. return 0;
  536. }
  537. static int
  538. GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  539. const void *pixels, int pitch)
  540. {
  541. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  542. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  543. GLES2_ActivateRenderer(renderer);
  544. /* Bail out if we're supposed to update an empty rectangle */
  545. if (rect->w <= 0 || rect->h <= 0)
  546. return 0;
  547. /* Create a texture subimage with the supplied data */
  548. data->glBindTexture(tdata->texture_type, tdata->texture);
  549. GLES2_TexSubImage2D(data, tdata->texture_type,
  550. rect->x,
  551. rect->y,
  552. rect->w,
  553. rect->h,
  554. tdata->pixel_format,
  555. tdata->pixel_type,
  556. pixels, pitch, SDL_BYTESPERPIXEL(texture->format));
  557. return GL_CheckError("glTexSubImage2D()", renderer);
  558. }
  559. static int
  560. GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture,
  561. const SDL_Rect * rect,
  562. const Uint8 *Yplane, int Ypitch,
  563. const Uint8 *Uplane, int Upitch,
  564. const Uint8 *Vplane, int Vpitch)
  565. {
  566. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  567. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  568. GLES2_ActivateRenderer(renderer);
  569. /* Bail out if we're supposed to update an empty rectangle */
  570. if (rect->w <= 0 || rect->h <= 0)
  571. return 0;
  572. data->glBindTexture(tdata->texture_type, tdata->texture_v);
  573. GLES2_TexSubImage2D(data, tdata->texture_type,
  574. rect->x,
  575. rect->y,
  576. rect->w / 2,
  577. rect->h / 2,
  578. tdata->pixel_format,
  579. tdata->pixel_type,
  580. Vplane, Vpitch, 1);
  581. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  582. GLES2_TexSubImage2D(data, tdata->texture_type,
  583. rect->x,
  584. rect->y,
  585. rect->w / 2,
  586. rect->h / 2,
  587. tdata->pixel_format,
  588. tdata->pixel_type,
  589. Uplane, Upitch, 1);
  590. data->glBindTexture(tdata->texture_type, tdata->texture);
  591. GLES2_TexSubImage2D(data, tdata->texture_type,
  592. rect->x,
  593. rect->y,
  594. rect->w,
  595. rect->h,
  596. tdata->pixel_format,
  597. tdata->pixel_type,
  598. Vplane, Vpitch, 1);
  599. return GL_CheckError("glTexSubImage2D()", renderer);
  600. }
  601. static int
  602. GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect,
  603. void **pixels, int *pitch)
  604. {
  605. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  606. /* Retrieve the buffer/pitch for the specified region */
  607. *pixels = (Uint8 *)tdata->pixel_data +
  608. (tdata->pitch * rect->y) +
  609. (rect->x * SDL_BYTESPERPIXEL(texture->format));
  610. *pitch = tdata->pitch;
  611. return 0;
  612. }
  613. static void
  614. GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  615. {
  616. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  617. SDL_Rect rect;
  618. /* We do whole texture updates, at least for now */
  619. rect.x = 0;
  620. rect.y = 0;
  621. rect.w = texture->w;
  622. rect.h = texture->h;
  623. GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch);
  624. }
  625. static int
  626. GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
  627. {
  628. GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  629. GLES2_TextureData *texturedata = NULL;
  630. GLenum status;
  631. if (texture == NULL) {
  632. data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer);
  633. } else {
  634. texturedata = (GLES2_TextureData *) texture->driverdata;
  635. data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO);
  636. /* TODO: check if texture pixel format allows this operation */
  637. data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0);
  638. /* Check FBO status */
  639. status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER);
  640. if (status != GL_FRAMEBUFFER_COMPLETE) {
  641. return SDL_SetError("glFramebufferTexture2D() failed");
  642. }
  643. }
  644. return 0;
  645. }
  646. static void
  647. GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
  648. {
  649. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  650. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  651. GLES2_ActivateRenderer(renderer);
  652. /* Destroy the texture */
  653. if (tdata)
  654. {
  655. data->glDeleteTextures(1, &tdata->texture);
  656. if (tdata->texture_v) {
  657. data->glDeleteTextures(1, &tdata->texture_v);
  658. }
  659. if (tdata->texture_u) {
  660. data->glDeleteTextures(1, &tdata->texture_u);
  661. }
  662. SDL_free(tdata->pixel_data);
  663. SDL_free(tdata);
  664. texture->driverdata = NULL;
  665. }
  666. }
  667. /*************************************************************************************************
  668. * Shader management functions *
  669. *************************************************************************************************/
  670. static GLES2_ShaderCacheEntry *GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type,
  671. SDL_BlendMode blendMode);
  672. static void GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry);
  673. static GLES2_ProgramCacheEntry *GLES2_CacheProgram(SDL_Renderer *renderer,
  674. GLES2_ShaderCacheEntry *vertex,
  675. GLES2_ShaderCacheEntry *fragment,
  676. SDL_BlendMode blendMode);
  677. static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source,
  678. SDL_BlendMode blendMode);
  679. static GLES2_ProgramCacheEntry *
  680. GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex,
  681. GLES2_ShaderCacheEntry *fragment, SDL_BlendMode blendMode)
  682. {
  683. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  684. GLES2_ProgramCacheEntry *entry;
  685. GLES2_ShaderCacheEntry *shaderEntry;
  686. GLint linkSuccessful;
  687. /* Check if we've already cached this program */
  688. entry = data->program_cache.head;
  689. while (entry)
  690. {
  691. if (entry->vertex_shader == vertex && entry->fragment_shader == fragment)
  692. break;
  693. entry = entry->next;
  694. }
  695. if (entry)
  696. {
  697. if (data->program_cache.head != entry)
  698. {
  699. if (entry->next)
  700. entry->next->prev = entry->prev;
  701. if (entry->prev)
  702. entry->prev->next = entry->next;
  703. entry->prev = NULL;
  704. entry->next = data->program_cache.head;
  705. data->program_cache.head->prev = entry;
  706. data->program_cache.head = entry;
  707. }
  708. return entry;
  709. }
  710. /* Create a program cache entry */
  711. entry = (GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(GLES2_ProgramCacheEntry));
  712. if (!entry)
  713. {
  714. SDL_OutOfMemory();
  715. return NULL;
  716. }
  717. entry->vertex_shader = vertex;
  718. entry->fragment_shader = fragment;
  719. entry->blend_mode = blendMode;
  720. /* Create the program and link it */
  721. entry->id = data->glCreateProgram();
  722. data->glAttachShader(entry->id, vertex->id);
  723. data->glAttachShader(entry->id, fragment->id);
  724. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_POSITION, "a_position");
  725. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord");
  726. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle");
  727. data->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center");
  728. data->glLinkProgram(entry->id);
  729. data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful);
  730. if (!linkSuccessful)
  731. {
  732. data->glDeleteProgram(entry->id);
  733. SDL_free(entry);
  734. SDL_SetError("Failed to link shader program");
  735. return NULL;
  736. }
  737. /* Predetermine locations of uniform variables */
  738. entry->uniform_locations[GLES2_UNIFORM_PROJECTION] =
  739. data->glGetUniformLocation(entry->id, "u_projection");
  740. entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V] =
  741. data->glGetUniformLocation(entry->id, "u_texture_v");
  742. entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U] =
  743. data->glGetUniformLocation(entry->id, "u_texture_u");
  744. entry->uniform_locations[GLES2_UNIFORM_TEXTURE] =
  745. data->glGetUniformLocation(entry->id, "u_texture");
  746. entry->uniform_locations[GLES2_UNIFORM_MODULATION] =
  747. data->glGetUniformLocation(entry->id, "u_modulation");
  748. entry->uniform_locations[GLES2_UNIFORM_COLOR] =
  749. data->glGetUniformLocation(entry->id, "u_color");
  750. entry->modulation_r = entry->modulation_g = entry->modulation_b = entry->modulation_a = 255;
  751. entry->color_r = entry->color_g = entry->color_b = entry->color_a = 255;
  752. data->glUseProgram(entry->id);
  753. data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */
  754. data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */
  755. data->glUniform1i(entry->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */
  756. data->glUniformMatrix4fv(entry->uniform_locations[GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection);
  757. data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0f, 1.0f, 1.0f, 1.0f);
  758. data->glUniform4f(entry->uniform_locations[GLES2_UNIFORM_COLOR], 1.0f, 1.0f, 1.0f, 1.0f);
  759. /* Cache the linked program */
  760. if (data->program_cache.head)
  761. {
  762. entry->next = data->program_cache.head;
  763. data->program_cache.head->prev = entry;
  764. }
  765. else
  766. {
  767. data->program_cache.tail = entry;
  768. }
  769. data->program_cache.head = entry;
  770. ++data->program_cache.count;
  771. /* Increment the refcount of the shaders we're using */
  772. ++vertex->references;
  773. ++fragment->references;
  774. /* Evict the last entry from the cache if we exceed the limit */
  775. if (data->program_cache.count > GLES2_MAX_CACHED_PROGRAMS)
  776. {
  777. shaderEntry = data->program_cache.tail->vertex_shader;
  778. if (--shaderEntry->references <= 0)
  779. GLES2_EvictShader(renderer, shaderEntry);
  780. shaderEntry = data->program_cache.tail->fragment_shader;
  781. if (--shaderEntry->references <= 0)
  782. GLES2_EvictShader(renderer, shaderEntry);
  783. data->glDeleteProgram(data->program_cache.tail->id);
  784. data->program_cache.tail = data->program_cache.tail->prev;
  785. SDL_free(data->program_cache.tail->next);
  786. data->program_cache.tail->next = NULL;
  787. --data->program_cache.count;
  788. }
  789. return entry;
  790. }
  791. static GLES2_ShaderCacheEntry *
  792. GLES2_CacheShader(SDL_Renderer *renderer, GLES2_ShaderType type, SDL_BlendMode blendMode)
  793. {
  794. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  795. const GLES2_Shader *shader;
  796. const GLES2_ShaderInstance *instance = NULL;
  797. GLES2_ShaderCacheEntry *entry = NULL;
  798. GLint compileSuccessful = GL_FALSE;
  799. int i, j;
  800. /* Find the corresponding shader */
  801. shader = GLES2_GetShader(type, blendMode);
  802. if (!shader)
  803. {
  804. SDL_SetError("No shader matching the requested characteristics was found");
  805. return NULL;
  806. }
  807. /* Find a matching shader instance that's supported on this hardware */
  808. for (i = 0; i < shader->instance_count && !instance; ++i)
  809. {
  810. for (j = 0; j < data->shader_format_count && !instance; ++j)
  811. {
  812. if (!shader->instances)
  813. continue;
  814. if (!shader->instances[i])
  815. continue;
  816. if (shader->instances[i]->format != data->shader_formats[j])
  817. continue;
  818. instance = shader->instances[i];
  819. }
  820. }
  821. if (!instance)
  822. {
  823. SDL_SetError("The specified shader cannot be loaded on the current platform");
  824. return NULL;
  825. }
  826. /* Check if we've already cached this shader */
  827. entry = data->shader_cache.head;
  828. while (entry)
  829. {
  830. if (entry->instance == instance)
  831. break;
  832. entry = entry->next;
  833. }
  834. if (entry)
  835. return entry;
  836. /* Create a shader cache entry */
  837. entry = (GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(GLES2_ShaderCacheEntry));
  838. if (!entry)
  839. {
  840. SDL_OutOfMemory();
  841. return NULL;
  842. }
  843. entry->type = type;
  844. entry->instance = instance;
  845. /* Compile or load the selected shader instance */
  846. entry->id = data->glCreateShader(instance->type);
  847. if (instance->format == (GLenum)-1)
  848. {
  849. data->glShaderSource(entry->id, 1, (const char **)&instance->data, NULL);
  850. data->glCompileShader(entry->id);
  851. data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful);
  852. }
  853. else
  854. {
  855. data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length);
  856. compileSuccessful = GL_TRUE;
  857. }
  858. if (!compileSuccessful)
  859. {
  860. char *info = NULL;
  861. int length = 0;
  862. data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length);
  863. if (length > 0) {
  864. info = SDL_stack_alloc(char, length);
  865. if (info) {
  866. data->glGetShaderInfoLog(entry->id, length, &length, info);
  867. }
  868. }
  869. if (info) {
  870. SDL_SetError("Failed to load the shader: %s", info);
  871. SDL_stack_free(info);
  872. } else {
  873. SDL_SetError("Failed to load the shader");
  874. }
  875. data->glDeleteShader(entry->id);
  876. SDL_free(entry);
  877. return NULL;
  878. }
  879. /* Link the shader entry in at the front of the cache */
  880. if (data->shader_cache.head)
  881. {
  882. entry->next = data->shader_cache.head;
  883. data->shader_cache.head->prev = entry;
  884. }
  885. data->shader_cache.head = entry;
  886. ++data->shader_cache.count;
  887. return entry;
  888. }
  889. static void
  890. GLES2_EvictShader(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *entry)
  891. {
  892. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  893. /* Unlink the shader from the cache */
  894. if (entry->next)
  895. entry->next->prev = entry->prev;
  896. if (entry->prev)
  897. entry->prev->next = entry->next;
  898. if (data->shader_cache.head == entry)
  899. data->shader_cache.head = entry->next;
  900. --data->shader_cache.count;
  901. /* Deallocate the shader */
  902. data->glDeleteShader(entry->id);
  903. SDL_free(entry);
  904. }
  905. static int
  906. GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendMode blendMode)
  907. {
  908. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  909. GLES2_ShaderCacheEntry *vertex = NULL;
  910. GLES2_ShaderCacheEntry *fragment = NULL;
  911. GLES2_ShaderType vtype, ftype;
  912. GLES2_ProgramCacheEntry *program;
  913. /* Select an appropriate shader pair for the specified modes */
  914. vtype = GLES2_SHADER_VERTEX_DEFAULT;
  915. switch (source)
  916. {
  917. case GLES2_IMAGESOURCE_SOLID:
  918. ftype = GLES2_SHADER_FRAGMENT_SOLID_SRC;
  919. break;
  920. case GLES2_IMAGESOURCE_TEXTURE_ABGR:
  921. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC;
  922. break;
  923. case GLES2_IMAGESOURCE_TEXTURE_ARGB:
  924. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC;
  925. break;
  926. case GLES2_IMAGESOURCE_TEXTURE_RGB:
  927. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC;
  928. break;
  929. case GLES2_IMAGESOURCE_TEXTURE_BGR:
  930. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC;
  931. break;
  932. case GLES2_IMAGESOURCE_TEXTURE_YUV:
  933. ftype = GLES2_SHADER_FRAGMENT_TEXTURE_YUV_SRC;
  934. break;
  935. default:
  936. goto fault;
  937. }
  938. /* Load the requested shaders */
  939. vertex = GLES2_CacheShader(renderer, vtype, blendMode);
  940. if (!vertex)
  941. goto fault;
  942. fragment = GLES2_CacheShader(renderer, ftype, blendMode);
  943. if (!fragment)
  944. goto fault;
  945. /* Check if we need to change programs at all */
  946. if (data->current_program &&
  947. data->current_program->vertex_shader == vertex &&
  948. data->current_program->fragment_shader == fragment)
  949. return 0;
  950. /* Generate a matching program */
  951. program = GLES2_CacheProgram(renderer, vertex, fragment, blendMode);
  952. if (!program)
  953. goto fault;
  954. /* Select that program in OpenGL */
  955. data->glUseProgram(program->id);
  956. /* Set the current program */
  957. data->current_program = program;
  958. /* Activate an orthographic projection */
  959. if (GLES2_SetOrthographicProjection(renderer) < 0)
  960. goto fault;
  961. /* Clean up and return */
  962. return 0;
  963. fault:
  964. if (vertex && vertex->references <= 0)
  965. GLES2_EvictShader(renderer, vertex);
  966. if (fragment && fragment->references <= 0)
  967. GLES2_EvictShader(renderer, fragment);
  968. data->current_program = NULL;
  969. return -1;
  970. }
  971. static int
  972. GLES2_SetOrthographicProjection(SDL_Renderer *renderer)
  973. {
  974. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  975. GLfloat projection[4][4];
  976. if (!renderer->viewport.w || !renderer->viewport.h) {
  977. return 0;
  978. }
  979. /* Prepare an orthographic projection */
  980. projection[0][0] = 2.0f / renderer->viewport.w;
  981. projection[0][1] = 0.0f;
  982. projection[0][2] = 0.0f;
  983. projection[0][3] = 0.0f;
  984. projection[1][0] = 0.0f;
  985. if (renderer->target) {
  986. projection[1][1] = 2.0f / renderer->viewport.h;
  987. } else {
  988. projection[1][1] = -2.0f / renderer->viewport.h;
  989. }
  990. projection[1][2] = 0.0f;
  991. projection[1][3] = 0.0f;
  992. projection[2][0] = 0.0f;
  993. projection[2][1] = 0.0f;
  994. projection[2][2] = 0.0f;
  995. projection[2][3] = 0.0f;
  996. projection[3][0] = -1.0f;
  997. if (renderer->target) {
  998. projection[3][1] = -1.0f;
  999. } else {
  1000. projection[3][1] = 1.0f;
  1001. }
  1002. projection[3][2] = 0.0f;
  1003. projection[3][3] = 1.0f;
  1004. /* Set the projection matrix */
  1005. if (SDL_memcmp(data->current_program->projection, projection, sizeof (projection)) != 0) {
  1006. const GLuint locProjection = data->current_program->uniform_locations[GLES2_UNIFORM_PROJECTION];
  1007. data->glUniformMatrix4fv(locProjection, 1, GL_FALSE, (GLfloat *)projection);
  1008. SDL_memcpy(data->current_program->projection, projection, sizeof (projection));
  1009. }
  1010. return 0;
  1011. }
  1012. /*************************************************************************************************
  1013. * Rendering functions *
  1014. *************************************************************************************************/
  1015. static const float inv255f = 1.0f / 255.0f;
  1016. static int GLES2_RenderClear(SDL_Renderer *renderer);
  1017. static int GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
  1018. static int GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count);
  1019. static int GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count);
  1020. static int GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  1021. const SDL_FRect *dstrect);
  1022. static int GLES2_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
  1023. const SDL_Rect * srcrect, const SDL_FRect * dstrect,
  1024. const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip);
  1025. static int GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1026. Uint32 pixel_format, void * pixels, int pitch);
  1027. static void GLES2_RenderPresent(SDL_Renderer *renderer);
  1028. static SDL_bool
  1029. CompareColors(Uint8 r1, Uint8 g1, Uint8 b1, Uint8 a1,
  1030. Uint8 r2, Uint8 g2, Uint8 b2, Uint8 a2)
  1031. {
  1032. Uint32 Pixel1, Pixel2;
  1033. RGBA8888_FROM_RGBA(Pixel1, r1, g1, b1, a1);
  1034. RGBA8888_FROM_RGBA(Pixel2, r2, g2, b2, a2);
  1035. return (Pixel1 == Pixel2);
  1036. }
  1037. static int
  1038. GLES2_RenderClear(SDL_Renderer * renderer)
  1039. {
  1040. Uint8 r, g, b, a;
  1041. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1042. GLES2_ActivateRenderer(renderer);
  1043. if (!CompareColors(data->clear_r, data->clear_g, data->clear_b, data->clear_a,
  1044. renderer->r, renderer->g, renderer->b, renderer->a)) {
  1045. /* Select the color to clear with */
  1046. g = renderer->g;
  1047. a = renderer->a;
  1048. if (renderer->target &&
  1049. (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
  1050. renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
  1051. r = renderer->b;
  1052. b = renderer->r;
  1053. } else {
  1054. r = renderer->r;
  1055. b = renderer->b;
  1056. }
  1057. data->glClearColor((GLfloat) r * inv255f,
  1058. (GLfloat) g * inv255f,
  1059. (GLfloat) b * inv255f,
  1060. (GLfloat) a * inv255f);
  1061. data->clear_r = renderer->r;
  1062. data->clear_g = renderer->g;
  1063. data->clear_b = renderer->b;
  1064. data->clear_a = renderer->a;
  1065. }
  1066. data->glClear(GL_COLOR_BUFFER_BIT);
  1067. return 0;
  1068. }
  1069. static void
  1070. GLES2_SetBlendMode(GLES2_DriverContext *data, int blendMode)
  1071. {
  1072. if (blendMode != data->current.blendMode) {
  1073. switch (blendMode) {
  1074. default:
  1075. case SDL_BLENDMODE_NONE:
  1076. data->glDisable(GL_BLEND);
  1077. break;
  1078. case SDL_BLENDMODE_BLEND:
  1079. data->glEnable(GL_BLEND);
  1080. data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
  1081. break;
  1082. case SDL_BLENDMODE_ADD:
  1083. data->glEnable(GL_BLEND);
  1084. data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
  1085. break;
  1086. case SDL_BLENDMODE_MOD:
  1087. data->glEnable(GL_BLEND);
  1088. data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
  1089. break;
  1090. }
  1091. data->current.blendMode = blendMode;
  1092. }
  1093. }
  1094. static void
  1095. GLES2_SetTexCoords(GLES2_DriverContext * data, SDL_bool enabled)
  1096. {
  1097. if (enabled != data->current.tex_coords) {
  1098. if (enabled) {
  1099. data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1100. } else {
  1101. data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1102. }
  1103. data->current.tex_coords = enabled;
  1104. }
  1105. }
  1106. static int
  1107. GLES2_SetDrawingState(SDL_Renderer * renderer)
  1108. {
  1109. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1110. const int blendMode = renderer->blendMode;
  1111. GLES2_ProgramCacheEntry *program;
  1112. Uint8 r, g, b, a;
  1113. GLES2_ActivateRenderer(renderer);
  1114. GLES2_SetBlendMode(data, blendMode);
  1115. GLES2_SetTexCoords(data, SDL_FALSE);
  1116. /* Activate an appropriate shader and set the projection matrix */
  1117. if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0) {
  1118. return -1;
  1119. }
  1120. /* Select the color to draw with */
  1121. g = renderer->g;
  1122. a = renderer->a;
  1123. if (renderer->target &&
  1124. (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
  1125. renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
  1126. r = renderer->b;
  1127. b = renderer->r;
  1128. } else {
  1129. r = renderer->r;
  1130. b = renderer->b;
  1131. }
  1132. program = data->current_program;
  1133. if (!CompareColors(program->color_r, program->color_g, program->color_b, program->color_a, r, g, b, a)) {
  1134. /* Select the color to draw with */
  1135. data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  1136. program->color_r = r;
  1137. program->color_g = g;
  1138. program->color_b = b;
  1139. program->color_a = a;
  1140. }
  1141. return 0;
  1142. }
  1143. static int
  1144. GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
  1145. {
  1146. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1147. GLfloat *vertices;
  1148. int idx;
  1149. if (GLES2_SetDrawingState(renderer) < 0) {
  1150. return -1;
  1151. }
  1152. /* Emit the specified vertices as points */
  1153. vertices = SDL_stack_alloc(GLfloat, count * 2);
  1154. for (idx = 0; idx < count; ++idx) {
  1155. GLfloat x = points[idx].x + 0.5f;
  1156. GLfloat y = points[idx].y + 0.5f;
  1157. vertices[idx * 2] = x;
  1158. vertices[(idx * 2) + 1] = y;
  1159. }
  1160. data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  1161. data->glDrawArrays(GL_POINTS, 0, count);
  1162. SDL_stack_free(vertices);
  1163. return 0;
  1164. }
  1165. static int
  1166. GLES2_RenderDrawLines(SDL_Renderer *renderer, const SDL_FPoint *points, int count)
  1167. {
  1168. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1169. GLfloat *vertices;
  1170. int idx;
  1171. if (GLES2_SetDrawingState(renderer) < 0) {
  1172. return -1;
  1173. }
  1174. /* Emit a line strip including the specified vertices */
  1175. vertices = SDL_stack_alloc(GLfloat, count * 2);
  1176. for (idx = 0; idx < count; ++idx) {
  1177. GLfloat x = points[idx].x + 0.5f;
  1178. GLfloat y = points[idx].y + 0.5f;
  1179. vertices[idx * 2] = x;
  1180. vertices[(idx * 2) + 1] = y;
  1181. }
  1182. data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  1183. data->glDrawArrays(GL_LINE_STRIP, 0, count);
  1184. /* We need to close the endpoint of the line */
  1185. if (count == 2 ||
  1186. points[0].x != points[count-1].x || points[0].y != points[count-1].y) {
  1187. data->glDrawArrays(GL_POINTS, count-1, 1);
  1188. }
  1189. SDL_stack_free(vertices);
  1190. return GL_CheckError("", renderer);
  1191. }
  1192. static int
  1193. GLES2_RenderFillRects(SDL_Renderer *renderer, const SDL_FRect *rects, int count)
  1194. {
  1195. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1196. GLfloat vertices[8];
  1197. int idx;
  1198. if (GLES2_SetDrawingState(renderer) < 0) {
  1199. return -1;
  1200. }
  1201. /* Emit a line loop for each rectangle */
  1202. for (idx = 0; idx < count; ++idx) {
  1203. const SDL_FRect *rect = &rects[idx];
  1204. GLfloat xMin = rect->x;
  1205. GLfloat xMax = (rect->x + rect->w);
  1206. GLfloat yMin = rect->y;
  1207. GLfloat yMax = (rect->y + rect->h);
  1208. vertices[0] = xMin;
  1209. vertices[1] = yMin;
  1210. vertices[2] = xMax;
  1211. vertices[3] = yMin;
  1212. vertices[4] = xMin;
  1213. vertices[5] = yMax;
  1214. vertices[6] = xMax;
  1215. vertices[7] = yMax;
  1216. data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  1217. data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1218. }
  1219. return GL_CheckError("", renderer);
  1220. }
  1221. static int
  1222. GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  1223. const SDL_FRect *dstrect)
  1224. {
  1225. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1226. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1227. GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1228. SDL_BlendMode blendMode;
  1229. GLfloat vertices[8];
  1230. GLfloat texCoords[8];
  1231. GLES2_ProgramCacheEntry *program;
  1232. Uint8 r, g, b, a;
  1233. GLES2_ActivateRenderer(renderer);
  1234. /* Activate an appropriate shader and set the projection matrix */
  1235. blendMode = texture->blendMode;
  1236. if (renderer->target) {
  1237. /* Check if we need to do color mapping between the source and render target textures */
  1238. if (renderer->target->format != texture->format) {
  1239. switch (texture->format)
  1240. {
  1241. case SDL_PIXELFORMAT_ARGB8888:
  1242. switch (renderer->target->format)
  1243. {
  1244. case SDL_PIXELFORMAT_ABGR8888:
  1245. case SDL_PIXELFORMAT_BGR888:
  1246. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1247. break;
  1248. case SDL_PIXELFORMAT_RGB888:
  1249. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1250. break;
  1251. }
  1252. break;
  1253. case SDL_PIXELFORMAT_ABGR8888:
  1254. switch (renderer->target->format)
  1255. {
  1256. case SDL_PIXELFORMAT_ARGB8888:
  1257. case SDL_PIXELFORMAT_RGB888:
  1258. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1259. break;
  1260. case SDL_PIXELFORMAT_BGR888:
  1261. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1262. break;
  1263. }
  1264. break;
  1265. case SDL_PIXELFORMAT_RGB888:
  1266. switch (renderer->target->format)
  1267. {
  1268. case SDL_PIXELFORMAT_ABGR8888:
  1269. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1270. break;
  1271. case SDL_PIXELFORMAT_ARGB8888:
  1272. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1273. break;
  1274. case SDL_PIXELFORMAT_BGR888:
  1275. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1276. break;
  1277. }
  1278. break;
  1279. case SDL_PIXELFORMAT_BGR888:
  1280. switch (renderer->target->format)
  1281. {
  1282. case SDL_PIXELFORMAT_ABGR8888:
  1283. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1284. break;
  1285. case SDL_PIXELFORMAT_ARGB8888:
  1286. sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1287. break;
  1288. case SDL_PIXELFORMAT_RGB888:
  1289. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1290. break;
  1291. }
  1292. break;
  1293. }
  1294. }
  1295. else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
  1296. }
  1297. else {
  1298. switch (texture->format)
  1299. {
  1300. case SDL_PIXELFORMAT_ARGB8888:
  1301. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1302. break;
  1303. case SDL_PIXELFORMAT_ABGR8888:
  1304. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1305. break;
  1306. case SDL_PIXELFORMAT_RGB888:
  1307. sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1308. break;
  1309. case SDL_PIXELFORMAT_BGR888:
  1310. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1311. break;
  1312. // TODO: new shader to change yv planes YV12 format
  1313. case SDL_PIXELFORMAT_IYUV:
  1314. case SDL_PIXELFORMAT_YV12:
  1315. sourceType = GLES2_IMAGESOURCE_TEXTURE_YUV;
  1316. break;
  1317. default:
  1318. return -1;
  1319. }
  1320. }
  1321. if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) {
  1322. return -1;
  1323. }
  1324. /* Select the target texture */
  1325. if (tdata->yuv) {
  1326. data->glActiveTexture(GL_TEXTURE2);
  1327. data->glBindTexture(tdata->texture_type, tdata->texture_v);
  1328. data->glActiveTexture(GL_TEXTURE1);
  1329. data->glBindTexture(tdata->texture_type, tdata->texture_u);
  1330. data->glActiveTexture(GL_TEXTURE0);
  1331. }
  1332. data->glBindTexture(tdata->texture_type, tdata->texture);
  1333. /* Configure color modulation */
  1334. g = texture->g;
  1335. a = texture->a;
  1336. if (renderer->target &&
  1337. (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
  1338. renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
  1339. r = texture->b;
  1340. b = texture->r;
  1341. } else {
  1342. r = texture->r;
  1343. b = texture->b;
  1344. }
  1345. program = data->current_program;
  1346. if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
  1347. data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  1348. program->modulation_r = r;
  1349. program->modulation_g = g;
  1350. program->modulation_b = b;
  1351. program->modulation_a = a;
  1352. }
  1353. /* Configure texture blending */
  1354. GLES2_SetBlendMode(data, blendMode);
  1355. GLES2_SetTexCoords(data, SDL_TRUE);
  1356. /* Emit the textured quad */
  1357. vertices[0] = dstrect->x;
  1358. vertices[1] = dstrect->y;
  1359. vertices[2] = (dstrect->x + dstrect->w);
  1360. vertices[3] = dstrect->y;
  1361. vertices[4] = dstrect->x;
  1362. vertices[5] = (dstrect->y + dstrect->h);
  1363. vertices[6] = (dstrect->x + dstrect->w);
  1364. vertices[7] = (dstrect->y + dstrect->h);
  1365. data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  1366. texCoords[0] = srcrect->x / (GLfloat)texture->w;
  1367. texCoords[1] = srcrect->y / (GLfloat)texture->h;
  1368. texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1369. texCoords[3] = srcrect->y / (GLfloat)texture->h;
  1370. texCoords[4] = srcrect->x / (GLfloat)texture->w;
  1371. texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1372. texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1373. texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1374. data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
  1375. data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1376. return GL_CheckError("", renderer);
  1377. }
  1378. static int
  1379. GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
  1380. const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
  1381. {
  1382. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1383. GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
  1384. GLES2_ImageSource sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1385. GLES2_ProgramCacheEntry *program;
  1386. Uint8 r, g, b, a;
  1387. SDL_BlendMode blendMode;
  1388. GLfloat vertices[8];
  1389. GLfloat texCoords[8];
  1390. GLfloat translate[8];
  1391. GLfloat fAngle[4];
  1392. GLfloat tmp;
  1393. GLES2_ActivateRenderer(renderer);
  1394. data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
  1395. data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
  1396. fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
  1397. /* Calculate the center of rotation */
  1398. translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
  1399. translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
  1400. /* Activate an appropriate shader and set the projection matrix */
  1401. blendMode = texture->blendMode;
  1402. if (renderer->target) {
  1403. /* Check if we need to do color mapping between the source and render target textures */
  1404. if (renderer->target->format != texture->format) {
  1405. switch (texture->format)
  1406. {
  1407. case SDL_PIXELFORMAT_ARGB8888:
  1408. switch (renderer->target->format)
  1409. {
  1410. case SDL_PIXELFORMAT_ABGR8888:
  1411. case SDL_PIXELFORMAT_BGR888:
  1412. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1413. break;
  1414. case SDL_PIXELFORMAT_RGB888:
  1415. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1416. break;
  1417. }
  1418. break;
  1419. case SDL_PIXELFORMAT_ABGR8888:
  1420. switch (renderer->target->format)
  1421. {
  1422. case SDL_PIXELFORMAT_ARGB8888:
  1423. case SDL_PIXELFORMAT_RGB888:
  1424. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1425. break;
  1426. case SDL_PIXELFORMAT_BGR888:
  1427. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1428. break;
  1429. }
  1430. break;
  1431. case SDL_PIXELFORMAT_RGB888:
  1432. switch (renderer->target->format)
  1433. {
  1434. case SDL_PIXELFORMAT_ABGR8888:
  1435. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1436. break;
  1437. case SDL_PIXELFORMAT_ARGB8888:
  1438. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1439. break;
  1440. case SDL_PIXELFORMAT_BGR888:
  1441. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1442. break;
  1443. }
  1444. break;
  1445. case SDL_PIXELFORMAT_BGR888:
  1446. switch (renderer->target->format)
  1447. {
  1448. case SDL_PIXELFORMAT_ABGR8888:
  1449. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1450. break;
  1451. case SDL_PIXELFORMAT_ARGB8888:
  1452. sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1453. break;
  1454. case SDL_PIXELFORMAT_RGB888:
  1455. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1456. break;
  1457. }
  1458. break;
  1459. }
  1460. }
  1461. else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */
  1462. }
  1463. else {
  1464. switch (texture->format)
  1465. {
  1466. case SDL_PIXELFORMAT_ARGB8888:
  1467. sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB;
  1468. break;
  1469. case SDL_PIXELFORMAT_ABGR8888:
  1470. sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR;
  1471. break;
  1472. case SDL_PIXELFORMAT_RGB888:
  1473. sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB;
  1474. break;
  1475. case SDL_PIXELFORMAT_BGR888:
  1476. sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR;
  1477. break;
  1478. default:
  1479. return -1;
  1480. }
  1481. }
  1482. if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
  1483. return -1;
  1484. /* Select the target texture */
  1485. data->glBindTexture(tdata->texture_type, tdata->texture);
  1486. /* Configure color modulation */
  1487. /* !!! FIXME: grep for glUniform4f(), move that stuff to a subroutine, it's a lot of copy/paste. */
  1488. g = texture->g;
  1489. a = texture->a;
  1490. if (renderer->target &&
  1491. (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 ||
  1492. renderer->target->format == SDL_PIXELFORMAT_RGB888)) {
  1493. r = texture->b;
  1494. b = texture->r;
  1495. } else {
  1496. r = texture->r;
  1497. b = texture->b;
  1498. }
  1499. program = data->current_program;
  1500. if (!CompareColors(program->modulation_r, program->modulation_g, program->modulation_b, program->modulation_a, r, g, b, a)) {
  1501. data->glUniform4f(program->uniform_locations[GLES2_UNIFORM_MODULATION], r * inv255f, g * inv255f, b * inv255f, a * inv255f);
  1502. program->modulation_r = r;
  1503. program->modulation_g = g;
  1504. program->modulation_b = b;
  1505. program->modulation_a = a;
  1506. }
  1507. /* Configure texture blending */
  1508. GLES2_SetBlendMode(data, blendMode);
  1509. GLES2_SetTexCoords(data, SDL_TRUE);
  1510. /* Emit the textured quad */
  1511. vertices[0] = dstrect->x;
  1512. vertices[1] = dstrect->y;
  1513. vertices[2] = (dstrect->x + dstrect->w);
  1514. vertices[3] = dstrect->y;
  1515. vertices[4] = dstrect->x;
  1516. vertices[5] = (dstrect->y + dstrect->h);
  1517. vertices[6] = (dstrect->x + dstrect->w);
  1518. vertices[7] = (dstrect->y + dstrect->h);
  1519. if (flip & SDL_FLIP_HORIZONTAL) {
  1520. tmp = vertices[0];
  1521. vertices[0] = vertices[4] = vertices[2];
  1522. vertices[2] = vertices[6] = tmp;
  1523. }
  1524. if (flip & SDL_FLIP_VERTICAL) {
  1525. tmp = vertices[1];
  1526. vertices[1] = vertices[3] = vertices[5];
  1527. vertices[5] = vertices[7] = tmp;
  1528. }
  1529. data->glVertexAttribPointer(GLES2_ATTRIBUTE_ANGLE, 1, GL_FLOAT, GL_FALSE, 0, &fAngle);
  1530. data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
  1531. data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
  1532. texCoords[0] = srcrect->x / (GLfloat)texture->w;
  1533. texCoords[1] = srcrect->y / (GLfloat)texture->h;
  1534. texCoords[2] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1535. texCoords[3] = srcrect->y / (GLfloat)texture->h;
  1536. texCoords[4] = srcrect->x / (GLfloat)texture->w;
  1537. texCoords[5] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1538. texCoords[6] = (srcrect->x + srcrect->w) / (GLfloat)texture->w;
  1539. texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
  1540. data->glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
  1541. data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  1542. data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
  1543. data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
  1544. return GL_CheckError("", renderer);
  1545. }
  1546. static int
  1547. GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
  1548. Uint32 pixel_format, void * pixels, int pitch)
  1549. {
  1550. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1551. Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
  1552. void *temp_pixels;
  1553. int temp_pitch;
  1554. Uint8 *src, *dst, *tmp;
  1555. int w, h, length, rows;
  1556. int status;
  1557. GLES2_ActivateRenderer(renderer);
  1558. temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format);
  1559. temp_pixels = SDL_malloc(rect->h * temp_pitch);
  1560. if (!temp_pixels) {
  1561. return SDL_OutOfMemory();
  1562. }
  1563. SDL_GetRendererOutputSize(renderer, &w, &h);
  1564. data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
  1565. GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
  1566. if (GL_CheckError("glReadPixels()", renderer) < 0) {
  1567. return -1;
  1568. }
  1569. /* Flip the rows to be top-down */
  1570. length = rect->w * SDL_BYTESPERPIXEL(temp_format);
  1571. src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
  1572. dst = (Uint8*)temp_pixels;
  1573. tmp = SDL_stack_alloc(Uint8, length);
  1574. rows = rect->h / 2;
  1575. while (rows--) {
  1576. SDL_memcpy(tmp, dst, length);
  1577. SDL_memcpy(dst, src, length);
  1578. SDL_memcpy(src, tmp, length);
  1579. dst += temp_pitch;
  1580. src -= temp_pitch;
  1581. }
  1582. SDL_stack_free(tmp);
  1583. status = SDL_ConvertPixels(rect->w, rect->h,
  1584. temp_format, temp_pixels, temp_pitch,
  1585. pixel_format, pixels, pitch);
  1586. SDL_free(temp_pixels);
  1587. return status;
  1588. }
  1589. static void
  1590. GLES2_RenderPresent(SDL_Renderer *renderer)
  1591. {
  1592. GLES2_ActivateRenderer(renderer);
  1593. /* Tell the video driver to swap buffers */
  1594. SDL_GL_SwapWindow(renderer->window);
  1595. }
  1596. /*************************************************************************************************
  1597. * Bind/unbinding of textures
  1598. *************************************************************************************************/
  1599. static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh);
  1600. static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture);
  1601. static int GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh)
  1602. {
  1603. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1604. GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  1605. GLES2_ActivateRenderer(renderer);
  1606. data->glBindTexture(texturedata->texture_type, texturedata->texture);
  1607. if(texw) *texw = 1.0;
  1608. if(texh) *texh = 1.0;
  1609. return 0;
  1610. }
  1611. static int GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture)
  1612. {
  1613. GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
  1614. GLES2_TextureData *texturedata = (GLES2_TextureData *)texture->driverdata;
  1615. GLES2_ActivateRenderer(renderer);
  1616. data->glBindTexture(texturedata->texture_type, 0);
  1617. return 0;
  1618. }
  1619. /*************************************************************************************************
  1620. * Renderer instantiation *
  1621. *************************************************************************************************/
  1622. #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
  1623. static void
  1624. GLES2_ResetState(SDL_Renderer *renderer)
  1625. {
  1626. GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata;
  1627. if (SDL_CurrentContext == data->context) {
  1628. GLES2_UpdateViewport(renderer);
  1629. } else {
  1630. GLES2_ActivateRenderer(renderer);
  1631. }
  1632. data->current.blendMode = -1;
  1633. data->current.tex_coords = SDL_FALSE;
  1634. data->glActiveTexture(GL_TEXTURE0);
  1635. data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
  1636. data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  1637. data->glClearColor((GLfloat) data->clear_r * inv255f,
  1638. (GLfloat) data->clear_g * inv255f,
  1639. (GLfloat) data->clear_b * inv255f,
  1640. (GLfloat) data->clear_a * inv255f);
  1641. data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
  1642. data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
  1643. GL_CheckError("", renderer);
  1644. }
  1645. static SDL_Renderer *
  1646. GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
  1647. {
  1648. SDL_Renderer *renderer;
  1649. GLES2_DriverContext *data;
  1650. GLint nFormats;
  1651. #ifndef ZUNE_HD
  1652. GLboolean hasCompiler;
  1653. #endif
  1654. Uint32 window_flags;
  1655. GLint window_framebuffer;
  1656. GLint value;
  1657. int profile_mask, major, minor;
  1658. SDL_bool changed_window = SDL_FALSE;
  1659. SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
  1660. SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
  1661. SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
  1662. window_flags = SDL_GetWindowFlags(window);
  1663. if (!(window_flags & SDL_WINDOW_OPENGL) ||
  1664. profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) {
  1665. changed_window = SDL_TRUE;
  1666. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
  1667. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR);
  1668. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR);
  1669. if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) {
  1670. goto error;
  1671. }
  1672. }
  1673. /* Create the renderer struct */
  1674. renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer));
  1675. if (!renderer) {
  1676. SDL_OutOfMemory();
  1677. goto error;
  1678. }
  1679. data = (GLES2_DriverContext *)SDL_calloc(1, sizeof(GLES2_DriverContext));
  1680. if (!data) {
  1681. GLES2_DestroyRenderer(renderer);
  1682. SDL_OutOfMemory();
  1683. goto error;
  1684. }
  1685. renderer->info = GLES2_RenderDriver.info;
  1686. renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
  1687. renderer->driverdata = data;
  1688. renderer->window = window;
  1689. /* Create an OpenGL ES 2.0 context */
  1690. data->context = SDL_GL_CreateContext(window);
  1691. if (!data->context) {
  1692. GLES2_DestroyRenderer(renderer);
  1693. goto error;
  1694. }
  1695. if (SDL_GL_MakeCurrent(window, data->context) < 0) {
  1696. GLES2_DestroyRenderer(renderer);
  1697. goto error;
  1698. }
  1699. if (GLES2_LoadFunctions(data) < 0) {
  1700. GLES2_DestroyRenderer(renderer);
  1701. goto error;
  1702. }
  1703. #if __WINRT__
  1704. /* DLudwig, 2013-11-29: ANGLE for WinRT doesn't seem to work unless VSync
  1705. * is turned on. Not doing so will freeze the screen's contents to that
  1706. * of the first drawn frame.
  1707. */
  1708. flags |= SDL_RENDERER_PRESENTVSYNC;
  1709. #endif
  1710. if (flags & SDL_RENDERER_PRESENTVSYNC) {
  1711. SDL_GL_SetSwapInterval(1);
  1712. } else {
  1713. SDL_GL_SetSwapInterval(0);
  1714. }
  1715. if (SDL_GL_GetSwapInterval() > 0) {
  1716. renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
  1717. }
  1718. /* Check for debug output support */
  1719. if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 &&
  1720. (value & SDL_GL_CONTEXT_DEBUG_FLAG)) {
  1721. data->debug_enabled = SDL_TRUE;
  1722. }
  1723. value = 0;
  1724. data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  1725. renderer->info.max_texture_width = value;
  1726. value = 0;
  1727. data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
  1728. renderer->info.max_texture_height = value;
  1729. /* Determine supported shader formats */
  1730. /* HACK: glGetInteger is broken on the Zune HD's compositor, so we just hardcode this */
  1731. #ifdef ZUNE_HD
  1732. nFormats = 1;
  1733. #else /* !ZUNE_HD */
  1734. data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats);
  1735. data->glGetBooleanv(GL_SHADER_COMPILER, &hasCompiler);
  1736. if (hasCompiler)
  1737. ++nFormats;
  1738. #endif /* ZUNE_HD */
  1739. data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum));
  1740. if (!data->shader_formats)
  1741. {
  1742. GLES2_DestroyRenderer(renderer);
  1743. SDL_OutOfMemory();
  1744. goto error;
  1745. }
  1746. data->shader_format_count = nFormats;
  1747. #ifdef ZUNE_HD
  1748. data->shader_formats[0] = GL_NVIDIA_PLATFORM_BINARY_NV;
  1749. #else /* !ZUNE_HD */
  1750. data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats);
  1751. if (hasCompiler)
  1752. data->shader_formats[nFormats - 1] = (GLenum)-1;
  1753. #endif /* ZUNE_HD */
  1754. data->framebuffers = NULL;
  1755. data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer);
  1756. data->window_framebuffer = (GLuint)window_framebuffer;
  1757. /* Populate the function pointers for the module */
  1758. renderer->WindowEvent = &GLES2_WindowEvent;
  1759. renderer->CreateTexture = &GLES2_CreateTexture;
  1760. renderer->UpdateTexture = &GLES2_UpdateTexture;
  1761. renderer->UpdateTextureYUV = &GLES2_UpdateTextureYUV;
  1762. renderer->LockTexture = &GLES2_LockTexture;
  1763. renderer->UnlockTexture = &GLES2_UnlockTexture;
  1764. renderer->SetRenderTarget = &GLES2_SetRenderTarget;
  1765. renderer->UpdateViewport = &GLES2_UpdateViewport;
  1766. renderer->UpdateClipRect = &GLES2_UpdateClipRect;
  1767. renderer->RenderClear = &GLES2_RenderClear;
  1768. renderer->RenderDrawPoints = &GLES2_RenderDrawPoints;
  1769. renderer->RenderDrawLines = &GLES2_RenderDrawLines;
  1770. renderer->RenderFillRects = &GLES2_RenderFillRects;
  1771. renderer->RenderCopy = &GLES2_RenderCopy;
  1772. renderer->RenderCopyEx = &GLES2_RenderCopyEx;
  1773. renderer->RenderReadPixels = &GLES2_RenderReadPixels;
  1774. renderer->RenderPresent = &GLES2_RenderPresent;
  1775. renderer->DestroyTexture = &GLES2_DestroyTexture;
  1776. renderer->DestroyRenderer = &GLES2_DestroyRenderer;
  1777. renderer->GL_BindTexture = &GLES2_BindTexture;
  1778. renderer->GL_UnbindTexture = &GLES2_UnbindTexture;
  1779. renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12;
  1780. renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV;
  1781. GLES2_ResetState(renderer);
  1782. return renderer;
  1783. error:
  1784. if (changed_window) {
  1785. /* Uh oh, better try to put it back... */
  1786. SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask);
  1787. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
  1788. SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
  1789. SDL_RecreateWindow(window, window_flags);
  1790. }
  1791. return NULL;
  1792. }
  1793. #endif /* SDL_VIDEO_RENDER_OGL_ES2 && !SDL_RENDER_DISABLED */
  1794. /* vi: set ts=4 sw=4 expandtab: */