1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | #include "../../SDL_internal.h" |
22 | |
23 | #if SDL_VIDEO_RENDER_VITA_GLES2 && !SDL_RENDER_DISABLED |
24 | |
25 | #include "SDL_assert.h" |
26 | #include "SDL_hints.h" |
27 | #include "SDL_opengles2.h" |
28 | #include "../SDL_sysrender.h" |
29 | #include "../../video/SDL_blit.h" |
30 | #include "SDL_shaders_gles2vita.h" |
31 | |
32 | //#include <psp2/gxm.h> |
33 | //#include <psp2/types.h> |
34 | //#include <psp2/kernel/sysmem.h> |
35 | |
36 | /* To prevent unnecessary window recreation, |
37 | * these should match the defaults selected in SDL_GL_ResetAttributes |
38 | */ |
39 | #define RENDERER_CONTEXT_MAJOR 2 |
40 | #define RENDERER_CONTEXT_MINOR 0 |
41 | |
42 | /* Used to re-create the window with OpenGL ES capability */ |
43 | extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); |
44 | |
45 | /************************************************************************************************* |
46 | * Context structures * |
47 | *************************************************************************************************/ |
48 | |
49 | typedef struct VITA_GLES2_FBOList VITA_GLES2_FBOList; |
50 | |
51 | struct VITA_GLES2_FBOList |
52 | { |
53 | Uint32 w, h; |
54 | GLuint FBO; |
55 | VITA_GLES2_FBOList *next; |
56 | }; |
57 | |
58 | typedef struct VITA_GLES2_TextureData |
59 | { |
60 | GLenum texture; |
61 | GLenum texture_type; |
62 | GLenum pixel_format; |
63 | GLenum pixel_type; |
64 | void *pixel_data; |
65 | int pitch; |
66 | /* YUV texture support */ |
67 | SDL_bool yuv; |
68 | SDL_bool nv12; |
69 | GLenum texture_v; |
70 | GLenum texture_u; |
71 | VITA_GLES2_FBOList *fbo; |
72 | } VITA_GLES2_TextureData; |
73 | |
74 | typedef struct VITA_GLES2_ShaderCacheEntry |
75 | { |
76 | GLuint id; |
77 | VITA_GLES2_ShaderType type; |
78 | const VITA_GLES2_ShaderInstance *instance; |
79 | int references; |
80 | struct VITA_GLES2_ShaderCacheEntry *prev; |
81 | struct VITA_GLES2_ShaderCacheEntry *next; |
82 | } VITA_GLES2_ShaderCacheEntry; |
83 | |
84 | typedef struct VITA_GLES2_ShaderCache |
85 | { |
86 | int count; |
87 | VITA_GLES2_ShaderCacheEntry *head; |
88 | } VITA_GLES2_ShaderCache; |
89 | |
90 | typedef struct VITA_GLES2_ProgramCacheEntry |
91 | { |
92 | GLuint id; |
93 | VITA_GLES2_ShaderCacheEntry *vertex_shader; |
94 | VITA_GLES2_ShaderCacheEntry *fragment_shader; |
95 | GLuint uniform_locations[16]; |
96 | Uint32 color; |
97 | GLfloat projection[4][4]; |
98 | struct VITA_GLES2_ProgramCacheEntry *prev; |
99 | struct VITA_GLES2_ProgramCacheEntry *next; |
100 | } VITA_GLES2_ProgramCacheEntry; |
101 | |
102 | typedef struct VITA_GLES2_ProgramCache |
103 | { |
104 | int count; |
105 | VITA_GLES2_ProgramCacheEntry *head; |
106 | VITA_GLES2_ProgramCacheEntry *tail; |
107 | } VITA_GLES2_ProgramCache; |
108 | |
109 | typedef enum |
110 | { |
111 | VITA_GLES2_ATTRIBUTE_POSITION = 0, |
112 | VITA_GLES2_ATTRIBUTE_TEXCOORD = 1, |
113 | VITA_GLES2_ATTRIBUTE_ANGLE = 2, |
114 | VITA_GLES2_ATTRIBUTE_CENTER = 3, |
115 | } VITA_GLES2_Attribute; |
116 | |
117 | typedef enum |
118 | { |
119 | VITA_GLES2_UNIFORM_PROJECTION, |
120 | VITA_GLES2_UNIFORM_TEXTURE, |
121 | VITA_GLES2_UNIFORM_COLOR, |
122 | VITA_GLES2_UNIFORM_TEXTURE_U, |
123 | VITA_GLES2_UNIFORM_TEXTURE_V |
124 | } VITA_GLES2_Uniform; |
125 | |
126 | typedef enum |
127 | { |
128 | VITA_GLES2_IMAGESOURCE_INVALID, |
129 | VITA_GLES2_IMAGESOURCE_SOLID, |
130 | VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR, |
131 | VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB, |
132 | VITA_GLES2_IMAGESOURCE_TEXTURE_RGB, |
133 | VITA_GLES2_IMAGESOURCE_TEXTURE_BGR, |
134 | VITA_GLES2_IMAGESOURCE_TEXTURE_YUV, |
135 | VITA_GLES2_IMAGESOURCE_TEXTURE_NV12, |
136 | VITA_GLES2_IMAGESOURCE_TEXTURE_NV21, |
137 | VITA_GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES |
138 | } VITA_GLES2_ImageSource; |
139 | |
140 | typedef struct |
141 | { |
142 | SDL_Rect viewport; |
143 | SDL_bool viewport_dirty; |
144 | SDL_Texture *texture; |
145 | SDL_Texture *target; |
146 | SDL_BlendMode blend; |
147 | SDL_bool cliprect_enabled_dirty; |
148 | SDL_bool cliprect_enabled; |
149 | SDL_bool cliprect_dirty; |
150 | SDL_Rect cliprect; |
151 | SDL_bool texturing; |
152 | SDL_bool is_copy_ex; |
153 | Uint32 color; |
154 | Uint32 clear_color; |
155 | int drawablew; |
156 | int drawableh; |
157 | VITA_GLES2_ProgramCacheEntry *program; |
158 | GLfloat projection[4][4]; |
159 | } VITA_GLES2_DrawStateCache; |
160 | |
161 | typedef struct VITA_GLES2_RenderData |
162 | { |
163 | SDL_GLContext *context; |
164 | |
165 | SDL_bool debug_enabled; |
166 | |
167 | #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; |
168 | #include "SDL_gles2funcs.h" |
169 | #undef SDL_PROC |
170 | |
171 | VITA_GLES2_FBOList *framebuffers; |
172 | GLuint window_framebuffer; |
173 | |
174 | int shader_format_count; |
175 | GLenum *shader_formats; |
176 | VITA_GLES2_ShaderCache shader_cache; |
177 | VITA_GLES2_ProgramCache program_cache; |
178 | Uint8 clear_r, clear_g, clear_b, clear_a; |
179 | |
180 | GLuint vertex_buffers[8]; |
181 | size_t vertex_buffer_size[8]; |
182 | int current_vertex_buffer; |
183 | VITA_GLES2_DrawStateCache drawstate; |
184 | } VITA_GLES2_RenderData; |
185 | |
186 | #define VITA_GLES2_MAX_CACHED_PROGRAMS 8 |
187 | |
188 | static const float inv255f = 1.0f / 255.0f; |
189 | |
190 | |
191 | SDL_FORCE_INLINE const char* |
192 | GL_TranslateError (GLenum error) |
193 | { |
194 | #define GL_ERROR_TRANSLATE(e) case e: return #e; |
195 | switch (error) { |
196 | GL_ERROR_TRANSLATE(GL_INVALID_ENUM) |
197 | GL_ERROR_TRANSLATE(GL_INVALID_VALUE) |
198 | GL_ERROR_TRANSLATE(GL_INVALID_OPERATION) |
199 | GL_ERROR_TRANSLATE(GL_OUT_OF_MEMORY) |
200 | GL_ERROR_TRANSLATE(GL_NO_ERROR) |
201 | default: |
202 | return "UNKNOWN" ; |
203 | } |
204 | #undef GL_ERROR_TRANSLATE |
205 | } |
206 | |
207 | SDL_FORCE_INLINE void |
208 | GL_ClearErrors(SDL_Renderer *renderer) |
209 | { |
210 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *) renderer->driverdata; |
211 | |
212 | if (!data->debug_enabled) { |
213 | return; |
214 | } |
215 | while (data->glGetError() != GL_NO_ERROR) { |
216 | /* continue; */ |
217 | } |
218 | } |
219 | |
220 | SDL_FORCE_INLINE int |
221 | GL_CheckAllErrors (const char *prefix, SDL_Renderer *renderer, const char *file, int line, const char *function) |
222 | { |
223 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *) renderer->driverdata; |
224 | int ret = 0; |
225 | |
226 | if (!data->debug_enabled) { |
227 | return 0; |
228 | } |
229 | /* check gl errors (can return multiple errors) */ |
230 | for (;;) { |
231 | GLenum error = data->glGetError(); |
232 | if (error != GL_NO_ERROR) { |
233 | if (prefix == NULL || prefix[0] == '\0') { |
234 | prefix = "generic" ; |
235 | } |
236 | SDL_SetError("%s: %s (%d): %s %s (0x%X)" , prefix, file, line, function, GL_TranslateError(error), error); |
237 | ret = -1; |
238 | } else { |
239 | break; |
240 | } |
241 | } |
242 | return ret; |
243 | } |
244 | |
245 | #if 0 |
246 | #define GL_CheckError(prefix, renderer) |
247 | #else |
248 | #define GL_CheckError(prefix, renderer) GL_CheckAllErrors(prefix, renderer, SDL_FILE, SDL_LINE, SDL_FUNCTION) |
249 | #endif |
250 | |
251 | /************************************************************************************************* |
252 | * Renderer state APIs * |
253 | *************************************************************************************************/ |
254 | |
255 | static int VITA_GLES2_LoadFunctions(VITA_GLES2_RenderData * data) |
256 | { |
257 | #define SDL_PROC(ret,func,params) data->func=func; |
258 | #include "SDL_gles2funcs.h" |
259 | #undef SDL_PROC |
260 | return 0; |
261 | } |
262 | |
263 | static VITA_GLES2_FBOList * |
264 | VITA_GLES2_GetFBO(VITA_GLES2_RenderData *data, Uint32 w, Uint32 h) |
265 | { |
266 | VITA_GLES2_FBOList *result = data->framebuffers; |
267 | while ((result) && ((result->w != w) || (result->h != h)) ) { |
268 | result = result->next; |
269 | } |
270 | if (result == NULL) { |
271 | result = SDL_malloc(sizeof(VITA_GLES2_FBOList)); |
272 | result->w = w; |
273 | result->h = h; |
274 | data->glGenFramebuffers(1, &result->FBO); |
275 | result->next = data->framebuffers; |
276 | data->framebuffers = result; |
277 | } |
278 | return result; |
279 | } |
280 | |
281 | static int |
282 | VITA_GLES2_ActivateRenderer(SDL_Renderer * renderer) |
283 | { |
284 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
285 | |
286 | if (SDL_GL_GetCurrentContext() != data->context) { |
287 | /* Null out the current program to ensure we set it again */ |
288 | data->drawstate.program = NULL; |
289 | |
290 | if (SDL_GL_MakeCurrent(renderer->window, data->context) < 0) { |
291 | return -1; |
292 | } |
293 | } |
294 | |
295 | GL_ClearErrors(renderer); |
296 | |
297 | return 0; |
298 | } |
299 | |
300 | static void |
301 | VITA_GLES2_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) |
302 | { |
303 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
304 | |
305 | if (event->event == SDL_WINDOWEVENT_MINIMIZED) { |
306 | /* According to Apple documentation, we need to finish drawing NOW! */ |
307 | data->glFinish(); |
308 | } |
309 | } |
310 | |
311 | static int |
312 | VITA_GLES2_GetOutputSize(SDL_Renderer * renderer, int *w, int *h) |
313 | { |
314 | SDL_GL_GetDrawableSize(renderer->window, w, h); |
315 | return 0; |
316 | } |
317 | |
318 | static GLenum GetBlendFunc(SDL_BlendFactor factor) |
319 | { |
320 | switch (factor) { |
321 | case SDL_BLENDFACTOR_ZERO: |
322 | return GL_ZERO; |
323 | case SDL_BLENDFACTOR_ONE: |
324 | return GL_ONE; |
325 | case SDL_BLENDFACTOR_SRC_COLOR: |
326 | return GL_SRC_COLOR; |
327 | case SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR: |
328 | return GL_ONE_MINUS_SRC_COLOR; |
329 | case SDL_BLENDFACTOR_SRC_ALPHA: |
330 | return GL_SRC_ALPHA; |
331 | case SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA: |
332 | return GL_ONE_MINUS_SRC_ALPHA; |
333 | case SDL_BLENDFACTOR_DST_COLOR: |
334 | return GL_DST_COLOR; |
335 | case SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR: |
336 | return GL_ONE_MINUS_DST_COLOR; |
337 | case SDL_BLENDFACTOR_DST_ALPHA: |
338 | return GL_DST_ALPHA; |
339 | case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA: |
340 | return GL_ONE_MINUS_DST_ALPHA; |
341 | default: |
342 | return GL_INVALID_ENUM; |
343 | } |
344 | } |
345 | |
346 | static GLenum GetBlendEquation(SDL_BlendOperation operation) |
347 | { |
348 | switch (operation) { |
349 | case SDL_BLENDOPERATION_ADD: |
350 | return GL_FUNC_ADD; |
351 | case SDL_BLENDOPERATION_SUBTRACT: |
352 | return GL_FUNC_SUBTRACT; |
353 | case SDL_BLENDOPERATION_REV_SUBTRACT: |
354 | return GL_FUNC_REVERSE_SUBTRACT; |
355 | default: |
356 | return GL_INVALID_ENUM; |
357 | } |
358 | } |
359 | |
360 | static SDL_bool |
361 | VITA_GLES2_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) |
362 | { |
363 | SDL_BlendFactor srcColorFactor = SDL_GetBlendModeSrcColorFactor(blendMode); |
364 | SDL_BlendFactor srcAlphaFactor = SDL_GetBlendModeSrcAlphaFactor(blendMode); |
365 | SDL_BlendOperation colorOperation = SDL_GetBlendModeColorOperation(blendMode); |
366 | SDL_BlendFactor dstColorFactor = SDL_GetBlendModeDstColorFactor(blendMode); |
367 | SDL_BlendFactor dstAlphaFactor = SDL_GetBlendModeDstAlphaFactor(blendMode); |
368 | SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode); |
369 | |
370 | if (GetBlendFunc(srcColorFactor) == GL_INVALID_ENUM || |
371 | GetBlendFunc(srcAlphaFactor) == GL_INVALID_ENUM || |
372 | GetBlendEquation(colorOperation) == GL_INVALID_ENUM || |
373 | GetBlendFunc(dstColorFactor) == GL_INVALID_ENUM || |
374 | GetBlendFunc(dstAlphaFactor) == GL_INVALID_ENUM || |
375 | GetBlendEquation(alphaOperation) == GL_INVALID_ENUM) { |
376 | return SDL_FALSE; |
377 | } |
378 | return SDL_TRUE; |
379 | } |
380 | |
381 | |
382 | static void |
383 | VITA_GLES2_EvictShader(VITA_GLES2_RenderData *data, VITA_GLES2_ShaderCacheEntry *entry) |
384 | { |
385 | /* Unlink the shader from the cache */ |
386 | if (entry->next) { |
387 | entry->next->prev = entry->prev; |
388 | } |
389 | if (entry->prev) { |
390 | entry->prev->next = entry->next; |
391 | } |
392 | if (data->shader_cache.head == entry) { |
393 | data->shader_cache.head = entry->next; |
394 | } |
395 | --data->shader_cache.count; |
396 | |
397 | /* Deallocate the shader */ |
398 | data->glDeleteShader(entry->id); |
399 | SDL_free(entry); |
400 | } |
401 | |
402 | static VITA_GLES2_ProgramCacheEntry * |
403 | VITA_GLES2_CacheProgram(VITA_GLES2_RenderData *data, VITA_GLES2_ShaderCacheEntry *vertex, |
404 | VITA_GLES2_ShaderCacheEntry *fragment) |
405 | { |
406 | VITA_GLES2_ProgramCacheEntry *entry; |
407 | VITA_GLES2_ShaderCacheEntry *shaderEntry; |
408 | GLint linkSuccessful; |
409 | |
410 | /* Check if we've already cached this program */ |
411 | entry = data->program_cache.head; |
412 | while (entry) { |
413 | if (entry->vertex_shader == vertex && entry->fragment_shader == fragment) { |
414 | break; |
415 | } |
416 | entry = entry->next; |
417 | } |
418 | if (entry) { |
419 | if (data->program_cache.head != entry) { |
420 | if (entry->next) { |
421 | entry->next->prev = entry->prev; |
422 | } |
423 | if (entry->prev) { |
424 | entry->prev->next = entry->next; |
425 | } |
426 | entry->prev = NULL; |
427 | entry->next = data->program_cache.head; |
428 | data->program_cache.head->prev = entry; |
429 | data->program_cache.head = entry; |
430 | } |
431 | return entry; |
432 | } |
433 | |
434 | /* Create a program cache entry */ |
435 | entry = (VITA_GLES2_ProgramCacheEntry *)SDL_calloc(1, sizeof(VITA_GLES2_ProgramCacheEntry)); |
436 | if (!entry) { |
437 | SDL_OutOfMemory(); |
438 | return NULL; |
439 | } |
440 | entry->vertex_shader = vertex; |
441 | entry->fragment_shader = fragment; |
442 | |
443 | /* Create the program and link it */ |
444 | entry->id = data->glCreateProgram(); |
445 | data->glAttachShader(entry->id, vertex->id); |
446 | data->glAttachShader(entry->id, fragment->id); |
447 | data->glBindAttribLocation(entry->id, VITA_GLES2_ATTRIBUTE_POSITION, "a_position" ); |
448 | data->glBindAttribLocation(entry->id, VITA_GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord" ); |
449 | data->glBindAttribLocation(entry->id, VITA_GLES2_ATTRIBUTE_ANGLE, "a_angle" ); |
450 | data->glBindAttribLocation(entry->id, VITA_GLES2_ATTRIBUTE_CENTER, "a_center" ); |
451 | data->glLinkProgram(entry->id); |
452 | data->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful); |
453 | if (!linkSuccessful) { |
454 | data->glDeleteProgram(entry->id); |
455 | SDL_free(entry); |
456 | SDL_SetError("Failed to link shader program" ); |
457 | return NULL; |
458 | } |
459 | |
460 | /* Predetermine locations of uniform variables */ |
461 | entry->uniform_locations[VITA_GLES2_UNIFORM_PROJECTION] = |
462 | data->glGetUniformLocation(entry->id, "u_projection" ); |
463 | entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE_V] = |
464 | data->glGetUniformLocation(entry->id, "u_texture_v" ); |
465 | entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE_U] = |
466 | data->glGetUniformLocation(entry->id, "u_texture_u" ); |
467 | entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE] = |
468 | data->glGetUniformLocation(entry->id, "u_texture" ); |
469 | entry->uniform_locations[VITA_GLES2_UNIFORM_COLOR] = |
470 | data->glGetUniformLocation(entry->id, "u_color" ); |
471 | |
472 | entry->color = 0; |
473 | |
474 | data->glUseProgram(entry->id); |
475 | if (entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE_V] != -1) { |
476 | data->glUniform1i(entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE_V], 2); /* always texture unit 2. */ |
477 | } |
478 | if (entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE_U] != -1) { |
479 | data->glUniform1i(entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE_U], 1); /* always texture unit 1. */ |
480 | } |
481 | if (entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE] != -1) { |
482 | data->glUniform1i(entry->uniform_locations[VITA_GLES2_UNIFORM_TEXTURE], 0); /* always texture unit 0. */ |
483 | } |
484 | if (entry->uniform_locations[VITA_GLES2_UNIFORM_PROJECTION] != -1) { |
485 | data->glUniformMatrix4fv(entry->uniform_locations[VITA_GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)entry->projection); |
486 | } |
487 | if (entry->uniform_locations[VITA_GLES2_UNIFORM_COLOR] != -1) { |
488 | data->glUniform4f(entry->uniform_locations[VITA_GLES2_UNIFORM_COLOR], 0.0f, 0.0f, 0.0f, 0.0f); |
489 | } |
490 | |
491 | /* Cache the linked program */ |
492 | if (data->program_cache.head) { |
493 | entry->next = data->program_cache.head; |
494 | data->program_cache.head->prev = entry; |
495 | } else { |
496 | data->program_cache.tail = entry; |
497 | } |
498 | data->program_cache.head = entry; |
499 | ++data->program_cache.count; |
500 | |
501 | /* Increment the refcount of the shaders we're using */ |
502 | ++vertex->references; |
503 | ++fragment->references; |
504 | |
505 | /* Evict the last entry from the cache if we exceed the limit */ |
506 | if (data->program_cache.count > VITA_GLES2_MAX_CACHED_PROGRAMS) { |
507 | shaderEntry = data->program_cache.tail->vertex_shader; |
508 | if (--shaderEntry->references <= 0) { |
509 | VITA_GLES2_EvictShader(data, shaderEntry); |
510 | } |
511 | shaderEntry = data->program_cache.tail->fragment_shader; |
512 | if (--shaderEntry->references <= 0) { |
513 | VITA_GLES2_EvictShader(data, shaderEntry); |
514 | } |
515 | data->glDeleteProgram(data->program_cache.tail->id); |
516 | data->program_cache.tail = data->program_cache.tail->prev; |
517 | if (data->program_cache.tail != NULL) { |
518 | SDL_free(data->program_cache.tail->next); |
519 | data->program_cache.tail->next = NULL; |
520 | } |
521 | --data->program_cache.count; |
522 | } |
523 | return entry; |
524 | } |
525 | |
526 | static VITA_GLES2_ShaderCacheEntry * |
527 | VITA_GLES2_CacheShader(VITA_GLES2_RenderData *data, VITA_GLES2_ShaderType type) |
528 | { |
529 | const VITA_GLES2_Shader *shader; |
530 | const VITA_GLES2_ShaderInstance *instance = NULL; |
531 | VITA_GLES2_ShaderCacheEntry *entry = NULL; |
532 | GLint compileSuccessful = GL_FALSE; |
533 | int i, j; |
534 | |
535 | /* Find the corresponding shader */ |
536 | shader = VITA_GLES2_GetShader(type); |
537 | if (!shader) { |
538 | SDL_SetError("No shader matching the requested characteristics was found" ); |
539 | return NULL; |
540 | } |
541 | |
542 | /* Find a matching shader instance that's supported on this hardware */ |
543 | for (i = 0; i < shader->instance_count && !instance; ++i) { |
544 | for (j = 0; j < data->shader_format_count && !instance; ++j) { |
545 | if (!shader->instances[i]) { |
546 | continue; |
547 | } |
548 | if (shader->instances[i]->format != data->shader_formats[j]) { |
549 | continue; |
550 | } |
551 | instance = shader->instances[i]; |
552 | } |
553 | } |
554 | if (!instance) { |
555 | SDL_SetError("The specified shader cannot be loaded on the current platform" ); |
556 | return NULL; |
557 | } |
558 | |
559 | /* Check if we've already cached this shader */ |
560 | entry = data->shader_cache.head; |
561 | while (entry) { |
562 | if (entry->instance == instance) { |
563 | break; |
564 | } |
565 | entry = entry->next; |
566 | } |
567 | if (entry) { |
568 | return entry; |
569 | } |
570 | |
571 | /* Create a shader cache entry */ |
572 | entry = (VITA_GLES2_ShaderCacheEntry *)SDL_calloc(1, sizeof(VITA_GLES2_ShaderCacheEntry)); |
573 | if (!entry) { |
574 | SDL_OutOfMemory(); |
575 | return NULL; |
576 | } |
577 | entry->type = type; |
578 | entry->instance = instance; |
579 | |
580 | /* Compile or load the selected shader instance */ |
581 | entry->id = data->glCreateShader(instance->type); |
582 | if (instance->format == (GLenum)-1) { |
583 | data->glShaderSource(entry->id, 1, (const char **)(char *)&instance->data, NULL); |
584 | data->glCompileShader(entry->id); |
585 | data->glGetShaderiv(entry->id, GL_COMPILE_STATUS, &compileSuccessful); |
586 | } else { |
587 | data->glShaderBinary(1, &entry->id, instance->format, instance->data, instance->length); |
588 | compileSuccessful = GL_TRUE; |
589 | } |
590 | if (!compileSuccessful) { |
591 | SDL_bool isstack = SDL_FALSE; |
592 | char *info = NULL; |
593 | int length = 0; |
594 | |
595 | data->glGetShaderiv(entry->id, GL_INFO_LOG_LENGTH, &length); |
596 | if (length > 0) { |
597 | info = SDL_small_alloc(char, length, &isstack); |
598 | if (info) { |
599 | data->glGetShaderInfoLog(entry->id, length, &length, info); |
600 | } |
601 | } |
602 | if (info) { |
603 | SDL_SetError("Failed to load the shader: %s" , info); |
604 | SDL_small_free(info, isstack); |
605 | } else { |
606 | SDL_SetError("Failed to load the shader" ); |
607 | } |
608 | data->glDeleteShader(entry->id); |
609 | SDL_free(entry); |
610 | return NULL; |
611 | } |
612 | |
613 | /* Link the shader entry in at the front of the cache */ |
614 | if (data->shader_cache.head) { |
615 | entry->next = data->shader_cache.head; |
616 | data->shader_cache.head->prev = entry; |
617 | } |
618 | data->shader_cache.head = entry; |
619 | ++data->shader_cache.count; |
620 | return entry; |
621 | } |
622 | |
623 | static int |
624 | VITA_GLES2_SelectProgram(VITA_GLES2_RenderData *data, VITA_GLES2_ImageSource source, int w, int h) |
625 | { |
626 | VITA_GLES2_ShaderCacheEntry *vertex = NULL; |
627 | VITA_GLES2_ShaderCacheEntry *fragment = NULL; |
628 | VITA_GLES2_ShaderType vtype, ftype; |
629 | VITA_GLES2_ProgramCacheEntry *program; |
630 | |
631 | /* Select an appropriate shader pair for the specified modes */ |
632 | vtype = VITA_GLES2_SHADER_VERTEX_DEFAULT; |
633 | switch (source) { |
634 | case VITA_GLES2_IMAGESOURCE_SOLID: |
635 | ftype = VITA_GLES2_SHADER_FRAGMENT_SOLID_SRC; |
636 | break; |
637 | case VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR: |
638 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC; |
639 | break; |
640 | case VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB: |
641 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC; |
642 | break; |
643 | case VITA_GLES2_IMAGESOURCE_TEXTURE_RGB: |
644 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_RGB_SRC; |
645 | break; |
646 | case VITA_GLES2_IMAGESOURCE_TEXTURE_BGR: |
647 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_BGR_SRC; |
648 | break; |
649 | case VITA_GLES2_IMAGESOURCE_TEXTURE_YUV: |
650 | switch (SDL_GetYUVConversionModeForResolution(w, h)) { |
651 | case SDL_YUV_CONVERSION_JPEG: |
652 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_YUV_JPEG_SRC; |
653 | break; |
654 | case SDL_YUV_CONVERSION_BT601: |
655 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT601_SRC; |
656 | break; |
657 | case SDL_YUV_CONVERSION_BT709: |
658 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_YUV_BT709_SRC; |
659 | break; |
660 | default: |
661 | SDL_SetError("Unsupported YUV conversion mode: %d\n" , SDL_GetYUVConversionModeForResolution(w, h)); |
662 | goto fault; |
663 | } |
664 | break; |
665 | case VITA_GLES2_IMAGESOURCE_TEXTURE_NV12: |
666 | switch (SDL_GetYUVConversionModeForResolution(w, h)) { |
667 | case SDL_YUV_CONVERSION_JPEG: |
668 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_NV12_JPEG_SRC; |
669 | break; |
670 | case SDL_YUV_CONVERSION_BT601: |
671 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT601_SRC; |
672 | break; |
673 | case SDL_YUV_CONVERSION_BT709: |
674 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_NV12_BT709_SRC; |
675 | break; |
676 | default: |
677 | SDL_SetError("Unsupported YUV conversion mode: %d\n" , SDL_GetYUVConversionModeForResolution(w, h)); |
678 | goto fault; |
679 | } |
680 | break; |
681 | case VITA_GLES2_IMAGESOURCE_TEXTURE_NV21: |
682 | switch (SDL_GetYUVConversionModeForResolution(w, h)) { |
683 | case SDL_YUV_CONVERSION_JPEG: |
684 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_NV21_JPEG_SRC; |
685 | break; |
686 | case SDL_YUV_CONVERSION_BT601: |
687 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT601_SRC; |
688 | break; |
689 | case SDL_YUV_CONVERSION_BT709: |
690 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_NV21_BT709_SRC; |
691 | break; |
692 | default: |
693 | SDL_SetError("Unsupported YUV conversion mode: %d\n" , SDL_GetYUVConversionModeForResolution(w, h)); |
694 | goto fault; |
695 | } |
696 | break; |
697 | case VITA_GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES: |
698 | ftype = VITA_GLES2_SHADER_FRAGMENT_TEXTURE_EXTERNAL_OES_SRC; |
699 | break; |
700 | default: |
701 | goto fault; |
702 | } |
703 | |
704 | /* Load the requested shaders */ |
705 | vertex = VITA_GLES2_CacheShader(data, vtype); |
706 | if (!vertex) { |
707 | goto fault; |
708 | } |
709 | fragment = VITA_GLES2_CacheShader(data, ftype); |
710 | if (!fragment) { |
711 | goto fault; |
712 | } |
713 | |
714 | /* Check if we need to change programs at all */ |
715 | if (data->drawstate.program && |
716 | data->drawstate.program->vertex_shader == vertex && |
717 | data->drawstate.program->fragment_shader == fragment) { |
718 | return 0; |
719 | } |
720 | |
721 | /* Generate a matching program */ |
722 | program = VITA_GLES2_CacheProgram(data, vertex, fragment); |
723 | if (!program) { |
724 | goto fault; |
725 | } |
726 | |
727 | /* Select that program in OpenGL */ |
728 | data->glUseProgram(program->id); |
729 | |
730 | /* Set the current program */ |
731 | data->drawstate.program = program; |
732 | |
733 | /* Clean up and return */ |
734 | return 0; |
735 | fault: |
736 | if (vertex && vertex->references <= 0) { |
737 | VITA_GLES2_EvictShader(data, vertex); |
738 | } |
739 | if (fragment && fragment->references <= 0) { |
740 | VITA_GLES2_EvictShader(data, fragment); |
741 | } |
742 | data->drawstate.program = NULL; |
743 | return -1; |
744 | } |
745 | |
746 | static int |
747 | VITA_GLES2_QueueSetViewport(SDL_Renderer * renderer, SDL_RenderCommand *cmd) |
748 | { |
749 | return 0; /* nothing to do in this backend. */ |
750 | } |
751 | |
752 | static int |
753 | VITA_GLES2_QueueDrawPoints(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FPoint * points, int count) |
754 | { |
755 | |
756 | GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 2 * sizeof (GLfloat), 4, &cmd->data.draw.first); |
757 | |
758 | int i; |
759 | |
760 | if (!verts) { |
761 | return -1; |
762 | } |
763 | |
764 | cmd->data.draw.count = count; |
765 | for (i = 0; i < count; i++) { |
766 | *(verts++) = 0.5f + points[i].x; |
767 | *(verts++) = 0.5f + points[i].y; |
768 | } |
769 | |
770 | return 0; |
771 | } |
772 | |
773 | static int |
774 | VITA_GLES2_QueueFillRects(SDL_Renderer * renderer, SDL_RenderCommand *cmd, const SDL_FRect * rects, int count) |
775 | { |
776 | GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, count * 8 * sizeof (GLfloat), 4, &cmd->data.draw.first); |
777 | |
778 | int i; |
779 | |
780 | if (!verts) { |
781 | return -1; |
782 | } |
783 | |
784 | cmd->data.draw.count = count; |
785 | |
786 | for (i = 0; i < count; i++) { |
787 | const SDL_FRect *rect = &rects[i]; |
788 | const GLfloat minx = rect->x; |
789 | const GLfloat maxx = rect->x + rect->w; |
790 | const GLfloat miny = rect->y; |
791 | const GLfloat maxy = rect->y + rect->h; |
792 | *(verts++) = minx; |
793 | *(verts++) = miny; |
794 | *(verts++) = maxx; |
795 | *(verts++) = miny; |
796 | *(verts++) = minx; |
797 | *(verts++) = maxy; |
798 | *(verts++) = maxx; |
799 | *(verts++) = maxy; |
800 | } |
801 | |
802 | return 0; |
803 | } |
804 | |
805 | static int |
806 | VITA_GLES2_QueueCopy(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, |
807 | const SDL_Rect * srcrect, const SDL_FRect * dstrect) |
808 | { |
809 | GLfloat minx, miny, maxx, maxy; |
810 | GLfloat minu, maxu, minv, maxv; |
811 | GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 16 * sizeof (GLfloat), 4, &cmd->data.draw.first); |
812 | |
813 | if (!verts) { |
814 | return -1; |
815 | } |
816 | |
817 | cmd->data.draw.count = 1; |
818 | |
819 | minx = dstrect->x; |
820 | miny = dstrect->y; |
821 | maxx = dstrect->x + dstrect->w; |
822 | maxy = dstrect->y + dstrect->h; |
823 | |
824 | minu = (GLfloat) srcrect->x / texture->w; |
825 | maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; |
826 | minv = (GLfloat) srcrect->y / texture->h; |
827 | maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; |
828 | |
829 | *(verts++) = minx; |
830 | *(verts++) = miny; |
831 | *(verts++) = maxx; |
832 | *(verts++) = miny; |
833 | *(verts++) = minx; |
834 | *(verts++) = maxy; |
835 | *(verts++) = maxx; |
836 | *(verts++) = maxy; |
837 | |
838 | *(verts++) = minu; |
839 | *(verts++) = minv; |
840 | *(verts++) = maxu; |
841 | *(verts++) = minv; |
842 | *(verts++) = minu; |
843 | *(verts++) = maxv; |
844 | *(verts++) = maxu; |
845 | *(verts++) = maxv; |
846 | |
847 | return 0; |
848 | } |
849 | |
850 | static int |
851 | VITA_GLES2_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * texture, |
852 | const SDL_Rect * srcquad, const SDL_FRect * dstrect, |
853 | const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip) |
854 | { |
855 | /* render expects cos value - 1 (see VITA_GLES2_VertexSrc_Default_) */ |
856 | const float radian_angle = (float)(M_PI * (360.0 - angle) / 180.0); |
857 | const GLfloat s = (GLfloat) SDL_sin(radian_angle); |
858 | const GLfloat c = (GLfloat) SDL_cos(radian_angle) - 1.0f; |
859 | const GLfloat centerx = center->x + dstrect->x; |
860 | const GLfloat centery = center->y + dstrect->y; |
861 | GLfloat minx, miny, maxx, maxy; |
862 | GLfloat minu, maxu, minv, maxv; |
863 | GLfloat *verts = (GLfloat *) SDL_AllocateRenderVertices(renderer, 32 * sizeof (GLfloat), 4, &cmd->data.draw.first); |
864 | |
865 | if (!verts) { |
866 | return -1; |
867 | } |
868 | |
869 | if (flip & SDL_FLIP_HORIZONTAL) { |
870 | minx = dstrect->x + dstrect->w; |
871 | maxx = dstrect->x; |
872 | } else { |
873 | minx = dstrect->x; |
874 | maxx = dstrect->x + dstrect->w; |
875 | } |
876 | |
877 | if (flip & SDL_FLIP_VERTICAL) { |
878 | miny = dstrect->y + dstrect->h; |
879 | maxy = dstrect->y; |
880 | } else { |
881 | miny = dstrect->y; |
882 | maxy = dstrect->y + dstrect->h; |
883 | } |
884 | |
885 | minu = ((GLfloat) srcquad->x) / ((GLfloat) texture->w); |
886 | maxu = ((GLfloat) (srcquad->x + srcquad->w)) / ((GLfloat) texture->w); |
887 | minv = ((GLfloat) srcquad->y) / ((GLfloat) texture->h); |
888 | maxv = ((GLfloat) (srcquad->y + srcquad->h)) / ((GLfloat) texture->h); |
889 | |
890 | |
891 | cmd->data.draw.count = 1; |
892 | |
893 | *(verts++) = minx; |
894 | *(verts++) = miny; |
895 | *(verts++) = maxx; |
896 | *(verts++) = miny; |
897 | *(verts++) = minx; |
898 | *(verts++) = maxy; |
899 | *(verts++) = maxx; |
900 | *(verts++) = maxy; |
901 | |
902 | *(verts++) = minu; |
903 | *(verts++) = minv; |
904 | *(verts++) = maxu; |
905 | *(verts++) = minv; |
906 | *(verts++) = minu; |
907 | *(verts++) = maxv; |
908 | *(verts++) = maxu; |
909 | *(verts++) = maxv; |
910 | |
911 | *(verts++) = s; |
912 | *(verts++) = c; |
913 | *(verts++) = s; |
914 | *(verts++) = c; |
915 | *(verts++) = s; |
916 | *(verts++) = c; |
917 | *(verts++) = s; |
918 | *(verts++) = c; |
919 | |
920 | *(verts++) = centerx; |
921 | *(verts++) = centery; |
922 | *(verts++) = centerx; |
923 | *(verts++) = centery; |
924 | *(verts++) = centerx; |
925 | *(verts++) = centery; |
926 | *(verts++) = centerx; |
927 | *(verts++) = centery; |
928 | |
929 | return 0; |
930 | } |
931 | |
932 | static int |
933 | SetDrawState(VITA_GLES2_RenderData *data, const SDL_RenderCommand *cmd, const VITA_GLES2_ImageSource imgsrc) |
934 | { |
935 | const SDL_bool was_copy_ex = data->drawstate.is_copy_ex; |
936 | const SDL_bool is_copy_ex = (cmd->command == SDL_RENDERCMD_COPY_EX); |
937 | SDL_Texture *texture = cmd->data.draw.texture; |
938 | const SDL_BlendMode blend = cmd->data.draw.blend; |
939 | VITA_GLES2_ProgramCacheEntry *program; |
940 | |
941 | SDL_assert((texture != NULL) == (imgsrc != VITA_GLES2_IMAGESOURCE_SOLID)); |
942 | |
943 | if (data->drawstate.viewport_dirty) { |
944 | const SDL_Rect *viewport = &data->drawstate.viewport; |
945 | data->glViewport(viewport->x, |
946 | data->drawstate.target ? viewport->y : (data->drawstate.drawableh - viewport->y - viewport->h), |
947 | viewport->w, viewport->h); |
948 | if (viewport->w && viewport->h) { |
949 | data->drawstate.projection[0][0] = 2.0f / viewport->w; |
950 | data->drawstate.projection[1][1] = (data->drawstate.target ? 2.0f : -2.0f) / viewport->h; |
951 | data->drawstate.projection[3][1] = data->drawstate.target ? -1.0f : 1.0f; |
952 | } |
953 | data->drawstate.viewport_dirty = SDL_FALSE; |
954 | } |
955 | |
956 | if (data->drawstate.cliprect_enabled_dirty) { |
957 | if (!data->drawstate.cliprect_enabled) { |
958 | data->glDisable(GL_SCISSOR_TEST); |
959 | } else { |
960 | data->glEnable(GL_SCISSOR_TEST); |
961 | } |
962 | data->drawstate.cliprect_enabled_dirty = SDL_FALSE; |
963 | } |
964 | |
965 | if (data->drawstate.cliprect_enabled && data->drawstate.cliprect_dirty) { |
966 | const SDL_Rect *viewport = &data->drawstate.viewport; |
967 | const SDL_Rect *rect = &data->drawstate.cliprect; |
968 | data->glScissor(viewport->x + rect->x, |
969 | data->drawstate.target ? viewport->y + rect->y : data->drawstate.drawableh - viewport->y - rect->y - rect->h, |
970 | rect->w, rect->h); |
971 | data->drawstate.cliprect_dirty = SDL_FALSE; |
972 | } |
973 | |
974 | if (texture != data->drawstate.texture) { |
975 | if ((texture != NULL) != data->drawstate.texturing) { |
976 | if (texture == NULL) { |
977 | data->glDisableVertexAttribArray((GLenum) VITA_GLES2_ATTRIBUTE_TEXCOORD); |
978 | data->drawstate.texturing = SDL_FALSE; |
979 | } else { |
980 | data->glEnableVertexAttribArray((GLenum) VITA_GLES2_ATTRIBUTE_TEXCOORD); |
981 | data->drawstate.texturing = SDL_TRUE; |
982 | } |
983 | } |
984 | |
985 | if (texture) { |
986 | VITA_GLES2_TextureData *tdata = (VITA_GLES2_TextureData *) texture->driverdata; |
987 | if (tdata->yuv) { |
988 | data->glActiveTexture(GL_TEXTURE2); |
989 | data->glBindTexture(tdata->texture_type, tdata->texture_v); |
990 | |
991 | data->glActiveTexture(GL_TEXTURE1); |
992 | data->glBindTexture(tdata->texture_type, tdata->texture_u); |
993 | |
994 | data->glActiveTexture(GL_TEXTURE0); |
995 | } else if (tdata->nv12) { |
996 | data->glActiveTexture(GL_TEXTURE1); |
997 | data->glBindTexture(tdata->texture_type, tdata->texture_u); |
998 | |
999 | data->glActiveTexture(GL_TEXTURE0); |
1000 | } |
1001 | data->glBindTexture(tdata->texture_type, tdata->texture); |
1002 | } |
1003 | |
1004 | data->drawstate.texture = texture; |
1005 | } |
1006 | |
1007 | if (texture) { |
1008 | data->glVertexAttribPointer(VITA_GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 8))); |
1009 | } |
1010 | |
1011 | if (VITA_GLES2_SelectProgram(data, imgsrc, texture ? texture->w : 0, texture ? texture->h : 0) < 0) { |
1012 | return -1; |
1013 | } |
1014 | |
1015 | program = data->drawstate.program; |
1016 | |
1017 | if (program->uniform_locations[VITA_GLES2_UNIFORM_PROJECTION] != -1) { |
1018 | if (SDL_memcmp(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)) != 0) { |
1019 | data->glUniformMatrix4fv(program->uniform_locations[VITA_GLES2_UNIFORM_PROJECTION], 1, GL_FALSE, (GLfloat *)data->drawstate.projection); |
1020 | SDL_memcpy(program->projection, data->drawstate.projection, sizeof (data->drawstate.projection)); |
1021 | } |
1022 | } |
1023 | |
1024 | if (program->uniform_locations[VITA_GLES2_UNIFORM_COLOR] != -1) { |
1025 | if (data->drawstate.color != program->color) { |
1026 | const Uint8 r = (data->drawstate.color >> 16) & 0xFF; |
1027 | const Uint8 g = (data->drawstate.color >> 8) & 0xFF; |
1028 | const Uint8 b = (data->drawstate.color >> 0) & 0xFF; |
1029 | const Uint8 a = (data->drawstate.color >> 24) & 0xFF; |
1030 | data->glUniform4f(program->uniform_locations[VITA_GLES2_UNIFORM_COLOR], r * inv255f, g * inv255f, b * inv255f, a * inv255f); |
1031 | program->color = data->drawstate.color; |
1032 | } |
1033 | } |
1034 | |
1035 | if (blend != data->drawstate.blend) { |
1036 | if (blend == SDL_BLENDMODE_NONE) { |
1037 | data->glDisable(GL_BLEND); |
1038 | } else { |
1039 | data->glEnable(GL_BLEND); |
1040 | data->glBlendFuncSeparate(GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend)), |
1041 | GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend)), |
1042 | GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend)), |
1043 | GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend))); |
1044 | data->glBlendEquationSeparate(GetBlendEquation(SDL_GetBlendModeColorOperation(blend)), |
1045 | GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend))); |
1046 | } |
1047 | data->drawstate.blend = blend; |
1048 | } |
1049 | |
1050 | /* all drawing commands use this */ |
1051 | data->glVertexAttribPointer(VITA_GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) cmd->data.draw.first); |
1052 | |
1053 | if (is_copy_ex != was_copy_ex) { |
1054 | if (is_copy_ex) { |
1055 | data->glEnableVertexAttribArray((GLenum) VITA_GLES2_ATTRIBUTE_ANGLE); |
1056 | data->glEnableVertexAttribArray((GLenum) VITA_GLES2_ATTRIBUTE_CENTER); |
1057 | } else { |
1058 | data->glDisableVertexAttribArray((GLenum) VITA_GLES2_ATTRIBUTE_ANGLE); |
1059 | data->glDisableVertexAttribArray((GLenum) VITA_GLES2_ATTRIBUTE_CENTER); |
1060 | } |
1061 | data->drawstate.is_copy_ex = is_copy_ex; |
1062 | } |
1063 | |
1064 | if (is_copy_ex) { |
1065 | data->glVertexAttribPointer(VITA_GLES2_ATTRIBUTE_ANGLE, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 16))); |
1066 | data->glVertexAttribPointer(VITA_GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *) (cmd->data.draw.first + (sizeof (GLfloat) * 24))); |
1067 | } |
1068 | |
1069 | return 0; |
1070 | } |
1071 | |
1072 | static int |
1073 | SetCopyState(SDL_Renderer *renderer, const SDL_RenderCommand *cmd) |
1074 | { |
1075 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *) renderer->driverdata; |
1076 | VITA_GLES2_ImageSource sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR; |
1077 | SDL_Texture *texture = cmd->data.draw.texture; |
1078 | |
1079 | /* Pick an appropriate shader */ |
1080 | if (renderer->target) { |
1081 | /* Check if we need to do color mapping between the source and render target textures */ |
1082 | if (renderer->target->format != texture->format) { |
1083 | switch (texture->format) { |
1084 | case SDL_PIXELFORMAT_ARGB8888: |
1085 | switch (renderer->target->format) { |
1086 | case SDL_PIXELFORMAT_ABGR8888: |
1087 | case SDL_PIXELFORMAT_BGR888: |
1088 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB; |
1089 | break; |
1090 | case SDL_PIXELFORMAT_RGB888: |
1091 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR; |
1092 | break; |
1093 | } |
1094 | break; |
1095 | case SDL_PIXELFORMAT_ABGR8888: |
1096 | switch (renderer->target->format) { |
1097 | case SDL_PIXELFORMAT_ARGB8888: |
1098 | case SDL_PIXELFORMAT_RGB888: |
1099 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB; |
1100 | break; |
1101 | case SDL_PIXELFORMAT_BGR888: |
1102 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR; |
1103 | break; |
1104 | } |
1105 | break; |
1106 | case SDL_PIXELFORMAT_RGB888: |
1107 | switch (renderer->target->format) { |
1108 | case SDL_PIXELFORMAT_ABGR8888: |
1109 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB; |
1110 | break; |
1111 | case SDL_PIXELFORMAT_ARGB8888: |
1112 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_BGR; |
1113 | break; |
1114 | case SDL_PIXELFORMAT_BGR888: |
1115 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB; |
1116 | break; |
1117 | } |
1118 | break; |
1119 | case SDL_PIXELFORMAT_BGR888: |
1120 | switch (renderer->target->format) { |
1121 | case SDL_PIXELFORMAT_ABGR8888: |
1122 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_BGR; |
1123 | break; |
1124 | case SDL_PIXELFORMAT_ARGB8888: |
1125 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_RGB; |
1126 | break; |
1127 | case SDL_PIXELFORMAT_RGB888: |
1128 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB; |
1129 | break; |
1130 | } |
1131 | break; |
1132 | case SDL_PIXELFORMAT_IYUV: |
1133 | case SDL_PIXELFORMAT_YV12: |
1134 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_YUV; |
1135 | break; |
1136 | case SDL_PIXELFORMAT_NV12: |
1137 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_NV12; |
1138 | break; |
1139 | case SDL_PIXELFORMAT_NV21: |
1140 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_NV21; |
1141 | break; |
1142 | case SDL_PIXELFORMAT_EXTERNAL_OES: |
1143 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES; |
1144 | break; |
1145 | default: |
1146 | return SDL_SetError("Unsupported texture format" ); |
1147 | } |
1148 | } else { |
1149 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR; /* Texture formats match, use the non color mapping shader (even if the formats are not ABGR) */ |
1150 | } |
1151 | } else { |
1152 | switch (texture->format) { |
1153 | case SDL_PIXELFORMAT_ARGB8888: |
1154 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ARGB; |
1155 | break; |
1156 | case SDL_PIXELFORMAT_ABGR8888: |
1157 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_ABGR; |
1158 | break; |
1159 | case SDL_PIXELFORMAT_RGB888: |
1160 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_RGB; |
1161 | break; |
1162 | case SDL_PIXELFORMAT_BGR888: |
1163 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_BGR; |
1164 | break; |
1165 | case SDL_PIXELFORMAT_IYUV: |
1166 | case SDL_PIXELFORMAT_YV12: |
1167 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_YUV; |
1168 | break; |
1169 | case SDL_PIXELFORMAT_NV12: |
1170 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_NV12; |
1171 | break; |
1172 | case SDL_PIXELFORMAT_NV21: |
1173 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_NV21; |
1174 | break; |
1175 | case SDL_PIXELFORMAT_EXTERNAL_OES: |
1176 | sourceType = VITA_GLES2_IMAGESOURCE_TEXTURE_EXTERNAL_OES; |
1177 | break; |
1178 | default: |
1179 | return SDL_SetError("Unsupported texture format" ); |
1180 | } |
1181 | } |
1182 | |
1183 | return SetDrawState(data, cmd, sourceType); |
1184 | } |
1185 | |
1186 | static int |
1187 | VITA_GLES2_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize) |
1188 | { |
1189 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *) renderer->driverdata; |
1190 | const SDL_bool colorswap = (renderer->target && (renderer->target->format == SDL_PIXELFORMAT_ARGB8888 || renderer->target->format == SDL_PIXELFORMAT_RGB888)); |
1191 | const int vboidx = data->current_vertex_buffer; |
1192 | const GLuint vbo = data->vertex_buffers[vboidx]; |
1193 | size_t i; |
1194 | |
1195 | if (VITA_GLES2_ActivateRenderer(renderer) < 0) { |
1196 | return -1; |
1197 | } |
1198 | |
1199 | data->drawstate.target = renderer->target; |
1200 | if (!data->drawstate.target) { |
1201 | SDL_GL_GetDrawableSize(renderer->window, &data->drawstate.drawablew, &data->drawstate.drawableh); |
1202 | } |
1203 | |
1204 | /* upload the new VBO data for this set of commands. */ |
1205 | /* NULL/zero vertices could happen SetRenderTarget is the first render command */ |
1206 | if (vertsize > 0 && vertices != NULL) |
1207 | { |
1208 | data->glBindBuffer(GL_ARRAY_BUFFER, vbo); |
1209 | if (data->vertex_buffer_size[vboidx] < vertsize) { |
1210 | data->glBufferData(GL_ARRAY_BUFFER, vertsize, vertices, GL_DYNAMIC_DRAW); |
1211 | data->vertex_buffer_size[vboidx] = vertsize; |
1212 | } else { |
1213 | data->glBufferSubData(GL_ARRAY_BUFFER, 0, vertsize, vertices); |
1214 | } |
1215 | } |
1216 | |
1217 | /* cycle through a few VBOs so the GL has some time with the data before we replace it. */ |
1218 | data->current_vertex_buffer++; |
1219 | if (data->current_vertex_buffer >= SDL_arraysize(data->vertex_buffers)) { |
1220 | data->current_vertex_buffer = 0; |
1221 | } |
1222 | |
1223 | data->glDisable(GL_DEPTH_TEST); |
1224 | data->glDisable(GL_CULL_FACE); |
1225 | |
1226 | while (cmd) { |
1227 | switch (cmd->command) { |
1228 | case SDL_RENDERCMD_SETDRAWCOLOR: { |
1229 | const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r; |
1230 | const Uint8 g = cmd->data.color.g; |
1231 | const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b; |
1232 | const Uint8 a = cmd->data.color.a; |
1233 | data->drawstate.color = ((a << 24) | (r << 16) | (g << 8) | b); |
1234 | break; |
1235 | } |
1236 | |
1237 | case SDL_RENDERCMD_SETVIEWPORT: { |
1238 | SDL_Rect *viewport = &data->drawstate.viewport; |
1239 | if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) { |
1240 | SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)); |
1241 | data->drawstate.viewport_dirty = SDL_TRUE; |
1242 | } |
1243 | break; |
1244 | } |
1245 | |
1246 | case SDL_RENDERCMD_SETCLIPRECT: { |
1247 | const SDL_Rect *rect = &cmd->data.cliprect.rect; |
1248 | if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) { |
1249 | data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled; |
1250 | data->drawstate.cliprect_enabled_dirty = SDL_TRUE; |
1251 | } |
1252 | |
1253 | if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) { |
1254 | SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)); |
1255 | data->drawstate.cliprect_dirty = SDL_TRUE; |
1256 | } |
1257 | break; |
1258 | } |
1259 | |
1260 | case SDL_RENDERCMD_CLEAR: { |
1261 | const Uint8 r = colorswap ? cmd->data.color.b : cmd->data.color.r; |
1262 | const Uint8 g = cmd->data.color.g; |
1263 | const Uint8 b = colorswap ? cmd->data.color.r : cmd->data.color.b; |
1264 | const Uint8 a = cmd->data.color.a; |
1265 | const Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b); |
1266 | if (color != data->drawstate.clear_color) { |
1267 | const GLfloat fr = ((GLfloat) r) * inv255f; |
1268 | const GLfloat fg = ((GLfloat) g) * inv255f; |
1269 | const GLfloat fb = ((GLfloat) b) * inv255f; |
1270 | const GLfloat fa = ((GLfloat) a) * inv255f; |
1271 | data->glClearColor(fr, fg, fb, fa); |
1272 | data->drawstate.clear_color = color; |
1273 | } |
1274 | |
1275 | if (data->drawstate.cliprect_enabled || data->drawstate.cliprect_enabled_dirty) { |
1276 | data->glDisable(GL_SCISSOR_TEST); |
1277 | data->drawstate.cliprect_enabled_dirty = data->drawstate.cliprect_enabled; |
1278 | } |
1279 | |
1280 | data->glClear(GL_COLOR_BUFFER_BIT); |
1281 | break; |
1282 | } |
1283 | |
1284 | case SDL_RENDERCMD_DRAW_POINTS: { |
1285 | if (SetDrawState(data, cmd, VITA_GLES2_IMAGESOURCE_SOLID) == 0) { |
1286 | data->glDrawArrays(GL_POINTS, 0, (GLsizei) cmd->data.draw.count); |
1287 | } |
1288 | break; |
1289 | } |
1290 | |
1291 | case SDL_RENDERCMD_DRAW_LINES: { |
1292 | const GLfloat *verts = (GLfloat *) (((Uint8 *) vertices) + cmd->data.draw.first); |
1293 | const size_t count = cmd->data.draw.count; |
1294 | if (SetDrawState(data, cmd, VITA_GLES2_IMAGESOURCE_SOLID) == 0) { |
1295 | if (count > 2 && (verts[0] == verts[(count-1)*2]) && (verts[1] == verts[(count*2)-1])) { |
1296 | /* GL_LINE_LOOP takes care of the final segment */ |
1297 | data->glDrawArrays(GL_LINE_LOOP, 0, (GLsizei) (count - 1)); |
1298 | } else { |
1299 | data->glDrawArrays(GL_LINE_STRIP, 0, (GLsizei) count); |
1300 | /* We need to close the endpoint of the line */ |
1301 | data->glDrawArrays(GL_POINTS, (GLsizei) (count - 1), 1); |
1302 | } |
1303 | } |
1304 | break; |
1305 | } |
1306 | |
1307 | case SDL_RENDERCMD_FILL_RECTS: { |
1308 | const size_t count = cmd->data.draw.count; |
1309 | size_t offset = 0; |
1310 | if (SetDrawState(data, cmd, VITA_GLES2_IMAGESOURCE_SOLID) == 0) { |
1311 | for (i = 0; i < count; ++i, offset += 4) { |
1312 | data->glDrawArrays(GL_TRIANGLE_STRIP, (GLsizei) offset, 4); |
1313 | } |
1314 | } |
1315 | break; |
1316 | } |
1317 | |
1318 | case SDL_RENDERCMD_COPY: |
1319 | case SDL_RENDERCMD_COPY_EX: { |
1320 | if (SetCopyState(renderer, cmd) == 0) { |
1321 | data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
1322 | } |
1323 | break; |
1324 | } |
1325 | |
1326 | case SDL_RENDERCMD_NO_OP: |
1327 | break; |
1328 | } |
1329 | |
1330 | cmd = cmd->next; |
1331 | } |
1332 | |
1333 | return GL_CheckError("" , renderer); |
1334 | } |
1335 | |
1336 | static void |
1337 | VITA_GLES2_DestroyRenderer(SDL_Renderer *renderer) |
1338 | { |
1339 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1340 | |
1341 | /* Deallocate everything */ |
1342 | if (data) { |
1343 | VITA_GLES2_ActivateRenderer(renderer); |
1344 | |
1345 | { |
1346 | VITA_GLES2_ShaderCacheEntry *entry; |
1347 | VITA_GLES2_ShaderCacheEntry *next; |
1348 | entry = data->shader_cache.head; |
1349 | while (entry) { |
1350 | data->glDeleteShader(entry->id); |
1351 | next = entry->next; |
1352 | SDL_free(entry); |
1353 | entry = next; |
1354 | } |
1355 | } |
1356 | { |
1357 | VITA_GLES2_ProgramCacheEntry *entry; |
1358 | VITA_GLES2_ProgramCacheEntry *next; |
1359 | entry = data->program_cache.head; |
1360 | while (entry) { |
1361 | data->glDeleteProgram(entry->id); |
1362 | next = entry->next; |
1363 | SDL_free(entry); |
1364 | entry = next; |
1365 | } |
1366 | } |
1367 | |
1368 | if (data->context) { |
1369 | while (data->framebuffers) { |
1370 | VITA_GLES2_FBOList *nextnode = data->framebuffers->next; |
1371 | data->glDeleteFramebuffers(1, &data->framebuffers->FBO); |
1372 | GL_CheckError("" , renderer); |
1373 | SDL_free(data->framebuffers); |
1374 | data->framebuffers = nextnode; |
1375 | } |
1376 | |
1377 | data->glDeleteBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers); |
1378 | GL_CheckError("" , renderer); |
1379 | |
1380 | SDL_GL_DeleteContext(data->context); |
1381 | } |
1382 | |
1383 | SDL_free(data->shader_formats); |
1384 | SDL_free(data); |
1385 | } |
1386 | SDL_free(renderer); |
1387 | } |
1388 | |
1389 | static int |
1390 | VITA_GLES2_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture) |
1391 | { |
1392 | VITA_GLES2_RenderData *renderdata = (VITA_GLES2_RenderData *)renderer->driverdata; |
1393 | VITA_GLES2_TextureData *data; |
1394 | GLenum format; |
1395 | GLenum type; |
1396 | GLenum scaleMode; |
1397 | |
1398 | VITA_GLES2_ActivateRenderer(renderer); |
1399 | |
1400 | renderdata->drawstate.texture = NULL; /* we trash this state. */ |
1401 | |
1402 | /* Determine the corresponding GLES texture format params */ |
1403 | switch (texture->format) |
1404 | { |
1405 | case SDL_PIXELFORMAT_ARGB8888: |
1406 | case SDL_PIXELFORMAT_ABGR8888: |
1407 | case SDL_PIXELFORMAT_RGB888: |
1408 | case SDL_PIXELFORMAT_BGR888: |
1409 | format = GL_RGBA; |
1410 | type = GL_UNSIGNED_BYTE; |
1411 | break; |
1412 | case SDL_PIXELFORMAT_IYUV: |
1413 | case SDL_PIXELFORMAT_YV12: |
1414 | case SDL_PIXELFORMAT_NV12: |
1415 | case SDL_PIXELFORMAT_NV21: |
1416 | format = GL_LUMINANCE; |
1417 | type = GL_UNSIGNED_BYTE; |
1418 | break; |
1419 | default: |
1420 | return SDL_SetError("Texture format not supported" ); |
1421 | } |
1422 | |
1423 | if (texture->format == SDL_PIXELFORMAT_EXTERNAL_OES && |
1424 | texture->access != SDL_TEXTUREACCESS_STATIC) { |
1425 | return SDL_SetError("Unsupported texture access for SDL_PIXELFORMAT_EXTERNAL_OES" ); |
1426 | } |
1427 | |
1428 | /* Allocate a texture struct */ |
1429 | data = (VITA_GLES2_TextureData *)SDL_calloc(1, sizeof(VITA_GLES2_TextureData)); |
1430 | if (!data) { |
1431 | return SDL_OutOfMemory(); |
1432 | } |
1433 | data->texture = 0; |
1434 | data->texture_type = GL_TEXTURE_2D; |
1435 | data->pixel_format = format; |
1436 | data->pixel_type = type; |
1437 | data->yuv = ((texture->format == SDL_PIXELFORMAT_IYUV) || (texture->format == SDL_PIXELFORMAT_YV12)); |
1438 | data->nv12 = ((texture->format == SDL_PIXELFORMAT_NV12) || (texture->format == SDL_PIXELFORMAT_NV21)); |
1439 | data->texture_u = 0; |
1440 | data->texture_v = 0; |
1441 | scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; |
1442 | |
1443 | /* Allocate a blob for image renderdata */ |
1444 | if (texture->access == SDL_TEXTUREACCESS_STREAMING) { |
1445 | size_t size; |
1446 | data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); |
1447 | size = texture->h * data->pitch; |
1448 | if (data->yuv) { |
1449 | /* Need to add size for the U and V planes */ |
1450 | size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2); |
1451 | } else if (data->nv12) { |
1452 | /* Need to add size for the U/V plane */ |
1453 | size += 2 * ((texture->h + 1) / 2) * ((data->pitch + 1) / 2); |
1454 | } |
1455 | data->pixel_data = SDL_calloc(1, size); |
1456 | if (!data->pixel_data) { |
1457 | SDL_free(data); |
1458 | return SDL_OutOfMemory(); |
1459 | } |
1460 | } |
1461 | |
1462 | /* Allocate the texture */ |
1463 | GL_CheckError("" , renderer); |
1464 | |
1465 | if (data->yuv) { |
1466 | renderdata->glGenTextures(1, &data->texture_v); |
1467 | if (GL_CheckError("glGenTexures()" , renderer) < 0) { |
1468 | return -1; |
1469 | } |
1470 | renderdata->glActiveTexture(GL_TEXTURE2); |
1471 | renderdata->glBindTexture(data->texture_type, data->texture_v); |
1472 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |
1473 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |
1474 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1475 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1476 | renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); |
1477 | |
1478 | renderdata->glGenTextures(1, &data->texture_u); |
1479 | if (GL_CheckError("glGenTexures()" , renderer) < 0) { |
1480 | return -1; |
1481 | } |
1482 | renderdata->glActiveTexture(GL_TEXTURE1); |
1483 | renderdata->glBindTexture(data->texture_type, data->texture_u); |
1484 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |
1485 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |
1486 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1487 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1488 | renderdata->glTexImage2D(data->texture_type, 0, format, (texture->w + 1) / 2, (texture->h + 1) / 2, 0, format, type, NULL); |
1489 | if (GL_CheckError("glTexImage2D()" , renderer) < 0) { |
1490 | return -1; |
1491 | } |
1492 | } else if (data->nv12) { |
1493 | renderdata->glGenTextures(1, &data->texture_u); |
1494 | if (GL_CheckError("glGenTexures()" , renderer) < 0) { |
1495 | return -1; |
1496 | } |
1497 | renderdata->glActiveTexture(GL_TEXTURE1); |
1498 | renderdata->glBindTexture(data->texture_type, data->texture_u); |
1499 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |
1500 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |
1501 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1502 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1503 | 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); |
1504 | if (GL_CheckError("glTexImage2D()" , renderer) < 0) { |
1505 | return -1; |
1506 | } |
1507 | } |
1508 | |
1509 | renderdata->glGenTextures(1, &data->texture); |
1510 | if (GL_CheckError("glGenTexures()" , renderer) < 0) { |
1511 | return -1; |
1512 | } |
1513 | texture->driverdata = data; |
1514 | renderdata->glActiveTexture(GL_TEXTURE0); |
1515 | renderdata->glBindTexture(data->texture_type, data->texture); |
1516 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, scaleMode); |
1517 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, scaleMode); |
1518 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1519 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1520 | if (texture->format != SDL_PIXELFORMAT_EXTERNAL_OES) { |
1521 | renderdata->glTexImage2D(data->texture_type, 0, format, texture->w, texture->h, 0, format, type, NULL); |
1522 | if (GL_CheckError("glTexImage2D()" , renderer) < 0) { |
1523 | return -1; |
1524 | } |
1525 | } |
1526 | |
1527 | if (texture->access == SDL_TEXTUREACCESS_TARGET) { |
1528 | data->fbo = VITA_GLES2_GetFBO(renderer->driverdata, texture->w, texture->h); |
1529 | } else { |
1530 | data->fbo = NULL; |
1531 | } |
1532 | |
1533 | return GL_CheckError("" , renderer); |
1534 | } |
1535 | |
1536 | static int |
1537 | VITA_GLES2_TexSubImage2D(VITA_GLES2_RenderData *data, GLenum target, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels, GLint pitch, GLint bpp) |
1538 | { |
1539 | Uint8 *blob = NULL; |
1540 | Uint8 *src; |
1541 | int src_pitch; |
1542 | int y; |
1543 | |
1544 | if ((width == 0) || (height == 0) || (bpp == 0)) { |
1545 | return 0; /* nothing to do */ |
1546 | } |
1547 | |
1548 | /* Reformat the texture data into a tightly packed array */ |
1549 | src_pitch = width * bpp; |
1550 | src = (Uint8 *)pixels; |
1551 | if (pitch != src_pitch) { |
1552 | blob = (Uint8 *)SDL_malloc(src_pitch * height); |
1553 | if (!blob) { |
1554 | return SDL_OutOfMemory(); |
1555 | } |
1556 | src = blob; |
1557 | for (y = 0; y < height; ++y) |
1558 | { |
1559 | SDL_memcpy(src, pixels, src_pitch); |
1560 | src += src_pitch; |
1561 | pixels = (Uint8 *)pixels + pitch; |
1562 | } |
1563 | src = blob; |
1564 | } |
1565 | |
1566 | data->glTexSubImage2D(target, 0, xoffset, yoffset, width, height, format, type, src); |
1567 | if (blob) { |
1568 | SDL_free(blob); |
1569 | } |
1570 | return 0; |
1571 | } |
1572 | |
1573 | static int |
1574 | VITA_GLES2_UpdateTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, |
1575 | const void *pixels, int pitch) |
1576 | { |
1577 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1578 | VITA_GLES2_TextureData *tdata = (VITA_GLES2_TextureData *)texture->driverdata; |
1579 | |
1580 | VITA_GLES2_ActivateRenderer(renderer); |
1581 | |
1582 | /* Bail out if we're supposed to update an empty rectangle */ |
1583 | if (rect->w <= 0 || rect->h <= 0) { |
1584 | return 0; |
1585 | } |
1586 | |
1587 | data->drawstate.texture = NULL; /* we trash this state. */ |
1588 | |
1589 | /* Create a texture subimage with the supplied data */ |
1590 | data->glBindTexture(tdata->texture_type, tdata->texture); |
1591 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1592 | rect->x, |
1593 | rect->y, |
1594 | rect->w, |
1595 | rect->h, |
1596 | tdata->pixel_format, |
1597 | tdata->pixel_type, |
1598 | pixels, pitch, SDL_BYTESPERPIXEL(texture->format)); |
1599 | |
1600 | if (tdata->yuv) { |
1601 | /* Skip to the correct offset into the next texture */ |
1602 | pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); |
1603 | if (texture->format == SDL_PIXELFORMAT_YV12) { |
1604 | data->glBindTexture(tdata->texture_type, tdata->texture_v); |
1605 | } else { |
1606 | data->glBindTexture(tdata->texture_type, tdata->texture_u); |
1607 | } |
1608 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1609 | rect->x / 2, |
1610 | rect->y / 2, |
1611 | (rect->w + 1) / 2, |
1612 | (rect->h + 1) / 2, |
1613 | tdata->pixel_format, |
1614 | tdata->pixel_type, |
1615 | pixels, (pitch + 1) / 2, 1); |
1616 | |
1617 | |
1618 | /* Skip to the correct offset into the next texture */ |
1619 | pixels = (const void*)((const Uint8*)pixels + ((rect->h + 1) / 2) * ((pitch + 1)/2)); |
1620 | if (texture->format == SDL_PIXELFORMAT_YV12) { |
1621 | data->glBindTexture(tdata->texture_type, tdata->texture_u); |
1622 | } else { |
1623 | data->glBindTexture(tdata->texture_type, tdata->texture_v); |
1624 | } |
1625 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1626 | rect->x / 2, |
1627 | rect->y / 2, |
1628 | (rect->w + 1) / 2, |
1629 | (rect->h + 1) / 2, |
1630 | tdata->pixel_format, |
1631 | tdata->pixel_type, |
1632 | pixels, (pitch + 1) / 2, 1); |
1633 | } else if (tdata->nv12) { |
1634 | /* Skip to the correct offset into the next texture */ |
1635 | pixels = (const void*)((const Uint8*)pixels + rect->h * pitch); |
1636 | data->glBindTexture(tdata->texture_type, tdata->texture_u); |
1637 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1638 | rect->x / 2, |
1639 | rect->y / 2, |
1640 | (rect->w + 1) / 2, |
1641 | (rect->h + 1) / 2, |
1642 | GL_LUMINANCE_ALPHA, |
1643 | GL_UNSIGNED_BYTE, |
1644 | pixels, 2 * ((pitch + 1) / 2), 2); |
1645 | } |
1646 | |
1647 | return GL_CheckError("glTexSubImage2D()" , renderer); |
1648 | } |
1649 | |
1650 | static int |
1651 | VITA_GLES2_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, |
1652 | const SDL_Rect * rect, |
1653 | const Uint8 *Yplane, int Ypitch, |
1654 | const Uint8 *Uplane, int Upitch, |
1655 | const Uint8 *Vplane, int Vpitch) |
1656 | { |
1657 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1658 | VITA_GLES2_TextureData *tdata = (VITA_GLES2_TextureData *)texture->driverdata; |
1659 | |
1660 | VITA_GLES2_ActivateRenderer(renderer); |
1661 | |
1662 | /* Bail out if we're supposed to update an empty rectangle */ |
1663 | if (rect->w <= 0 || rect->h <= 0) { |
1664 | return 0; |
1665 | } |
1666 | |
1667 | data->drawstate.texture = NULL; /* we trash this state. */ |
1668 | |
1669 | data->glBindTexture(tdata->texture_type, tdata->texture_v); |
1670 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1671 | rect->x / 2, |
1672 | rect->y / 2, |
1673 | (rect->w + 1) / 2, |
1674 | (rect->h + 1) / 2, |
1675 | tdata->pixel_format, |
1676 | tdata->pixel_type, |
1677 | Vplane, Vpitch, 1); |
1678 | |
1679 | data->glBindTexture(tdata->texture_type, tdata->texture_u); |
1680 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1681 | rect->x / 2, |
1682 | rect->y / 2, |
1683 | (rect->w + 1) / 2, |
1684 | (rect->h + 1) / 2, |
1685 | tdata->pixel_format, |
1686 | tdata->pixel_type, |
1687 | Uplane, Upitch, 1); |
1688 | |
1689 | data->glBindTexture(tdata->texture_type, tdata->texture); |
1690 | VITA_GLES2_TexSubImage2D(data, tdata->texture_type, |
1691 | rect->x, |
1692 | rect->y, |
1693 | rect->w, |
1694 | rect->h, |
1695 | tdata->pixel_format, |
1696 | tdata->pixel_type, |
1697 | Yplane, Ypitch, 1); |
1698 | |
1699 | return GL_CheckError("glTexSubImage2D()" , renderer); |
1700 | } |
1701 | |
1702 | static int |
1703 | VITA_GLES2_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *rect, |
1704 | void **pixels, int *pitch) |
1705 | { |
1706 | VITA_GLES2_TextureData *tdata = (VITA_GLES2_TextureData *)texture->driverdata; |
1707 | |
1708 | /* Retrieve the buffer/pitch for the specified region */ |
1709 | *pixels = (Uint8 *)tdata->pixel_data + |
1710 | (tdata->pitch * rect->y) + |
1711 | (rect->x * SDL_BYTESPERPIXEL(texture->format)); |
1712 | *pitch = tdata->pitch; |
1713 | |
1714 | return 0; |
1715 | } |
1716 | |
1717 | static void |
1718 | VITA_GLES2_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture) |
1719 | { |
1720 | VITA_GLES2_TextureData *tdata = (VITA_GLES2_TextureData *)texture->driverdata; |
1721 | SDL_Rect rect; |
1722 | |
1723 | /* We do whole texture updates, at least for now */ |
1724 | rect.x = 0; |
1725 | rect.y = 0; |
1726 | rect.w = texture->w; |
1727 | rect.h = texture->h; |
1728 | VITA_GLES2_UpdateTexture(renderer, texture, &rect, tdata->pixel_data, tdata->pitch); |
1729 | } |
1730 | |
1731 | static void |
1732 | VITA_GLES2_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture, SDL_ScaleMode scaleMode) |
1733 | { |
1734 | VITA_GLES2_RenderData *renderdata = (VITA_GLES2_RenderData *) renderer->driverdata; |
1735 | VITA_GLES2_TextureData *data = (VITA_GLES2_TextureData *) texture->driverdata; |
1736 | GLenum glScaleMode = (scaleMode == SDL_ScaleModeNearest) ? GL_NEAREST : GL_LINEAR; |
1737 | |
1738 | if (data->yuv) { |
1739 | renderdata->glActiveTexture(GL_TEXTURE2); |
1740 | renderdata->glBindTexture(data->texture_type, data->texture_v); |
1741 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); |
1742 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); |
1743 | |
1744 | renderdata->glActiveTexture(GL_TEXTURE1); |
1745 | renderdata->glBindTexture(data->texture_type, data->texture_u); |
1746 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); |
1747 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); |
1748 | } else if (data->nv12) { |
1749 | renderdata->glActiveTexture(GL_TEXTURE1); |
1750 | renderdata->glBindTexture(data->texture_type, data->texture_u); |
1751 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); |
1752 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); |
1753 | } |
1754 | |
1755 | renderdata->glActiveTexture(GL_TEXTURE0); |
1756 | renderdata->glBindTexture(data->texture_type, data->texture); |
1757 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MIN_FILTER, glScaleMode); |
1758 | renderdata->glTexParameteri(data->texture_type, GL_TEXTURE_MAG_FILTER, glScaleMode); |
1759 | } |
1760 | |
1761 | static int |
1762 | VITA_GLES2_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) |
1763 | { |
1764 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *) renderer->driverdata; |
1765 | VITA_GLES2_TextureData *texturedata = NULL; |
1766 | GLenum status; |
1767 | |
1768 | data->drawstate.viewport_dirty = SDL_TRUE; |
1769 | |
1770 | if (texture == NULL) { |
1771 | data->glBindFramebuffer(GL_FRAMEBUFFER, data->window_framebuffer); |
1772 | } else { |
1773 | texturedata = (VITA_GLES2_TextureData *) texture->driverdata; |
1774 | data->glBindFramebuffer(GL_FRAMEBUFFER, texturedata->fbo->FBO); |
1775 | /* TODO: check if texture pixel format allows this operation */ |
1776 | data->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texturedata->texture_type, texturedata->texture, 0); |
1777 | /* Check FBO status */ |
1778 | status = data->glCheckFramebufferStatus(GL_FRAMEBUFFER); |
1779 | if (status != GL_FRAMEBUFFER_COMPLETE) { |
1780 | return SDL_SetError("glFramebufferTexture2D() failed" ); |
1781 | } |
1782 | } |
1783 | return 0; |
1784 | } |
1785 | |
1786 | static void |
1787 | VITA_GLES2_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture) |
1788 | { |
1789 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1790 | VITA_GLES2_TextureData *tdata = (VITA_GLES2_TextureData *)texture->driverdata; |
1791 | |
1792 | VITA_GLES2_ActivateRenderer(renderer); |
1793 | |
1794 | if (data->drawstate.texture == texture) { |
1795 | data->drawstate.texture = NULL; |
1796 | } |
1797 | if (data->drawstate.target == texture) { |
1798 | data->drawstate.target = NULL; |
1799 | } |
1800 | |
1801 | /* Destroy the texture */ |
1802 | if (tdata) { |
1803 | data->glDeleteTextures(1, &tdata->texture); |
1804 | if (tdata->texture_v) { |
1805 | data->glDeleteTextures(1, &tdata->texture_v); |
1806 | } |
1807 | if (tdata->texture_u) { |
1808 | data->glDeleteTextures(1, &tdata->texture_u); |
1809 | } |
1810 | SDL_free(tdata->pixel_data); |
1811 | SDL_free(tdata); |
1812 | texture->driverdata = NULL; |
1813 | } |
1814 | } |
1815 | |
1816 | static int |
1817 | VITA_GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect, |
1818 | Uint32 pixel_format, void * pixels, int pitch) |
1819 | { |
1820 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1821 | Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888; |
1822 | size_t buflen; |
1823 | void *temp_pixels; |
1824 | int temp_pitch; |
1825 | Uint8 *src, *dst, *tmp; |
1826 | int w, h, length, rows; |
1827 | int status; |
1828 | |
1829 | temp_pitch = rect->w * SDL_BYTESPERPIXEL(temp_format); |
1830 | buflen = rect->h * temp_pitch; |
1831 | if (buflen == 0) { |
1832 | return 0; /* nothing to do. */ |
1833 | } |
1834 | |
1835 | temp_pixels = SDL_malloc(buflen); |
1836 | if (!temp_pixels) { |
1837 | return SDL_OutOfMemory(); |
1838 | } |
1839 | |
1840 | SDL_GetRendererOutputSize(renderer, &w, &h); |
1841 | |
1842 | data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h, |
1843 | rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels); |
1844 | if (GL_CheckError("glReadPixels()" , renderer) < 0) { |
1845 | return -1; |
1846 | } |
1847 | |
1848 | /* Flip the rows to be top-down if necessary */ |
1849 | if (!renderer->target) { |
1850 | SDL_bool isstack; |
1851 | length = rect->w * SDL_BYTESPERPIXEL(temp_format); |
1852 | src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch; |
1853 | dst = (Uint8*)temp_pixels; |
1854 | tmp = SDL_small_alloc(Uint8, length, &isstack); |
1855 | rows = rect->h / 2; |
1856 | while (rows--) { |
1857 | SDL_memcpy(tmp, dst, length); |
1858 | SDL_memcpy(dst, src, length); |
1859 | SDL_memcpy(src, tmp, length); |
1860 | dst += temp_pitch; |
1861 | src -= temp_pitch; |
1862 | } |
1863 | SDL_small_free(tmp, isstack); |
1864 | } |
1865 | |
1866 | status = SDL_ConvertPixels(rect->w, rect->h, |
1867 | temp_format, temp_pixels, temp_pitch, |
1868 | pixel_format, pixels, pitch); |
1869 | SDL_free(temp_pixels); |
1870 | |
1871 | return status; |
1872 | } |
1873 | |
1874 | static void |
1875 | VITA_GLES2_RenderPresent(SDL_Renderer *renderer) |
1876 | { |
1877 | /* Tell the video driver to swap buffers */ |
1878 | SDL_GL_SwapWindow(renderer->window); |
1879 | } |
1880 | |
1881 | |
1882 | /************************************************************************************************* |
1883 | * Bind/unbinding of textures |
1884 | *************************************************************************************************/ |
1885 | static int VITA_GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); |
1886 | static int VITA_GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture); |
1887 | |
1888 | static int VITA_GLES2_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh) |
1889 | { |
1890 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1891 | VITA_GLES2_TextureData *texturedata = (VITA_GLES2_TextureData *)texture->driverdata; |
1892 | VITA_GLES2_ActivateRenderer(renderer); |
1893 | |
1894 | data->glBindTexture(texturedata->texture_type, texturedata->texture); |
1895 | data->drawstate.texture = texture; |
1896 | |
1897 | if (texw) { |
1898 | *texw = 1.0; |
1899 | } |
1900 | if (texh) { |
1901 | *texh = 1.0; |
1902 | } |
1903 | |
1904 | return 0; |
1905 | } |
1906 | |
1907 | static int VITA_GLES2_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture) |
1908 | { |
1909 | VITA_GLES2_RenderData *data = (VITA_GLES2_RenderData *)renderer->driverdata; |
1910 | VITA_GLES2_TextureData *texturedata = (VITA_GLES2_TextureData *)texture->driverdata; |
1911 | VITA_GLES2_ActivateRenderer(renderer); |
1912 | |
1913 | data->glBindTexture(texturedata->texture_type, 0); |
1914 | data->drawstate.texture = NULL; |
1915 | |
1916 | return 0; |
1917 | } |
1918 | |
1919 | |
1920 | /************************************************************************************************* |
1921 | * Renderer instantiation * |
1922 | *************************************************************************************************/ |
1923 | |
1924 | static SDL_Renderer * |
1925 | VITA_GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) |
1926 | { |
1927 | SDL_Renderer *renderer; |
1928 | VITA_GLES2_RenderData *data; |
1929 | GLint nFormats; |
1930 | GLboolean hasCompiler; |
1931 | GLint window_framebuffer; |
1932 | GLint value; |
1933 | Uint32 window_flags = 0; |
1934 | |
1935 | window_flags = SDL_GetWindowFlags(window); |
1936 | |
1937 | if (!(window_flags & SDL_WINDOW_OPENGL)) { |
1938 | if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { |
1939 | goto error; |
1940 | } |
1941 | } |
1942 | |
1943 | /* Create the renderer struct */ |
1944 | renderer = (SDL_Renderer *)SDL_calloc(1, sizeof(SDL_Renderer)); |
1945 | if (!renderer) { |
1946 | SDL_OutOfMemory(); |
1947 | goto error; |
1948 | } |
1949 | |
1950 | data = (VITA_GLES2_RenderData *)SDL_calloc(1, sizeof(VITA_GLES2_RenderData)); |
1951 | if (!data) { |
1952 | SDL_free(renderer); |
1953 | SDL_OutOfMemory(); |
1954 | goto error; |
1955 | } |
1956 | |
1957 | renderer->info = VITA_GLES2_RenderDriver.info; |
1958 | renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE); |
1959 | renderer->driverdata = data; |
1960 | renderer->window = window; |
1961 | |
1962 | /* Create an OpenGL ES 2.0 context */ |
1963 | data->context = SDL_GL_CreateContext(window); |
1964 | if (!data->context) { |
1965 | SDL_free(renderer); |
1966 | SDL_free(data); |
1967 | goto error; |
1968 | } |
1969 | if (SDL_GL_MakeCurrent(window, data->context) < 0) { |
1970 | SDL_GL_DeleteContext(data->context); |
1971 | SDL_free(renderer); |
1972 | SDL_free(data); |
1973 | goto error; |
1974 | } |
1975 | |
1976 | if (VITA_GLES2_LoadFunctions(data) < 0) { |
1977 | SDL_GL_DeleteContext(data->context); |
1978 | SDL_free(renderer); |
1979 | SDL_free(data); |
1980 | goto error; |
1981 | } |
1982 | |
1983 | if (flags & SDL_RENDERER_PRESENTVSYNC) { |
1984 | SDL_GL_SetSwapInterval(1); |
1985 | } else { |
1986 | SDL_GL_SetSwapInterval(0); |
1987 | } |
1988 | |
1989 | if (SDL_GL_GetSwapInterval() > 0) { |
1990 | renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; |
1991 | } |
1992 | |
1993 | /* Check for debug output support */ |
1994 | if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_FLAGS, &value) == 0 && |
1995 | (value & SDL_GL_CONTEXT_DEBUG_FLAG)) { |
1996 | data->debug_enabled = SDL_TRUE; |
1997 | } |
1998 | |
1999 | value = 0; |
2000 | data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); |
2001 | renderer->info.max_texture_width = value; |
2002 | value = 0; |
2003 | data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); |
2004 | renderer->info.max_texture_height = value; |
2005 | |
2006 | data->glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &nFormats); |
2007 | hasCompiler = GL_TRUE; |
2008 | if (hasCompiler) { |
2009 | ++nFormats; |
2010 | } |
2011 | |
2012 | data->shader_formats = (GLenum *)SDL_calloc(nFormats, sizeof(GLenum)); |
2013 | if (!data->shader_formats) { |
2014 | VITA_GLES2_DestroyRenderer(renderer); |
2015 | SDL_OutOfMemory(); |
2016 | goto error; |
2017 | } |
2018 | data->shader_format_count = nFormats; |
2019 | data->glGetIntegerv(GL_SHADER_BINARY_FORMATS, (GLint *)data->shader_formats); |
2020 | if (hasCompiler) { |
2021 | data->shader_formats[nFormats - 1] = (GLenum)-1; |
2022 | } |
2023 | |
2024 | /* we keep a few of these and cycle through them, so data can live for a few frames. */ |
2025 | data->glGenBuffers(SDL_arraysize(data->vertex_buffers), data->vertex_buffers); |
2026 | |
2027 | data->framebuffers = NULL; |
2028 | data->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &window_framebuffer); |
2029 | data->window_framebuffer = (GLuint)window_framebuffer; |
2030 | |
2031 | /* Populate the function pointers for the module */ |
2032 | renderer->WindowEvent = VITA_GLES2_WindowEvent; |
2033 | renderer->GetOutputSize = VITA_GLES2_GetOutputSize; |
2034 | renderer->SupportsBlendMode = VITA_GLES2_SupportsBlendMode; |
2035 | renderer->CreateTexture = VITA_GLES2_CreateTexture; |
2036 | renderer->UpdateTexture = VITA_GLES2_UpdateTexture; |
2037 | renderer->UpdateTextureYUV = VITA_GLES2_UpdateTextureYUV; |
2038 | renderer->LockTexture = VITA_GLES2_LockTexture; |
2039 | renderer->UnlockTexture = VITA_GLES2_UnlockTexture; |
2040 | renderer->SetTextureScaleMode = VITA_GLES2_SetTextureScaleMode; |
2041 | renderer->SetRenderTarget = VITA_GLES2_SetRenderTarget; |
2042 | |
2043 | renderer->QueueSetViewport = VITA_GLES2_QueueSetViewport; |
2044 | renderer->QueueSetDrawColor = VITA_GLES2_QueueSetViewport; /* SetViewport and SetDrawColor are (currently) no-ops. */ |
2045 | renderer->QueueDrawPoints = VITA_GLES2_QueueDrawPoints; |
2046 | renderer->QueueDrawLines = VITA_GLES2_QueueDrawPoints; /* lines and points queue vertices the same way. */ |
2047 | renderer->QueueFillRects = VITA_GLES2_QueueFillRects; |
2048 | renderer->QueueCopy = VITA_GLES2_QueueCopy; |
2049 | renderer->QueueCopyEx = VITA_GLES2_QueueCopyEx; |
2050 | renderer->RunCommandQueue = VITA_GLES2_RunCommandQueue; |
2051 | renderer->RenderReadPixels = VITA_GLES2_RenderReadPixels; |
2052 | renderer->RenderPresent = VITA_GLES2_RenderPresent; |
2053 | renderer->DestroyTexture = VITA_GLES2_DestroyTexture; |
2054 | renderer->DestroyRenderer = VITA_GLES2_DestroyRenderer; |
2055 | renderer->GL_BindTexture = VITA_GLES2_BindTexture; |
2056 | renderer->GL_UnbindTexture = VITA_GLES2_UnbindTexture; |
2057 | |
2058 | // TODO. See shaders |
2059 | // renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_YV12; |
2060 | // renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_IYUV; |
2061 | // renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV12; |
2062 | // renderer->info.texture_formats[renderer->info.num_texture_formats++] = SDL_PIXELFORMAT_NV21; |
2063 | |
2064 | /* Set up parameters for rendering */ |
2065 | data->glActiveTexture(GL_TEXTURE0); |
2066 | data->glPixelStorei(GL_PACK_ALIGNMENT, 1); |
2067 | data->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
2068 | |
2069 | data->glEnableVertexAttribArray(VITA_GLES2_ATTRIBUTE_POSITION); |
2070 | data->glDisableVertexAttribArray(VITA_GLES2_ATTRIBUTE_TEXCOORD); |
2071 | |
2072 | data->glClearColor(1.0f, 1.0f, 1.0f, 1.0f); |
2073 | |
2074 | data->drawstate.blend = SDL_BLENDMODE_INVALID; |
2075 | data->drawstate.color = 0xFFFFFFFF; |
2076 | data->drawstate.clear_color = 0xFFFFFFFF; |
2077 | data->drawstate.projection[3][0] = -1.0f; |
2078 | data->drawstate.projection[3][3] = 1.0f; |
2079 | |
2080 | GL_CheckError("" , renderer); |
2081 | |
2082 | return renderer; |
2083 | |
2084 | error: |
2085 | return NULL; |
2086 | } |
2087 | |
2088 | SDL_RenderDriver VITA_GLES2_RenderDriver = { |
2089 | VITA_GLES2_CreateRenderer, |
2090 | { |
2091 | "VITA gles2" , |
2092 | (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE), |
2093 | 4, |
2094 | { |
2095 | SDL_PIXELFORMAT_ARGB8888, |
2096 | SDL_PIXELFORMAT_ABGR8888, |
2097 | SDL_PIXELFORMAT_RGB888, |
2098 | SDL_PIXELFORMAT_BGR888 |
2099 | }, |
2100 | 0, |
2101 | 0 |
2102 | } |
2103 | }; |
2104 | |
2105 | #endif /* SDL_VIDEO_RENDER_VITA_GLES2 && !SDL_RENDER_DISABLED */ |
2106 | |
2107 | /* vi: set ts=4 sw=4 expandtab: */ |
2108 | |