comparison src/video/glesrenderer/SDL_renderer_gles.c @ 2359:b70b96e615d2 gsoc2008_iphone

These files are the OpenGL ES render driver. You should be able to use them on any platform that supports OpenGL ES -- not just iPhone. The driver is based off the OpenGL render driver. There are a few differences between OpenGL and OpenGL ES that present difficulties for this driver: - OpenGL ES does NOT support many pixel formats (for example, no GL_BGR). Also, when using texture functions format and internalFormat must be the same -- this means 32 bit packed formats like SDL_PIXELFORMAT_BGR888 cannot be automatically converted to GL_RGB (which is 24bpp). - OpenGL ES doesn't have GL_PACK_ROW_LENGTH, which means data must be reformatted before uploading changes to dirty rects. This change has been added. - OpenGL ES doesn't support paletted textures, though there is an extension. I'm looking into this. Some other notable differences: - OpenGL ES has an extension called GL_OES_draw_texture which allows for quicker 2D sprite-type drawing. I use this in GL_RenderCopy when it is available. The iPhone supports the extension, but the iPhone Simulator does not (presently). - No glBegin() / glEnd() and no GL_QUADS! I'm using glDrawArrays with GL_TRIANGLE_STRIP instead!
author Holmes Futrell <hfutrell@umail.ucsb.edu>
date Thu, 17 Jul 2008 23:31:42 +0000
parents
children aad0c5ccf6bb
comparison
equal deleted inserted replaced
2358:da266ae53b98 2359:b70b96e615d2
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2006 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_video.h"
27 #include "SDL_opengles.h"
28 #include "SDL_sysvideo.h"
29 #include "SDL_pixels_c.h"
30 #include "SDL_rect_c.h"
31 #include "SDL_yuv_sw_c.h"
32
33 /* OpenGL ES 1.1 renderer implementation */
34
35 static const float inv255f = 1.0f / 255.0f;
36
37 static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
38 static int GL_ActivateRenderer(SDL_Renderer * renderer);
39 static int GL_DisplayModeChanged(SDL_Renderer * renderer);
40 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
41 static int GL_QueryTexturePixels(SDL_Renderer * renderer,
42 SDL_Texture * texture, void **pixels,
43 int *pitch);
44 static int GL_SetTexturePalette(SDL_Renderer * renderer,
45 SDL_Texture * texture,
46 const SDL_Color * colors, int firstcolor,
47 int ncolors);
48 static int GL_GetTexturePalette(SDL_Renderer * renderer,
49 SDL_Texture * texture, SDL_Color * colors,
50 int firstcolor, int ncolors);
51 static int GL_SetTextureColorMod(SDL_Renderer * renderer,
52 SDL_Texture * texture);
53 static int GL_SetTextureAlphaMod(SDL_Renderer * renderer,
54 SDL_Texture * texture);
55 static int GL_SetTextureBlendMode(SDL_Renderer * renderer,
56 SDL_Texture * texture);
57 static int GL_SetTextureScaleMode(SDL_Renderer * renderer,
58 SDL_Texture * texture);
59 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
60 const SDL_Rect * rect, const void *pixels,
61 int pitch);
62 static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
63 const SDL_Rect * rect, int markDirty, void **pixels,
64 int *pitch);
65 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
66 static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
67 int numrects, const SDL_Rect * rects);
68 static int GL_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
69 Uint8 a, const SDL_Rect * rect);
70 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
71 const SDL_Rect * srcrect, const SDL_Rect * dstrect);
72 static void GL_RenderPresent(SDL_Renderer * renderer);
73 static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
74 static void GL_DestroyRenderer(SDL_Renderer * renderer);
75
76
77 SDL_RenderDriver GL_ES_RenderDriver = {
78 GL_CreateRenderer,
79 {
80 "opengl_es",
81 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
82 SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
83 (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
84 SDL_TEXTUREMODULATE_ALPHA),
85 (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
86 SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
87 SDL_TEXTUREBLENDMODE_MOD),
88 (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
89 SDL_TEXTURESCALEMODE_SLOW),
90 #ifdef GL_IMG_texture_format_BGRA8888
91 3,
92 #else
93 2,
94 #endif
95 {
96 #ifdef GL_IMG_texture_format_BGRA8888
97 SDL_PIXELFORMAT_ARGB8888,
98 #endif
99 SDL_PIXELFORMAT_RGB24,
100 SDL_PIXELFORMAT_ABGR8888,
101 },
102 0,
103 0}
104 };
105
106 typedef struct
107 {
108 SDL_GLContext context;
109 SDL_bool updateSize;
110 int blendMode;
111 int scaleMode;
112
113 #ifndef APIENTRY
114 #define APIENTRY
115 #endif
116
117 SDL_bool useDrawTexture;
118 SDL_bool GL_OES_draw_texture_supported;
119
120 /* OpenGL ES functions */
121 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
122 #include "SDL_glesfuncs.h"
123 #undef SDL_PROC
124
125 } GL_RenderData;
126
127 typedef struct
128 {
129 GLuint texture;
130 GLenum type;
131 GLfloat texw;
132 GLfloat texh;
133 GLenum format;
134 GLenum formattype;
135 void *pixels;
136 int pitch;
137 SDL_DirtyRectList dirty;
138 } GL_TextureData;
139
140 static void
141 GL_SetError(const char *prefix, GLenum result)
142 {
143 const char *error;
144
145 switch (result) {
146 case GL_NO_ERROR:
147 error = "GL_NO_ERROR";
148 break;
149 case GL_INVALID_ENUM:
150 error = "GL_INVALID_ENUM";
151 break;
152 case GL_INVALID_VALUE:
153 error = "GL_INVALID_VALUE";
154 break;
155 case GL_INVALID_OPERATION:
156 error = "GL_INVALID_OPERATION";
157 break;
158 case GL_STACK_OVERFLOW:
159 error = "GL_STACK_OVERFLOW";
160 break;
161 case GL_STACK_UNDERFLOW:
162 error = "GL_STACK_UNDERFLOW";
163 break;
164 case GL_OUT_OF_MEMORY:
165 error = "GL_OUT_OF_MEMORY";
166 break;
167 default:
168 error = "UNKNOWN";
169 break;
170 }
171 SDL_SetError("%s: %s", prefix, error);
172 }
173
174 static int
175 GL_LoadFunctions(GL_RenderData * data)
176 {
177
178 #define SDL_PROC(ret,func,params) \
179 data->func = func;
180 #include "SDL_glesfuncs.h"
181 #undef SDL_PROC
182
183 return 0;
184 }
185
186 void
187 GL_AddRenderDriver(_THIS)
188 {
189 if (_this->GL_CreateContext) {
190 SDL_AddRenderDriver(0, &GL_ES_RenderDriver);
191 }
192 }
193
194 SDL_Renderer *
195 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
196 {
197
198 printf("gl(es) create renderer ...\n");
199
200 SDL_Renderer *renderer;
201 GL_RenderData *data;
202 GLint value;
203 int doublebuffer;
204
205 if (!(window->flags & SDL_WINDOW_OPENGL)) {
206 if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
207 return NULL;
208 }
209 }
210
211 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
212 if (!renderer) {
213 SDL_OutOfMemory();
214 return NULL;
215 }
216
217 data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
218 if (!data) {
219 GL_DestroyRenderer(renderer);
220 SDL_OutOfMemory();
221 return NULL;
222 }
223
224 renderer->ActivateRenderer = GL_ActivateRenderer;
225 renderer->DisplayModeChanged = GL_DisplayModeChanged;
226 renderer->CreateTexture = GL_CreateTexture;
227 renderer->QueryTexturePixels = GL_QueryTexturePixels;
228 renderer->SetTexturePalette = GL_SetTexturePalette;
229 renderer->GetTexturePalette = GL_GetTexturePalette;
230 renderer->SetTextureColorMod = GL_SetTextureColorMod;
231 renderer->SetTextureAlphaMod = GL_SetTextureAlphaMod;
232 renderer->SetTextureBlendMode = GL_SetTextureBlendMode;
233 renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
234 renderer->UpdateTexture = GL_UpdateTexture;
235 renderer->LockTexture = GL_LockTexture;
236 renderer->UnlockTexture = GL_UnlockTexture;
237 renderer->DirtyTexture = GL_DirtyTexture;
238 renderer->RenderFill = GL_RenderFill;
239 renderer->RenderCopy = GL_RenderCopy;
240 renderer->RenderPresent = GL_RenderPresent;
241 renderer->DestroyTexture = GL_DestroyTexture;
242 renderer->DestroyRenderer = GL_DestroyRenderer;
243 renderer->info = GL_ES_RenderDriver.info;
244 renderer->window = window->id;
245 renderer->driverdata = data;
246
247
248 renderer->info.flags = (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
249
250 if (GL_LoadFunctions(data) < 0) {
251 GL_DestroyRenderer(renderer);
252 return NULL;
253 }
254
255 data->context = SDL_GL_CreateContext(window->id);
256 if (!data->context) {
257 GL_DestroyRenderer(renderer);
258 return NULL;
259 }
260 if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
261 GL_DestroyRenderer(renderer);
262 return NULL;
263 }
264
265 if (flags & SDL_RENDERER_PRESENTVSYNC) {
266 SDL_GL_SetSwapInterval(1);
267 } else {
268 SDL_GL_SetSwapInterval(0);
269 }
270 if (SDL_GL_GetSwapInterval() > 0) {
271 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
272 }
273
274 if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
275 if (!doublebuffer) {
276 renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
277 }
278 }
279
280 if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
281 printf("using draw texture\n");
282 data->GL_OES_draw_texture_supported = SDL_TRUE;
283 data->useDrawTexture = SDL_TRUE;
284 }
285 else {
286 printf("not using draw texture\n");
287 data->GL_OES_draw_texture_supported = SDL_FALSE;
288 data->useDrawTexture = SDL_FALSE;
289 }
290
291 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
292 renderer->info.max_texture_width = value;
293 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
294 renderer->info.max_texture_height = value;
295
296 /* Set up parameters for rendering */
297 data->blendMode = -1;
298 data->scaleMode = -1;
299 data->glDisable(GL_DEPTH_TEST);
300 data->glDisable(GL_CULL_FACE);
301 data->glEnable(GL_TEXTURE_2D);
302 data->updateSize = SDL_TRUE;
303
304 return renderer;
305 }
306
307 static int GL_ActivateRenderer(SDL_Renderer * renderer)
308 {
309
310 GL_RenderData *data = (GL_RenderData *)renderer->driverdata;
311 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
312
313 if (data->context == NULL) {
314 printf("Context is null, dude\n");
315 }
316
317 if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
318 return -1;
319 }
320 if (data->updateSize) {
321 data->glMatrixMode(GL_PROJECTION);
322 data->glLoadIdentity();
323 data->glMatrixMode(GL_MODELVIEW);
324 data->glLoadIdentity();
325 data->glViewport(0, 0, window->w, window->h);
326 data->glOrthof(0.0, (GLfloat)window->w, (GLfloat)window->h, 0.0,
327 0.0, 1.0);
328 data->updateSize = SDL_FALSE;
329 }
330 return 0;
331 }
332
333 static int
334 GL_DisplayModeChanged(SDL_Renderer * renderer)
335 {
336 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
337
338 data->updateSize = SDL_TRUE;
339 return 0;
340 }
341
342 static __inline__ int
343 power_of_2(int input)
344 {
345 int value = 1;
346
347 while (value < input) {
348 value <<= 1;
349 }
350 return value;
351 }
352
353 static int
354 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
355 {
356 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
357 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
358 GL_TextureData *data;
359 GLint internalFormat;
360 GLenum format, type;
361 int texture_w, texture_h;
362 GLenum result;
363 switch (texture->format) {
364 case SDL_PIXELFORMAT_INDEX1LSB:
365 case SDL_PIXELFORMAT_INDEX1MSB:
366 case SDL_PIXELFORMAT_INDEX8:
367 case SDL_PIXELFORMAT_RGB332:
368 case SDL_PIXELFORMAT_RGB444:
369 case SDL_PIXELFORMAT_RGB555:
370 case SDL_PIXELFORMAT_ARGB4444:
371 case SDL_PIXELFORMAT_ARGB1555:
372 case SDL_PIXELFORMAT_BGR24:
373 case SDL_PIXELFORMAT_BGR888: /* can't convert 32 bit format to 24 */
374 case SDL_PIXELFORMAT_RGB888:
375 case SDL_PIXELFORMAT_RGBA8888:
376 case SDL_PIXELFORMAT_ARGB2101010:
377 SDL_SetError("Unsupported format");
378 return -1;
379 case SDL_PIXELFORMAT_ARGB8888:
380 #ifdef GL_IMG_texture_format_BGRA8888
381 internalFormat = GL_RGBA;
382 format = GL_RGBA;
383 type = GL_UNSIGNED_BYTE;
384 break;
385 #else
386 SDL_SetError("Unsupported format");
387 return -1;
388 #endif
389 case SDL_PIXELFORMAT_RGB24:
390 internalFormat = GL_RGB;
391 format = GL_RGB;
392 type = GL_UNSIGNED_BYTE;
393 break;
394 case SDL_PIXELFORMAT_ABGR8888:
395 internalFormat = GL_RGBA;
396 format = GL_RGBA;
397 type = GL_UNSIGNED_BYTE;
398 break;
399 /*
400 These formats would be supported if SDL had the necessary pixel formats
401 case SDL_PIXELFORMAT_BGR565:
402 internalFormat = GL_RGB;
403 format = GL_RGB;
404 type = GL_UNSIGNED_SHORT_5_6_5;
405 break;
406 case SDL_PIXELFORMAT_ABGR5551:
407 internalFormat = GL_RGBA;
408 format = GL_RGBA;
409 type = GL_UNSIGNED_SHORT_5_5_5_1;
410 break;
411 case SDL_PIXELFORMAT_ABGR4444:
412 internalFormat = GL_RGBA;
413 format = GL_RGBA;
414 type = GL_UNSIGNED_SHORT_4_4_4_4;
415 break;
416 */
417 default:
418 SDL_SetError("Unsupported texture format");
419 return -1;
420 }
421 data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
422 if (!data) {
423 SDL_OutOfMemory();
424 return -1;
425 }
426
427 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
428 data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
429 data->pixels = SDL_malloc(texture->h * data->pitch);
430 if (!data->pixels) {
431 SDL_OutOfMemory();
432 SDL_free(data);
433 return -1;
434 }
435 }
436
437 texture->driverdata = data;
438
439 renderdata->glGetError();
440 renderdata->glGenTextures(1, &data->texture);
441
442 data->type = GL_TEXTURE_2D;
443 texture_w = power_of_2(texture->w);
444 texture_h = power_of_2(texture->h);
445 data->texw = (GLfloat) texture->w / texture_w;
446 data->texh = (GLfloat) texture->h / texture_h;
447
448 data->format = format;
449 data->formattype = type;
450 renderdata->glBindTexture(data->type, data->texture);
451 renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
452 GL_NEAREST);
453 renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
454 GL_NEAREST);
455 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
456 GL_CLAMP_TO_EDGE);
457 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
458 GL_CLAMP_TO_EDGE);
459
460 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
461 texture_h, 0, format, type, NULL);
462
463 result = renderdata->glGetError();
464 if (result != GL_NO_ERROR) {
465 GL_SetError("glTexImage2D()", result);
466 return -1;
467 }
468 return 0;
469 }
470
471 static int
472 GL_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
473 void **pixels, int *pitch)
474 {
475 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
476
477 *pixels = data->pixels;
478 *pitch = data->pitch;
479 return 0;
480 }
481
482 static int
483 GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
484 const SDL_Color * colors, int firstcolor, int ncolors)
485 {
486 SDL_SetError("OpenGL ES does not support paletted textures");
487 return -1;
488 }
489
490 static int
491 GL_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
492 SDL_Color * colors, int firstcolor, int ncolors)
493 {
494 SDL_SetError("OpenGL ES does not support paletted textures");
495 return -1;
496 }
497
498 static void
499 SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
500 int pitch)
501 {
502
503
504 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
505 renderdata->glBindTexture(data->type, data->texture);
506 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
507 }
508
509 static int
510 GL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
511 {
512 return 0;
513 }
514
515 static int
516 GL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
517 {
518 return 0;
519 }
520
521 static int
522 GL_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
523 {
524 switch (texture->blendMode) {
525 case SDL_TEXTUREBLENDMODE_NONE:
526 case SDL_TEXTUREBLENDMODE_MASK:
527 case SDL_TEXTUREBLENDMODE_BLEND:
528 case SDL_TEXTUREBLENDMODE_ADD:
529 case SDL_TEXTUREBLENDMODE_MOD:
530 return 0;
531 default:
532 SDL_Unsupported();
533 texture->blendMode = SDL_TEXTUREBLENDMODE_NONE;
534 return -1;
535 }
536 }
537
538 static int
539 GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
540 {
541 switch (texture->scaleMode) {
542 case SDL_TEXTURESCALEMODE_NONE:
543 case SDL_TEXTURESCALEMODE_FAST:
544 case SDL_TEXTURESCALEMODE_SLOW:
545 return 0;
546 case SDL_TEXTURESCALEMODE_BEST:
547 SDL_Unsupported();
548 texture->scaleMode = SDL_TEXTURESCALEMODE_SLOW;
549 return -1;
550 default:
551 SDL_Unsupported();
552 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
553 return -1;
554 }
555 }
556
557 static int
558 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
559 const SDL_Rect * rect, const void *pixels, int pitch)
560 {
561 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
562 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
563 GLenum result;
564
565 SetupTextureUpdate(renderdata, texture, pitch);
566 renderdata->glGetError();
567 renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
568 rect->h, data->format, data->formattype,
569 pixels);
570 result = renderdata->glGetError();
571 if (result != GL_NO_ERROR) {
572 GL_SetError("glTexSubImage2D()", result);
573 return -1;
574 }
575 return 0;
576 }
577
578 static int
579 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
580 const SDL_Rect * rect, int markDirty, void **pixels,
581 int *pitch)
582 {
583 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
584
585 if (markDirty) {
586 SDL_AddDirtyRect(&data->dirty, rect);
587 }
588
589 *pixels =
590 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
591 rect->x * SDL_BYTESPERPIXEL(texture->format));
592 *pitch = data->pitch;
593 return 0;
594 }
595
596 static void
597 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
598 {
599 }
600
601 static void
602 GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
603 const SDL_Rect * rects)
604 {
605 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
606 int i;
607
608 for (i = 0; i < numrects; ++i) {
609 SDL_AddDirtyRect(&data->dirty, &rects[i]);
610 }
611 }
612
613 static int
614 GL_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
615 const SDL_Rect * rect)
616 {
617
618 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
619 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
620
621 /* set proper drawing color */
622 GLfloat oldClearColor[4];
623
624 data->glGetFloatv(GL_COLOR_CLEAR_VALUE, oldClearColor);
625
626 data->glClearColor((GLclampf) r * inv255f, (GLclampf) g * inv255f,
627 (GLclampf) b * inv255f, (GLclampf) a * inv255f);
628
629 data->glScissor(rect->x, window->h - rect->y - rect->h, rect->w, rect->h);
630 data->glEnable(GL_SCISSOR_TEST);
631 data->glClear(GL_COLOR_BUFFER_BIT);
632 data->glDisable(GL_SCISSOR_TEST);
633
634 /* reset clear color */
635 data->glClearColor(oldClearColor[0], oldClearColor[1], oldClearColor[2], oldClearColor[2]);
636
637 return 0;
638 }
639
640 static int
641 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
642 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
643 {
644
645 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
646 GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
647 int minx, miny, maxx, maxy;
648 GLfloat minu, maxu, minv, maxv;
649 int i;
650 void *temp_buffer; /* used for reformatting dirty rect pixels */
651 void *temp_ptr;
652
653 if (texturedata->dirty.list) {
654 SDL_DirtyRect *dirty;
655 void *pixels;
656 int bpp = SDL_BYTESPERPIXEL(texture->format);
657 int pitch = texturedata->pitch;
658
659 SetupTextureUpdate(data, texture, pitch);
660
661 data->glBindTexture(texturedata->type, texturedata->texture);
662 for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
663 SDL_Rect *rect = &dirty->rect;
664 pixels = (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch + rect->x * bpp);
665 /* There is no GL_UNPACK_ROW_LENGTH in OpenGLES
666 we must do this reformatting ourselves(!)
667
668 maybe it'd be a good idea to keep a temp buffer around
669 for this purpose rather than allocating it each time
670 */
671 temp_buffer = SDL_malloc(rect->w * rect->h * bpp);
672 temp_ptr = temp_buffer;
673 for (i=0; i<rect->h; i++) {
674 SDL_memcpy(temp_ptr, pixels, rect->w * bpp);
675 temp_ptr += rect->w * bpp;
676 pixels += pitch;
677 }
678
679 data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
680 rect->w, rect->h, texturedata->format,
681 texturedata->formattype, temp_buffer);
682
683 SDL_free(temp_buffer);
684
685 }
686 SDL_ClearDirtyRects(&texturedata->dirty);
687 }
688
689 data->glBindTexture(texturedata->type, texturedata->texture);
690 data->glEnable(GL_TEXTURE_2D);
691
692 if (texture->modMode) {
693 data->glColor4f((GLfloat) texture->r * inv255f,
694 (GLfloat) texture->g * inv255f,
695 (GLfloat) texture->b * inv255f,
696 (GLfloat) texture->a * inv255f);
697 } else {
698 data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
699 }
700
701 //if (texture->blendMode != data->blendMode) {
702 switch (texture->blendMode) {
703 case SDL_TEXTUREBLENDMODE_NONE:
704 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
705 data->glDisable(GL_BLEND);
706 break;
707 case SDL_TEXTUREBLENDMODE_MASK:
708 case SDL_TEXTUREBLENDMODE_BLEND:
709 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
710 data->glEnable(GL_BLEND);
711 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
712 break;
713 case SDL_TEXTUREBLENDMODE_ADD:
714 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
715 data->glEnable(GL_BLEND);
716 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
717 break;
718 case SDL_TEXTUREBLENDMODE_MOD:
719 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
720 data->glEnable(GL_BLEND);
721 data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
722 break;
723 }
724 data->blendMode = texture->blendMode;
725 // }
726
727 // if (texture->scaleMode != data->scaleMode) {
728 switch (texture->scaleMode) {
729 case SDL_TEXTURESCALEMODE_NONE:
730 case SDL_TEXTURESCALEMODE_FAST:
731 data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
732 GL_NEAREST);
733 data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
734 GL_NEAREST);
735 break;
736 case SDL_TEXTURESCALEMODE_SLOW:
737 case SDL_TEXTURESCALEMODE_BEST:
738 data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
739 GL_LINEAR);
740 data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
741 GL_LINEAR);
742 break;
743 }
744 data->scaleMode = texture->scaleMode;
745 //}
746
747 if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
748 /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
749 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
750 GLint cropRect[4];
751 cropRect[0] = srcrect->x;
752 cropRect[1] = srcrect->y + srcrect->h;
753 cropRect[2] = srcrect->w;
754 cropRect[3] = -srcrect->h;
755 data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, cropRect);
756 data->glDrawTexiOES(dstrect->x, window->h - dstrect->y - dstrect->h, 0, dstrect->w, dstrect->h);
757 }
758 else {
759
760 minx = dstrect->x;
761 miny = dstrect->y;
762 maxx = dstrect->x + dstrect->w;
763 maxy = dstrect->y + dstrect->h;
764
765 minu = (GLfloat) srcrect->x / texture->w;
766 minu *= texturedata->texw;
767 maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
768 maxu *= texturedata->texw;
769 minv = (GLfloat) srcrect->y / texture->h;
770 minv *= texturedata->texh;
771 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
772 maxv *= texturedata->texh;
773
774 GLshort vertices[8];
775 GLfloat texCoords[8];
776
777 vertices[0] = minx; vertices[1] = miny;
778 vertices[2] = maxx; vertices[3] = miny;
779 vertices[4] = minx; vertices[5] = maxy;
780 vertices[6] = maxx; vertices[7] = maxy;
781
782 texCoords[0] = minu; texCoords[1] = minv;
783 texCoords[2] = maxu; texCoords[3] = minv;
784 texCoords[4] = minu; texCoords[5] = maxv;
785 texCoords[6] = maxu; texCoords[7] = maxv;
786
787 data->glVertexPointer(2, GL_SHORT, 0, vertices);
788 data->glEnableClientState(GL_VERTEX_ARRAY);
789 data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
790 data->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
791 data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
792
793 }
794
795 return 0;
796 }
797
798 static void
799 GL_RenderPresent(SDL_Renderer * renderer)
800 {
801 SDL_GL_SwapWindow(renderer->window);
802 }
803
804 static void
805 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
806 {
807 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
808 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
809
810 if (!data) {
811 return;
812 }
813 if (data->texture) {
814 glDeleteTextures(1, &data->texture);
815 }
816 if (data->pixels) {
817 SDL_free(data->pixels);
818 }
819 SDL_FreeDirtyRects(&data->dirty);
820 SDL_free(data);
821 texture->driverdata = NULL;
822 }
823
824 static void
825 GL_DestroyRenderer(SDL_Renderer * renderer)
826 {
827 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
828
829 if (data) {
830 if (data->context) {
831 /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
832 SDL_GL_DeleteContext(data->context);
833 }
834 SDL_free(data);
835 }
836 SDL_free(renderer);
837 }
838
839 #endif /* SDL_VIDEO_RENDER_OGL */
840
841 /* vi: set ts=4 sw=4 expandtab: */