Mercurial > sdl-ios-xcode
comparison src/render/opengles/SDL_render_gles.c @ 5198:bb45ecd958d8
Renamed files for consistency
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 05 Feb 2011 12:01:11 -0800 |
parents | src/render/opengles/SDL_renderer_gles.c@d976b67150c5 |
children | 523409574510 |
comparison
equal
deleted
inserted
replaced
5197:69f47f2c1856 | 5198:bb45ecd958d8 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2010 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 #if SDL_VIDEO_RENDER_OGL_ES | |
25 | |
26 #include "SDL_opengles.h" | |
27 #include "../SDL_sysrender.h" | |
28 | |
29 #if defined(SDL_VIDEO_DRIVER_PANDORA) | |
30 | |
31 /* Empty function stub to get OpenGL ES 1.x support without */ | |
32 /* OpenGL ES extension GL_OES_draw_texture supported */ | |
33 GL_API void GL_APIENTRY | |
34 glDrawTexiOES(GLint x, GLint y, GLint z, GLint width, GLint height) | |
35 { | |
36 return; | |
37 } | |
38 | |
39 #endif /* PANDORA */ | |
40 | |
41 /* OpenGL ES 1.1 renderer implementation, based on the OpenGL renderer */ | |
42 | |
43 /* Used to re-create the window with OpenGL capability */ | |
44 extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); | |
45 | |
46 static const float inv255f = 1.0f / 255.0f; | |
47 | |
48 static SDL_Renderer *GLES_CreateRenderer(SDL_Window * window, Uint32 flags); | |
49 static void GLES_WindowEvent(SDL_Renderer * renderer, | |
50 const SDL_WindowEvent *event); | |
51 static int GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture); | |
52 static int GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
53 const SDL_Rect * rect, const void *pixels, | |
54 int pitch); | |
55 static int GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
56 const SDL_Rect * rect, void **pixels, int *pitch); | |
57 static void GLES_UnlockTexture(SDL_Renderer * renderer, | |
58 SDL_Texture * texture); | |
59 static int GLES_RenderDrawPoints(SDL_Renderer * renderer, | |
60 const SDL_Point * points, int count); | |
61 static int GLES_RenderDrawLines(SDL_Renderer * renderer, | |
62 const SDL_Point * points, int count); | |
63 static int GLES_RenderFillRects(SDL_Renderer * renderer, | |
64 const SDL_Rect ** rects, int count); | |
65 static int GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
66 const SDL_Rect * srcrect, | |
67 const SDL_Rect * dstrect); | |
68 static void GLES_RenderPresent(SDL_Renderer * renderer); | |
69 static void GLES_DestroyTexture(SDL_Renderer * renderer, | |
70 SDL_Texture * texture); | |
71 static void GLES_DestroyRenderer(SDL_Renderer * renderer); | |
72 | |
73 | |
74 SDL_RenderDriver GL_ES_RenderDriver = { | |
75 GLES_CreateRenderer, | |
76 { | |
77 "opengl_es", | |
78 (SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED), | |
79 1, | |
80 {SDL_PIXELFORMAT_ABGR8888}, | |
81 0, | |
82 0} | |
83 }; | |
84 | |
85 typedef struct | |
86 { | |
87 SDL_GLContext context; | |
88 SDL_bool updateSize; | |
89 int blendMode; | |
90 | |
91 #ifndef APIENTRY | |
92 #define APIENTRY | |
93 #endif | |
94 | |
95 SDL_bool useDrawTexture; | |
96 SDL_bool GL_OES_draw_texture_supported; | |
97 | |
98 /* OpenGL ES functions */ | |
99 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params; | |
100 #include "../../video/SDL_glesfuncs.h" | |
101 #undef SDL_PROC | |
102 | |
103 } GLES_RenderData; | |
104 | |
105 typedef struct | |
106 { | |
107 GLuint texture; | |
108 GLenum type; | |
109 GLfloat texw; | |
110 GLfloat texh; | |
111 GLenum format; | |
112 GLenum formattype; | |
113 void *pixels; | |
114 int pitch; | |
115 } GLES_TextureData; | |
116 | |
117 static void | |
118 GLES_SetError(const char *prefix, GLenum result) | |
119 { | |
120 const char *error; | |
121 | |
122 switch (result) { | |
123 case GL_NO_ERROR: | |
124 error = "GL_NO_ERROR"; | |
125 break; | |
126 case GL_INVALID_ENUM: | |
127 error = "GL_INVALID_ENUM"; | |
128 break; | |
129 case GL_INVALID_VALUE: | |
130 error = "GL_INVALID_VALUE"; | |
131 break; | |
132 case GL_INVALID_OPERATION: | |
133 error = "GL_INVALID_OPERATION"; | |
134 break; | |
135 case GL_STACK_OVERFLOW: | |
136 error = "GL_STACK_OVERFLOW"; | |
137 break; | |
138 case GL_STACK_UNDERFLOW: | |
139 error = "GL_STACK_UNDERFLOW"; | |
140 break; | |
141 case GL_OUT_OF_MEMORY: | |
142 error = "GL_OUT_OF_MEMORY"; | |
143 break; | |
144 default: | |
145 error = "UNKNOWN"; | |
146 break; | |
147 } | |
148 SDL_SetError("%s: %s", prefix, error); | |
149 } | |
150 | |
151 static int | |
152 GLES_LoadFunctions(GLES_RenderData * data) | |
153 { | |
154 | |
155 #define SDL_PROC(ret,func,params) \ | |
156 data->func = func; | |
157 #include "../../video/SDL_glesfuncs.h" | |
158 #undef SDL_PROC | |
159 | |
160 return 0; | |
161 } | |
162 | |
163 SDL_Renderer * | |
164 GLES_CreateRenderer(SDL_Window * window, Uint32 flags) | |
165 { | |
166 | |
167 SDL_Renderer *renderer; | |
168 GLES_RenderData *data; | |
169 GLint value; | |
170 Uint32 window_flags; | |
171 | |
172 window_flags = SDL_GetWindowFlags(window); | |
173 if (!(window_flags & SDL_WINDOW_OPENGL)) { | |
174 if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { | |
175 return NULL; | |
176 } | |
177 } | |
178 | |
179 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer)); | |
180 if (!renderer) { | |
181 SDL_OutOfMemory(); | |
182 return NULL; | |
183 } | |
184 | |
185 data = (GLES_RenderData *) SDL_calloc(1, sizeof(*data)); | |
186 if (!data) { | |
187 GLES_DestroyRenderer(renderer); | |
188 SDL_OutOfMemory(); | |
189 return NULL; | |
190 } | |
191 | |
192 renderer->WindowEvent = GLES_WindowEvent; | |
193 renderer->CreateTexture = GLES_CreateTexture; | |
194 renderer->UpdateTexture = GLES_UpdateTexture; | |
195 renderer->LockTexture = GLES_LockTexture; | |
196 renderer->UnlockTexture = GLES_UnlockTexture; | |
197 renderer->RenderDrawPoints = GLES_RenderDrawPoints; | |
198 renderer->RenderDrawLines = GLES_RenderDrawLines; | |
199 renderer->RenderFillRects = GLES_RenderFillRects; | |
200 renderer->RenderCopy = GLES_RenderCopy; | |
201 renderer->RenderPresent = GLES_RenderPresent; | |
202 renderer->DestroyTexture = GLES_DestroyTexture; | |
203 renderer->DestroyRenderer = GLES_DestroyRenderer; | |
204 renderer->info = GL_ES_RenderDriver.info; | |
205 renderer->driverdata = data; | |
206 | |
207 renderer->info.flags = SDL_RENDERER_ACCELERATED; | |
208 | |
209 if (GLES_LoadFunctions(data) < 0) { | |
210 GLES_DestroyRenderer(renderer); | |
211 return NULL; | |
212 } | |
213 | |
214 data->context = SDL_GL_CreateContext(window); | |
215 if (!data->context) { | |
216 GLES_DestroyRenderer(renderer); | |
217 return NULL; | |
218 } | |
219 if (SDL_GL_MakeCurrent(window, data->context) < 0) { | |
220 GLES_DestroyRenderer(renderer); | |
221 return NULL; | |
222 } | |
223 | |
224 if (flags & SDL_RENDERER_PRESENTVSYNC) { | |
225 SDL_GL_SetSwapInterval(1); | |
226 } else { | |
227 SDL_GL_SetSwapInterval(0); | |
228 } | |
229 if (SDL_GL_GetSwapInterval() > 0) { | |
230 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC; | |
231 } | |
232 | |
233 #if SDL_VIDEO_DRIVER_PANDORA | |
234 data->GL_OES_draw_texture_supported = SDL_FALSE; | |
235 data->useDrawTexture = SDL_FALSE; | |
236 #else | |
237 if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) { | |
238 data->GL_OES_draw_texture_supported = SDL_TRUE; | |
239 data->useDrawTexture = SDL_TRUE; | |
240 } else { | |
241 data->GL_OES_draw_texture_supported = SDL_FALSE; | |
242 data->useDrawTexture = SDL_FALSE; | |
243 } | |
244 #endif | |
245 | |
246 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); | |
247 renderer->info.max_texture_width = value; | |
248 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value); | |
249 renderer->info.max_texture_height = value; | |
250 | |
251 /* Set up parameters for rendering */ | |
252 data->blendMode = -1; | |
253 data->glDisable(GL_DEPTH_TEST); | |
254 data->glDisable(GL_CULL_FACE); | |
255 data->updateSize = SDL_TRUE; | |
256 | |
257 data->glEnableClientState(GL_VERTEX_ARRAY); | |
258 data->glEnableClientState(GL_TEXTURE_COORD_ARRAY); | |
259 | |
260 return renderer; | |
261 } | |
262 | |
263 static SDL_GLContext SDL_CurrentContext = NULL; | |
264 | |
265 static int | |
266 GLES_ActivateRenderer(SDL_Renderer * renderer) | |
267 { | |
268 | |
269 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
270 SDL_Window *window = renderer->window; | |
271 | |
272 if (SDL_CurrentContext != data->context) { | |
273 if (SDL_GL_MakeCurrent(window, data->context) < 0) { | |
274 return -1; | |
275 } | |
276 SDL_CurrentContext = data->context; | |
277 } | |
278 if (data->updateSize) { | |
279 int w, h; | |
280 | |
281 SDL_GetWindowSize(window, &w, &h); | |
282 data->glMatrixMode(GL_PROJECTION); | |
283 data->glLoadIdentity(); | |
284 data->glMatrixMode(GL_MODELVIEW); | |
285 data->glLoadIdentity(); | |
286 data->glViewport(0, 0, w, h); | |
287 data->glOrthof(0.0, (GLfloat) w, (GLfloat) h, 0.0, 0.0, 1.0); | |
288 data->updateSize = SDL_FALSE; | |
289 } | |
290 return 0; | |
291 } | |
292 | |
293 static void | |
294 GLES_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) | |
295 { | |
296 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
297 | |
298 if (event->event == SDL_WINDOWEVENT_RESIZED) { | |
299 /* Rebind the context to the window area and update matrices */ | |
300 SDL_CurrentContext = NULL; | |
301 data->updateSize = SDL_TRUE; | |
302 } | |
303 } | |
304 | |
305 static __inline__ int | |
306 power_of_2(int input) | |
307 { | |
308 int value = 1; | |
309 | |
310 while (value < input) { | |
311 value <<= 1; | |
312 } | |
313 return value; | |
314 } | |
315 | |
316 static int | |
317 GLES_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
318 { | |
319 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; | |
320 GLES_TextureData *data; | |
321 GLint internalFormat; | |
322 GLenum format, type; | |
323 int texture_w, texture_h; | |
324 GLenum result; | |
325 | |
326 GLES_ActivateRenderer(renderer); | |
327 | |
328 switch (texture->format) { | |
329 case SDL_PIXELFORMAT_ABGR8888: | |
330 internalFormat = GL_RGBA; | |
331 format = GL_RGBA; | |
332 type = GL_UNSIGNED_BYTE; | |
333 break; | |
334 default: | |
335 SDL_SetError("Texture format %s not supported by OpenGL ES", | |
336 SDL_GetPixelFormatName(texture->format)); | |
337 return -1; | |
338 } | |
339 | |
340 data = (GLES_TextureData *) SDL_calloc(1, sizeof(*data)); | |
341 if (!data) { | |
342 SDL_OutOfMemory(); | |
343 return -1; | |
344 } | |
345 | |
346 if (texture->access == SDL_TEXTUREACCESS_STREAMING) { | |
347 data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format); | |
348 data->pixels = SDL_malloc(texture->h * data->pitch); | |
349 if (!data->pixels) { | |
350 SDL_OutOfMemory(); | |
351 SDL_free(data); | |
352 return -1; | |
353 } | |
354 } | |
355 | |
356 texture->driverdata = data; | |
357 | |
358 renderdata->glGetError(); | |
359 renderdata->glEnable(GL_TEXTURE_2D); | |
360 renderdata->glGenTextures(1, &data->texture); | |
361 | |
362 data->type = GL_TEXTURE_2D; | |
363 /* no NPOV textures allowed in OpenGL ES (yet) */ | |
364 texture_w = power_of_2(texture->w); | |
365 texture_h = power_of_2(texture->h); | |
366 data->texw = (GLfloat) texture->w / texture_w; | |
367 data->texh = (GLfloat) texture->h / texture_h; | |
368 | |
369 data->format = format; | |
370 data->formattype = type; | |
371 renderdata->glBindTexture(data->type, data->texture); | |
372 renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER, | |
373 GL_LINEAR); | |
374 renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER, | |
375 GL_LINEAR); | |
376 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S, | |
377 GL_CLAMP_TO_EDGE); | |
378 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T, | |
379 GL_CLAMP_TO_EDGE); | |
380 | |
381 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w, | |
382 texture_h, 0, format, type, NULL); | |
383 renderdata->glDisable(GL_TEXTURE_2D); | |
384 | |
385 result = renderdata->glGetError(); | |
386 if (result != GL_NO_ERROR) { | |
387 GLES_SetError("glTexImage2D()", result); | |
388 return -1; | |
389 } | |
390 return 0; | |
391 } | |
392 | |
393 static void | |
394 SetupTextureUpdate(GLES_RenderData * renderdata, SDL_Texture * texture, | |
395 int pitch) | |
396 { | |
397 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |
398 } | |
399 | |
400 static int | |
401 GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
402 const SDL_Rect * rect, const void *pixels, int pitch) | |
403 { | |
404 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; | |
405 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; | |
406 GLenum result; | |
407 int bpp = SDL_BYTESPERPIXEL(texture->format); | |
408 void * temp_buffer; | |
409 void * temp_ptr; | |
410 int i; | |
411 | |
412 GLES_ActivateRenderer(renderer); | |
413 | |
414 renderdata->glGetError(); | |
415 SetupTextureUpdate(renderdata, texture, pitch); | |
416 renderdata->glEnable(data->type); | |
417 renderdata->glBindTexture(data->type, data->texture); | |
418 | |
419 if( rect->w * bpp == pitch ) { | |
420 temp_buffer = (void *)pixels; /* No need to reformat */ | |
421 } else { | |
422 /* Reformatting of mem area required */ | |
423 temp_buffer = SDL_malloc(rect->w * rect->h * bpp); | |
424 temp_ptr = temp_buffer; | |
425 for (i = 0; i < rect->h; i++) { | |
426 SDL_memcpy(temp_ptr, pixels, rect->w * bpp); | |
427 temp_ptr += rect->w * bpp; | |
428 pixels += pitch; | |
429 } | |
430 } | |
431 | |
432 renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w, | |
433 rect->h, data->format, data->formattype, | |
434 temp_buffer); | |
435 | |
436 if( temp_buffer != pixels ) { | |
437 SDL_free(temp_buffer); | |
438 } | |
439 | |
440 renderdata->glDisable(data->type); | |
441 result = renderdata->glGetError(); | |
442 if (result != GL_NO_ERROR) { | |
443 GLES_SetError("glTexSubImage2D()", result); | |
444 return -1; | |
445 } | |
446 return 0; | |
447 } | |
448 | |
449 static int | |
450 GLES_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, | |
451 const SDL_Rect * rect, void **pixels, int *pitch) | |
452 { | |
453 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; | |
454 | |
455 *pixels = | |
456 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch + | |
457 rect->x * SDL_BYTESPERPIXEL(texture->format)); | |
458 *pitch = data->pitch; | |
459 return 0; | |
460 } | |
461 | |
462 static void | |
463 GLES_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
464 { | |
465 GLES_RenderData *renderdata = (GLES_RenderData *) renderer->driverdata; | |
466 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; | |
467 | |
468 GLES_ActivateRenderer(renderer); | |
469 | |
470 SetupTextureUpdate(renderdata, texture, data->pitch); | |
471 renderdata->glEnable(data->type); | |
472 renderdata->glBindTexture(data->type, data->texture); | |
473 renderdata->glTexSubImage2D(data->type, 0, 0, 0, texture->w, | |
474 texture->h, data->format, data->formattype, | |
475 data->pixels); | |
476 renderdata->glDisable(data->type); | |
477 } | |
478 | |
479 static void | |
480 GLES_SetBlendMode(GLES_RenderData * data, int blendMode) | |
481 { | |
482 if (blendMode != data->blendMode) { | |
483 switch (blendMode) { | |
484 case SDL_BLENDMODE_NONE: | |
485 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); | |
486 data->glDisable(GL_BLEND); | |
487 break; | |
488 case SDL_BLENDMODE_BLEND: | |
489 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |
490 data->glEnable(GL_BLEND); | |
491 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
492 break; | |
493 case SDL_BLENDMODE_ADD: | |
494 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |
495 data->glEnable(GL_BLEND); | |
496 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE); | |
497 break; | |
498 case SDL_BLENDMODE_MOD: | |
499 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); | |
500 data->glEnable(GL_BLEND); | |
501 data->glBlendFunc(GL_ZERO, GL_SRC_COLOR); | |
502 break; | |
503 } | |
504 data->blendMode = blendMode; | |
505 } | |
506 } | |
507 | |
508 static int | |
509 GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points, | |
510 int count) | |
511 { | |
512 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
513 int i; | |
514 GLshort *vertices; | |
515 | |
516 GLES_ActivateRenderer(renderer); | |
517 | |
518 GLES_SetBlendMode(data, renderer->blendMode); | |
519 | |
520 data->glColor4f((GLfloat) renderer->r * inv255f, | |
521 (GLfloat) renderer->g * inv255f, | |
522 (GLfloat) renderer->b * inv255f, | |
523 (GLfloat) renderer->a * inv255f); | |
524 | |
525 vertices = SDL_stack_alloc(GLshort, count*2); | |
526 for (i = 0; i < count; ++i) { | |
527 vertices[2*i+0] = (GLshort)points[i].x; | |
528 vertices[2*i+1] = (GLshort)points[i].y; | |
529 } | |
530 data->glVertexPointer(2, GL_SHORT, 0, vertices); | |
531 data->glDrawArrays(GL_POINTS, 0, count); | |
532 SDL_stack_free(vertices); | |
533 | |
534 return 0; | |
535 } | |
536 | |
537 static int | |
538 GLES_RenderDrawLines(SDL_Renderer * renderer, const SDL_Point * points, | |
539 int count) | |
540 { | |
541 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
542 int i; | |
543 GLshort *vertices; | |
544 | |
545 GLES_ActivateRenderer(renderer); | |
546 | |
547 GLES_SetBlendMode(data, renderer->blendMode); | |
548 | |
549 data->glColor4f((GLfloat) renderer->r * inv255f, | |
550 (GLfloat) renderer->g * inv255f, | |
551 (GLfloat) renderer->b * inv255f, | |
552 (GLfloat) renderer->a * inv255f); | |
553 | |
554 vertices = SDL_stack_alloc(GLshort, count*2); | |
555 for (i = 0; i < count; ++i) { | |
556 vertices[2*i+0] = (GLshort)points[i].x; | |
557 vertices[2*i+1] = (GLshort)points[i].y; | |
558 } | |
559 data->glVertexPointer(2, GL_SHORT, 0, vertices); | |
560 if (count > 2 && | |
561 points[0].x == points[count-1].x && points[0].y == points[count-1].y) { | |
562 /* GL_LINE_LOOP takes care of the final segment */ | |
563 --count; | |
564 data->glDrawArrays(GL_LINE_LOOP, 0, count); | |
565 } else { | |
566 data->glDrawArrays(GL_LINE_STRIP, 0, count); | |
567 } | |
568 SDL_stack_free(vertices); | |
569 | |
570 return 0; | |
571 } | |
572 | |
573 static int | |
574 GLES_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects, | |
575 int count) | |
576 { | |
577 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
578 int i; | |
579 | |
580 GLES_ActivateRenderer(renderer); | |
581 | |
582 GLES_SetBlendMode(data, renderer->blendMode); | |
583 | |
584 data->glColor4f((GLfloat) renderer->r * inv255f, | |
585 (GLfloat) renderer->g * inv255f, | |
586 (GLfloat) renderer->b * inv255f, | |
587 (GLfloat) renderer->a * inv255f); | |
588 | |
589 for (i = 0; i < count; ++i) { | |
590 const SDL_Rect *rect = rects[i]; | |
591 GLshort minx = rect->x; | |
592 GLshort maxx = rect->x + rect->w; | |
593 GLshort miny = rect->y; | |
594 GLshort maxy = rect->y + rect->h; | |
595 GLshort vertices[8]; | |
596 vertices[0] = minx; | |
597 vertices[1] = miny; | |
598 vertices[2] = maxx; | |
599 vertices[3] = miny; | |
600 vertices[4] = minx; | |
601 vertices[5] = maxy; | |
602 vertices[6] = maxx; | |
603 vertices[7] = maxy; | |
604 | |
605 data->glVertexPointer(2, GL_SHORT, 0, vertices); | |
606 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
607 } | |
608 | |
609 return 0; | |
610 } | |
611 | |
612 static int | |
613 GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture, | |
614 const SDL_Rect * srcrect, const SDL_Rect * dstrect) | |
615 { | |
616 | |
617 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
618 GLES_TextureData *texturedata = (GLES_TextureData *) texture->driverdata; | |
619 int minx, miny, maxx, maxy; | |
620 GLfloat minu, maxu, minv, maxv; | |
621 int i; | |
622 void *temp_buffer; /* used for reformatting dirty rect pixels */ | |
623 void *temp_ptr; | |
624 | |
625 GLES_ActivateRenderer(renderer); | |
626 | |
627 data->glEnable(GL_TEXTURE_2D); | |
628 | |
629 data->glBindTexture(texturedata->type, texturedata->texture); | |
630 | |
631 if (texture->modMode) { | |
632 data->glColor4f((GLfloat) texture->r * inv255f, | |
633 (GLfloat) texture->g * inv255f, | |
634 (GLfloat) texture->b * inv255f, | |
635 (GLfloat) texture->a * inv255f); | |
636 } else { | |
637 data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | |
638 } | |
639 | |
640 GLES_SetBlendMode(data, texture->blendMode); | |
641 | |
642 if (data->GL_OES_draw_texture_supported && data->useDrawTexture) { | |
643 /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */ | |
644 GLint cropRect[4]; | |
645 int w, h; | |
646 SDL_Window *window = renderer->window; | |
647 | |
648 SDL_GetWindowSize(window, &w, &h); | |
649 cropRect[0] = srcrect->x; | |
650 cropRect[1] = srcrect->y + srcrect->h; | |
651 cropRect[2] = srcrect->w; | |
652 cropRect[3] = -srcrect->h; | |
653 data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, | |
654 cropRect); | |
655 data->glDrawTexiOES(dstrect->x, h - dstrect->y - dstrect->h, 0, | |
656 dstrect->w, dstrect->h); | |
657 } else { | |
658 | |
659 minx = dstrect->x; | |
660 miny = dstrect->y; | |
661 maxx = dstrect->x + dstrect->w; | |
662 maxy = dstrect->y + dstrect->h; | |
663 | |
664 minu = (GLfloat) srcrect->x / texture->w; | |
665 minu *= texturedata->texw; | |
666 maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w; | |
667 maxu *= texturedata->texw; | |
668 minv = (GLfloat) srcrect->y / texture->h; | |
669 minv *= texturedata->texh; | |
670 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h; | |
671 maxv *= texturedata->texh; | |
672 | |
673 GLshort vertices[8]; | |
674 GLfloat texCoords[8]; | |
675 | |
676 vertices[0] = minx; | |
677 vertices[1] = miny; | |
678 vertices[2] = maxx; | |
679 vertices[3] = miny; | |
680 vertices[4] = minx; | |
681 vertices[5] = maxy; | |
682 vertices[6] = maxx; | |
683 vertices[7] = maxy; | |
684 | |
685 texCoords[0] = minu; | |
686 texCoords[1] = minv; | |
687 texCoords[2] = maxu; | |
688 texCoords[3] = minv; | |
689 texCoords[4] = minu; | |
690 texCoords[5] = maxv; | |
691 texCoords[6] = maxu; | |
692 texCoords[7] = maxv; | |
693 | |
694 data->glVertexPointer(2, GL_SHORT, 0, vertices); | |
695 data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords); | |
696 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | |
697 } | |
698 | |
699 data->glDisable(GL_TEXTURE_2D); | |
700 | |
701 return 0; | |
702 } | |
703 | |
704 static void | |
705 GLES_RenderPresent(SDL_Renderer * renderer) | |
706 { | |
707 GLES_ActivateRenderer(renderer); | |
708 | |
709 SDL_GL_SwapWindow(renderer->window); | |
710 } | |
711 | |
712 static void | |
713 GLES_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture) | |
714 { | |
715 GLES_TextureData *data = (GLES_TextureData *) texture->driverdata; | |
716 | |
717 GLES_ActivateRenderer(renderer); | |
718 | |
719 if (!data) { | |
720 return; | |
721 } | |
722 if (data->texture) { | |
723 glDeleteTextures(1, &data->texture); | |
724 } | |
725 if (data->pixels) { | |
726 SDL_free(data->pixels); | |
727 } | |
728 SDL_free(data); | |
729 texture->driverdata = NULL; | |
730 } | |
731 | |
732 static void | |
733 GLES_DestroyRenderer(SDL_Renderer * renderer) | |
734 { | |
735 GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; | |
736 | |
737 if (data) { | |
738 if (data->context) { | |
739 SDL_GL_DeleteContext(data->context); | |
740 } | |
741 SDL_free(data); | |
742 } | |
743 SDL_free(renderer); | |
744 } | |
745 | |
746 #endif /* SDL_VIDEO_RENDER_OGL_ES */ | |
747 | |
748 /* vi: set ts=4 sw=4 expandtab: */ |