comparison src/video/glrenderer/SDL_renderer_gl.c @ 2335:69dd5af09ff1 gsoc2008_iphone

(none)
author Holmes Futrell <hfutrell@umail.ucsb.edu>
date Fri, 11 Jul 2008 00:22:16 +0000
parents src/video/SDL_renderer_gl.c@91e601d9df8b
children
comparison
equal deleted inserted replaced
2334:80ceefc00ada 2335:69dd5af09ff1
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
25
26 #include "SDL_video.h"
27 #include "SDL_opengl.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 #ifdef __MACOSX__
34 #include <OpenGL/OpenGL.h>
35 #endif
36
37 /* OpenGL renderer implementation */
38
39 /* Details on optimizing the texture path on Mac OS X:
40 http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
41 */
42
43 static const float inv255f = 1.0f / 255.0f;
44
45 static SDL_Renderer *GL_CreateRenderer(SDL_Window * window, Uint32 flags);
46 static int GL_ActivateRenderer(SDL_Renderer * renderer);
47 static int GL_DisplayModeChanged(SDL_Renderer * renderer);
48 static int GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
49 static int GL_QueryTexturePixels(SDL_Renderer * renderer,
50 SDL_Texture * texture, void **pixels,
51 int *pitch);
52 static int GL_SetTexturePalette(SDL_Renderer * renderer,
53 SDL_Texture * texture,
54 const SDL_Color * colors, int firstcolor,
55 int ncolors);
56 static int GL_GetTexturePalette(SDL_Renderer * renderer,
57 SDL_Texture * texture, SDL_Color * colors,
58 int firstcolor, int ncolors);
59 static int GL_SetTextureColorMod(SDL_Renderer * renderer,
60 SDL_Texture * texture);
61 static int GL_SetTextureAlphaMod(SDL_Renderer * renderer,
62 SDL_Texture * texture);
63 static int GL_SetTextureBlendMode(SDL_Renderer * renderer,
64 SDL_Texture * texture);
65 static int GL_SetTextureScaleMode(SDL_Renderer * renderer,
66 SDL_Texture * texture);
67 static int GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
68 const SDL_Rect * rect, const void *pixels,
69 int pitch);
70 static int GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
71 const SDL_Rect * rect, int markDirty, void **pixels,
72 int *pitch);
73 static void GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture);
74 static void GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture,
75 int numrects, const SDL_Rect * rects);
76 static int GL_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b,
77 Uint8 a, const SDL_Rect * rect);
78 static int GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
79 const SDL_Rect * srcrect, const SDL_Rect * dstrect);
80 static void GL_RenderPresent(SDL_Renderer * renderer);
81 static void GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture);
82 static void GL_DestroyRenderer(SDL_Renderer * renderer);
83
84
85 SDL_RenderDriver GL_RenderDriver = {
86 GL_CreateRenderer,
87 {
88 "opengl",
89 (SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTDISCARD |
90 SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED),
91 (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
92 SDL_TEXTUREMODULATE_ALPHA),
93 (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
94 SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
95 SDL_TEXTUREBLENDMODE_MOD),
96 (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST |
97 SDL_TEXTURESCALEMODE_SLOW),
98 16,
99 {
100 SDL_PIXELFORMAT_INDEX1LSB,
101 SDL_PIXELFORMAT_INDEX1MSB,
102 SDL_PIXELFORMAT_INDEX8,
103 SDL_PIXELFORMAT_RGB332,
104 SDL_PIXELFORMAT_RGB444,
105 SDL_PIXELFORMAT_RGB555,
106 SDL_PIXELFORMAT_ARGB4444,
107 SDL_PIXELFORMAT_ARGB1555,
108 SDL_PIXELFORMAT_RGB565,
109 SDL_PIXELFORMAT_RGB24,
110 SDL_PIXELFORMAT_BGR24,
111 SDL_PIXELFORMAT_RGB888,
112 SDL_PIXELFORMAT_BGR888,
113 SDL_PIXELFORMAT_ARGB8888,
114 SDL_PIXELFORMAT_ABGR8888,
115 SDL_PIXELFORMAT_ARGB2101010},
116 0,
117 0}
118 };
119
120 typedef struct
121 {
122 SDL_GLContext context;
123 SDL_bool updateSize;
124 SDL_bool GL_ARB_texture_rectangle_supported;
125 SDL_bool GL_EXT_paletted_texture_supported;
126 int blendMode;
127 int scaleMode;
128
129 /* OpenGL functions */
130 #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
131 #include "SDL_glfuncs.h"
132 #undef SDL_PROC
133
134 PFNGLCOLORTABLEEXTPROC glColorTableEXT;
135 void (*glTextureRangeAPPLE) (GLenum target, GLsizei length,
136 const GLvoid * pointer);
137 } GL_RenderData;
138
139 typedef struct
140 {
141 GLuint texture;
142 GLenum type;
143 GLfloat texw;
144 GLfloat texh;
145 GLenum format;
146 GLenum formattype;
147 Uint8 *palette;
148 void *pixels;
149 int pitch;
150 SDL_DirtyRectList dirty;
151 } GL_TextureData;
152
153
154 static void
155 GL_SetError(const char *prefix, GLenum result)
156 {
157 const char *error;
158
159 switch (result) {
160 case GL_NO_ERROR:
161 error = "GL_NO_ERROR";
162 break;
163 case GL_INVALID_ENUM:
164 error = "GL_INVALID_ENUM";
165 break;
166 case GL_INVALID_VALUE:
167 error = "GL_INVALID_VALUE";
168 break;
169 case GL_INVALID_OPERATION:
170 error = "GL_INVALID_OPERATION";
171 break;
172 case GL_STACK_OVERFLOW:
173 error = "GL_STACK_OVERFLOW";
174 break;
175 case GL_STACK_UNDERFLOW:
176 error = "GL_STACK_UNDERFLOW";
177 break;
178 case GL_OUT_OF_MEMORY:
179 error = "GL_OUT_OF_MEMORY";
180 break;
181 case GL_TABLE_TOO_LARGE:
182 error = "GL_TABLE_TOO_LARGE";
183 break;
184 default:
185 error = "UNKNOWN";
186 break;
187 }
188 SDL_SetError("%s: %s", prefix, error);
189 }
190
191 static int
192 GL_LoadFunctions(GL_RenderData * data)
193 {
194 #if defined(__QNXNTO__) && (_NTO_VERSION < 630)
195 #define __SDL_NOGETPROCADDR__
196 #elif defined(__MINT__)
197 #define __SDL_NOGETPROCADDR__
198 #endif
199 #ifdef __SDL_NOGETPROCADDR__
200 #define SDL_PROC(ret,func,params) data->func=func;
201 #else
202 #define SDL_PROC(ret,func,params) \
203 do { \
204 data->func = SDL_GL_GetProcAddress(#func); \
205 if ( ! data->func ) { \
206 SDL_SetError("Couldn't load GL function %s: %s\n", #func, SDL_GetError()); \
207 return -1; \
208 } \
209 } while ( 0 );
210 #endif /* __SDL_NOGETPROCADDR__ */
211
212 #include "SDL_glfuncs.h"
213 #undef SDL_PROC
214 return 0;
215 }
216
217 void
218 GL_AddRenderDriver(_THIS)
219 {
220 if (_this->GL_CreateContext) {
221 SDL_AddRenderDriver(0, &GL_RenderDriver);
222 }
223 }
224
225 SDL_Renderer *
226 GL_CreateRenderer(SDL_Window * window, Uint32 flags)
227 {
228 SDL_Renderer *renderer;
229 GL_RenderData *data;
230 GLint value;
231 int doublebuffer;
232
233 /* Render directly to the window, unless we're compositing */
234 #ifndef __MACOSX__
235 if (flags & SDL_RENDERER_SINGLEBUFFER) {
236 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0);
237 }
238 #endif
239 if (!(window->flags & SDL_WINDOW_OPENGL)) {
240 if (SDL_RecreateWindow(window, window->flags | SDL_WINDOW_OPENGL) < 0) {
241 return NULL;
242 }
243 }
244
245 renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
246 if (!renderer) {
247 SDL_OutOfMemory();
248 return NULL;
249 }
250
251 data = (GL_RenderData *) SDL_calloc(1, sizeof(*data));
252 if (!data) {
253 GL_DestroyRenderer(renderer);
254 SDL_OutOfMemory();
255 return NULL;
256 }
257
258 renderer->ActivateRenderer = GL_ActivateRenderer;
259 renderer->DisplayModeChanged = GL_DisplayModeChanged;
260 renderer->CreateTexture = GL_CreateTexture;
261 renderer->QueryTexturePixels = GL_QueryTexturePixels;
262 renderer->SetTexturePalette = GL_SetTexturePalette;
263 renderer->GetTexturePalette = GL_GetTexturePalette;
264 renderer->SetTextureColorMod = GL_SetTextureColorMod;
265 renderer->SetTextureAlphaMod = GL_SetTextureAlphaMod;
266 renderer->SetTextureBlendMode = GL_SetTextureBlendMode;
267 renderer->SetTextureScaleMode = GL_SetTextureScaleMode;
268 renderer->UpdateTexture = GL_UpdateTexture;
269 renderer->LockTexture = GL_LockTexture;
270 renderer->UnlockTexture = GL_UnlockTexture;
271 renderer->DirtyTexture = GL_DirtyTexture;
272 renderer->RenderFill = GL_RenderFill;
273 renderer->RenderCopy = GL_RenderCopy;
274 renderer->RenderPresent = GL_RenderPresent;
275 renderer->DestroyTexture = GL_DestroyTexture;
276 renderer->DestroyRenderer = GL_DestroyRenderer;
277 renderer->info = GL_RenderDriver.info;
278 renderer->window = window->id;
279 renderer->driverdata = data;
280
281 renderer->info.flags =
282 (SDL_RENDERER_PRESENTDISCARD | SDL_RENDERER_ACCELERATED);
283
284 if (GL_LoadFunctions(data) < 0) {
285 GL_DestroyRenderer(renderer);
286 return NULL;
287 }
288
289 data->context = SDL_GL_CreateContext(window->id);
290 if (!data->context) {
291 GL_DestroyRenderer(renderer);
292 return NULL;
293 }
294 if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
295 GL_DestroyRenderer(renderer);
296 return NULL;
297 }
298 #ifdef __MACOSX__
299 /* Enable multi-threaded rendering */
300 /* Disabled until Ryan finishes his VBO/PBO code...
301 CGLEnable(CGLGetCurrentContext(), kCGLCEMPEngine);
302 */
303 #endif
304
305 if (flags & SDL_RENDERER_PRESENTVSYNC) {
306 SDL_GL_SetSwapInterval(1);
307 } else {
308 SDL_GL_SetSwapInterval(0);
309 }
310 if (SDL_GL_GetSwapInterval() > 0) {
311 renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
312 }
313
314 if (SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &doublebuffer) == 0) {
315 if (!doublebuffer) {
316 renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
317 }
318 }
319
320 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
321 renderer->info.max_texture_width = value;
322 data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
323 renderer->info.max_texture_height = value;
324
325 if (SDL_GL_ExtensionSupported("GL_ARB_texture_rectangle")
326 || SDL_GL_ExtensionSupported("GL_EXT_texture_rectangle")) {
327 data->GL_ARB_texture_rectangle_supported = SDL_TRUE;
328 }
329 if (SDL_GL_ExtensionSupported("GL_EXT_paletted_texture")) {
330 data->GL_EXT_paletted_texture_supported = SDL_TRUE;
331 data->glColorTableEXT =
332 (PFNGLCOLORTABLEEXTPROC) SDL_GL_GetProcAddress("glColorTableEXT");
333 } else {
334 /* Don't advertise support for 8-bit indexed texture format */
335 Uint32 i, j;
336 SDL_RendererInfo *info = &renderer->info;
337 for (i = 0, j = 0; i < info->num_texture_formats; ++i) {
338 if (info->texture_formats[i] != SDL_PIXELFORMAT_INDEX8) {
339 info->texture_formats[j++] = info->texture_formats[i];
340 }
341 }
342 --info->num_texture_formats;
343 }
344 if (SDL_GL_ExtensionSupported("GL_APPLE_texture_range")) {
345 data->glTextureRangeAPPLE =
346 (void (*)(GLenum, GLsizei, const GLvoid *))
347 SDL_GL_GetProcAddress("glTextureRangeAPPLE");
348 }
349
350 /* Set up parameters for rendering */
351 data->blendMode = -1;
352 data->scaleMode = -1;
353 data->glDisable(GL_DEPTH_TEST);
354 data->glDisable(GL_CULL_FACE);
355 if (data->GL_ARB_texture_rectangle_supported) {
356 data->glEnable(GL_TEXTURE_RECTANGLE_ARB);
357 } else {
358 data->glEnable(GL_TEXTURE_2D);
359 }
360 data->updateSize = SDL_TRUE;
361
362 return renderer;
363 }
364
365 static int
366 GL_ActivateRenderer(SDL_Renderer * renderer)
367 {
368 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
369 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
370
371 if (SDL_GL_MakeCurrent(window->id, data->context) < 0) {
372 return -1;
373 }
374 if (data->updateSize) {
375 data->glMatrixMode(GL_PROJECTION);
376 data->glLoadIdentity();
377 data->glMatrixMode(GL_MODELVIEW);
378 data->glLoadIdentity();
379 data->glViewport(0, 0, window->w, window->h);
380 data->glOrtho(0.0, (GLdouble) window->w, (GLdouble) window->h, 0.0,
381 0.0, 1.0);
382 data->updateSize = SDL_FALSE;
383 }
384 return 0;
385 }
386
387 static int
388 GL_DisplayModeChanged(SDL_Renderer * renderer)
389 {
390 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
391
392 data->updateSize = SDL_TRUE;
393 return 0;
394 }
395
396 static __inline__ int
397 power_of_2(int input)
398 {
399 int value = 1;
400
401 while (value < input) {
402 value <<= 1;
403 }
404 return value;
405 }
406
407 static int
408 GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
409 {
410 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
411 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
412 GL_TextureData *data;
413 GLint internalFormat;
414 GLenum format, type;
415 int texture_w, texture_h;
416 GLenum result;
417
418 switch (texture->format) {
419 case SDL_PIXELFORMAT_INDEX1LSB:
420 case SDL_PIXELFORMAT_INDEX1MSB:
421 internalFormat = GL_RGB;
422 format = GL_COLOR_INDEX;
423 type = GL_BITMAP;
424 break;
425 case SDL_PIXELFORMAT_INDEX8:
426 if (!renderdata->GL_EXT_paletted_texture_supported) {
427 SDL_SetError("Unsupported texture format");
428 return -1;
429 }
430 internalFormat = GL_COLOR_INDEX8_EXT;
431 format = GL_COLOR_INDEX;
432 type = GL_UNSIGNED_BYTE;
433 break;
434 case SDL_PIXELFORMAT_RGB332:
435 internalFormat = GL_R3_G3_B2;
436 format = GL_RGB;
437 type = GL_UNSIGNED_BYTE_3_3_2;
438 break;
439 case SDL_PIXELFORMAT_RGB444:
440 internalFormat = GL_RGB4;
441 format = GL_RGB;
442 type = GL_UNSIGNED_SHORT_4_4_4_4;
443 break;
444 case SDL_PIXELFORMAT_RGB555:
445 internalFormat = GL_RGB5;
446 format = GL_RGB;
447 type = GL_UNSIGNED_SHORT_5_5_5_1;
448 break;
449 case SDL_PIXELFORMAT_ARGB4444:
450 internalFormat = GL_RGBA4;
451 format = GL_BGRA;
452 type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
453 break;
454 case SDL_PIXELFORMAT_ARGB1555:
455 internalFormat = GL_RGB5_A1;
456 format = GL_BGRA;
457 type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
458 break;
459 case SDL_PIXELFORMAT_RGB565:
460 internalFormat = GL_RGB8;
461 format = GL_RGB;
462 type = GL_UNSIGNED_SHORT_5_6_5;
463 break;
464 case SDL_PIXELFORMAT_RGB24:
465 internalFormat = GL_RGB8;
466 format = GL_RGB;
467 type = GL_UNSIGNED_BYTE;
468 break;
469 case SDL_PIXELFORMAT_RGB888:
470 internalFormat = GL_RGB8;
471 format = GL_BGRA;
472 type = GL_UNSIGNED_BYTE;
473 break;
474 case SDL_PIXELFORMAT_BGR24:
475 internalFormat = GL_RGB8;
476 format = GL_BGR;
477 type = GL_UNSIGNED_BYTE;
478 break;
479 case SDL_PIXELFORMAT_BGR888:
480 internalFormat = GL_RGB8;
481 format = GL_RGBA;
482 type = GL_UNSIGNED_BYTE;
483 break;
484 case SDL_PIXELFORMAT_ARGB8888:
485 #ifdef __MACOSX__
486 internalFormat = GL_RGBA;
487 format = GL_BGRA;
488 type = GL_UNSIGNED_INT_8_8_8_8_REV;
489 #else
490 internalFormat = GL_RGBA8;
491 format = GL_BGRA;
492 type = GL_UNSIGNED_BYTE;
493 #endif
494 break;
495 case SDL_PIXELFORMAT_ABGR8888:
496 internalFormat = GL_RGBA8;
497 format = GL_RGBA;
498 type = GL_UNSIGNED_BYTE;
499 break;
500 case SDL_PIXELFORMAT_ARGB2101010:
501 internalFormat = GL_RGB10_A2;
502 format = GL_BGRA;
503 type = GL_UNSIGNED_INT_2_10_10_10_REV;
504 break;
505 default:
506 SDL_SetError("Unsupported texture format");
507 return -1;
508 }
509
510 data = (GL_TextureData *) SDL_calloc(1, sizeof(*data));
511 if (!data) {
512 SDL_OutOfMemory();
513 return -1;
514 }
515
516 if (texture->format == SDL_PIXELFORMAT_INDEX8) {
517 data->palette = (Uint8 *) SDL_malloc(3 * 256 * sizeof(Uint8));
518 if (!data->palette) {
519 SDL_OutOfMemory();
520 SDL_free(data);
521 return -1;
522 }
523 SDL_memset(data->palette, 0xFF, 3 * 256 * sizeof(Uint8));
524 }
525
526 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
527 data->pitch = texture->w * SDL_BYTESPERPIXEL(texture->format);
528 data->pixels = SDL_malloc(texture->h * data->pitch);
529 if (!data->pixels) {
530 SDL_OutOfMemory();
531 SDL_free(data);
532 return -1;
533 }
534 }
535
536 texture->driverdata = data;
537
538 renderdata->glGetError();
539 renderdata->glGenTextures(1, &data->texture);
540 if (renderdata->GL_ARB_texture_rectangle_supported) {
541 data->type = GL_TEXTURE_RECTANGLE_ARB;
542 texture_w = texture->w;
543 texture_h = texture->h;
544 data->texw = (GLfloat) texture->w;
545 data->texh = (GLfloat) texture->h;
546 } else {
547 data->type = GL_TEXTURE_2D;
548 texture_w = power_of_2(texture->w);
549 texture_h = power_of_2(texture->h);
550 data->texw = (GLfloat) texture->w / texture_w;
551 data->texh = (GLfloat) texture->h / texture_h;
552 }
553 data->format = format;
554 data->formattype = type;
555 renderdata->glBindTexture(data->type, data->texture);
556 renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
557 GL_NEAREST);
558 renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
559 GL_NEAREST);
560 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
561 GL_CLAMP_TO_EDGE);
562 renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
563 GL_CLAMP_TO_EDGE);
564 #ifdef __MACOSX__
565 #ifndef GL_TEXTURE_STORAGE_HINT_APPLE
566 #define GL_TEXTURE_STORAGE_HINT_APPLE 0x85BC
567 #endif
568 #ifndef STORAGE_CACHED_APPLE
569 #define STORAGE_CACHED_APPLE 0x85BE
570 #endif
571 #ifndef STORAGE_SHARED_APPLE
572 #define STORAGE_SHARED_APPLE 0x85BF
573 #endif
574 if (texture->access == SDL_TEXTUREACCESS_STREAMING) {
575 renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
576 GL_STORAGE_SHARED_APPLE);
577 } else {
578 renderdata->glTexParameteri(data->type, GL_TEXTURE_STORAGE_HINT_APPLE,
579 GL_STORAGE_CACHED_APPLE);
580 }
581 if (texture->access == SDL_TEXTUREACCESS_STREAMING
582 && texture->format == SDL_PIXELFORMAT_ARGB8888) {
583 /*
584 if (renderdata->glTextureRangeAPPLE) {
585 renderdata->glTextureRangeAPPLE(data->type,
586 texture->h * data->pitch,
587 data->pixels);
588 }
589 */
590 renderdata->glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);
591 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
592 texture_h, 0, format, type, data->pixels);
593 } else
594 #endif
595 {
596 renderdata->glTexImage2D(data->type, 0, internalFormat, texture_w,
597 texture_h, 0, format, type, NULL);
598 }
599 result = renderdata->glGetError();
600 if (result != GL_NO_ERROR) {
601 GL_SetError("glTexImage2D()", result);
602 return -1;
603 }
604 return 0;
605 }
606
607 static int
608 GL_QueryTexturePixels(SDL_Renderer * renderer, SDL_Texture * texture,
609 void **pixels, int *pitch)
610 {
611 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
612
613 *pixels = data->pixels;
614 *pitch = data->pitch;
615 return 0;
616 }
617
618 static int
619 GL_SetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
620 const SDL_Color * colors, int firstcolor, int ncolors)
621 {
622 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
623 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
624 Uint8 *palette;
625
626 if (!data->palette) {
627 SDL_SetError("Texture doesn't have a palette");
628 return -1;
629 }
630 palette = data->palette + firstcolor * 3;
631 while (ncolors--) {
632 *palette++ = colors->r;
633 *palette++ = colors->g;
634 *palette++ = colors->b;
635 ++colors;
636 }
637 renderdata->glBindTexture(data->type, data->texture);
638 renderdata->glColorTableEXT(data->type, GL_RGB8, 256, GL_RGB,
639 GL_UNSIGNED_BYTE, data->palette);
640 return 0;
641 }
642
643 static int
644 GL_GetTexturePalette(SDL_Renderer * renderer, SDL_Texture * texture,
645 SDL_Color * colors, int firstcolor, int ncolors)
646 {
647 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
648 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
649 Uint8 *palette;
650
651 if (!data->palette) {
652 SDL_SetError("Texture doesn't have a palette");
653 return -1;
654 }
655 palette = data->palette + firstcolor * 3;
656 while (ncolors--) {
657 colors->r = *palette++;
658 colors->g = *palette++;
659 colors->b = *palette++;
660 colors->unused = SDL_ALPHA_OPAQUE;
661 ++colors;
662 }
663 return 0;
664 }
665
666 static void
667 SetupTextureUpdate(GL_RenderData * renderdata, SDL_Texture * texture,
668 int pitch)
669 {
670 if (texture->format == SDL_PIXELFORMAT_INDEX1LSB) {
671 renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
672 } else if (texture->format == SDL_PIXELFORMAT_INDEX1MSB) {
673 renderdata->glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
674 }
675 renderdata->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
676 renderdata->glPixelStorei(GL_UNPACK_ROW_LENGTH,
677 pitch / SDL_BYTESPERPIXEL(texture->format));
678 }
679
680 static int
681 GL_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
682 {
683 return 0;
684 }
685
686 static int
687 GL_SetTextureAlphaMod(SDL_Renderer * renderer, SDL_Texture * texture)
688 {
689 return 0;
690 }
691
692 static int
693 GL_SetTextureBlendMode(SDL_Renderer * renderer, SDL_Texture * texture)
694 {
695 switch (texture->blendMode) {
696 case SDL_TEXTUREBLENDMODE_NONE:
697 case SDL_TEXTUREBLENDMODE_MASK:
698 case SDL_TEXTUREBLENDMODE_BLEND:
699 case SDL_TEXTUREBLENDMODE_ADD:
700 case SDL_TEXTUREBLENDMODE_MOD:
701 return 0;
702 default:
703 SDL_Unsupported();
704 texture->blendMode = SDL_TEXTUREBLENDMODE_NONE;
705 return -1;
706 }
707 }
708
709 static int
710 GL_SetTextureScaleMode(SDL_Renderer * renderer, SDL_Texture * texture)
711 {
712 switch (texture->scaleMode) {
713 case SDL_TEXTURESCALEMODE_NONE:
714 case SDL_TEXTURESCALEMODE_FAST:
715 case SDL_TEXTURESCALEMODE_SLOW:
716 return 0;
717 case SDL_TEXTURESCALEMODE_BEST:
718 SDL_Unsupported();
719 texture->scaleMode = SDL_TEXTURESCALEMODE_SLOW;
720 return -1;
721 default:
722 SDL_Unsupported();
723 texture->scaleMode = SDL_TEXTURESCALEMODE_NONE;
724 return -1;
725 }
726 }
727
728 static int
729 GL_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
730 const SDL_Rect * rect, const void *pixels, int pitch)
731 {
732 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
733 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
734 GLenum result;
735
736 renderdata->glGetError();
737 SetupTextureUpdate(renderdata, texture, pitch);
738 renderdata->glBindTexture(data->type, data->texture);
739 renderdata->glTexSubImage2D(data->type, 0, rect->x, rect->y, rect->w,
740 rect->h, data->format, data->formattype,
741 pixels);
742 result = renderdata->glGetError();
743 if (result != GL_NO_ERROR) {
744 GL_SetError("glTexSubImage2D()", result);
745 return -1;
746 }
747 return 0;
748 }
749
750 static int
751 GL_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
752 const SDL_Rect * rect, int markDirty, void **pixels,
753 int *pitch)
754 {
755 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
756
757 if (markDirty) {
758 SDL_AddDirtyRect(&data->dirty, rect);
759 }
760
761 *pixels =
762 (void *) ((Uint8 *) data->pixels + rect->y * data->pitch +
763 rect->x * SDL_BYTESPERPIXEL(texture->format));
764 *pitch = data->pitch;
765 return 0;
766 }
767
768 static void
769 GL_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture)
770 {
771 }
772
773 static void
774 GL_DirtyTexture(SDL_Renderer * renderer, SDL_Texture * texture, int numrects,
775 const SDL_Rect * rects)
776 {
777 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
778 int i;
779
780 for (i = 0; i < numrects; ++i) {
781 SDL_AddDirtyRect(&data->dirty, &rects[i]);
782 }
783 }
784
785 static int
786 GL_RenderFill(SDL_Renderer * renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a,
787 const SDL_Rect * rect)
788 {
789 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
790 SDL_Window *window = SDL_GetWindowFromID(renderer->window);
791
792 data->glClearColor((GLclampf) r * inv255f, (GLclampf) g * inv255f,
793 (GLclampf) b * inv255f, (GLclampf) a * inv255f);
794 data->glViewport(rect->x, window->h - rect->y, rect->w, rect->h);
795 data->glClear(GL_COLOR_BUFFER_BIT);
796 data->glViewport(0, 0, window->w, window->h);
797 return 0;
798 }
799
800 static int
801 GL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
802 const SDL_Rect * srcrect, const SDL_Rect * dstrect)
803 {
804 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
805 GL_TextureData *texturedata = (GL_TextureData *) texture->driverdata;
806 int minx, miny, maxx, maxy;
807 GLfloat minu, maxu, minv, maxv;
808
809 if (texturedata->dirty.list) {
810 SDL_DirtyRect *dirty;
811 void *pixels;
812 int bpp = SDL_BYTESPERPIXEL(texture->format);
813 int pitch = texturedata->pitch;
814
815 SetupTextureUpdate(data, texture, pitch);
816 data->glBindTexture(texturedata->type, texturedata->texture);
817 for (dirty = texturedata->dirty.list; dirty; dirty = dirty->next) {
818 SDL_Rect *rect = &dirty->rect;
819 pixels =
820 (void *) ((Uint8 *) texturedata->pixels + rect->y * pitch +
821 rect->x * bpp);
822 data->glTexSubImage2D(texturedata->type, 0, rect->x, rect->y,
823 rect->w, rect->h, texturedata->format,
824 texturedata->formattype, pixels);
825 }
826 SDL_ClearDirtyRects(&texturedata->dirty);
827 }
828
829 minx = dstrect->x;
830 miny = dstrect->y;
831 maxx = dstrect->x + dstrect->w;
832 maxy = dstrect->y + dstrect->h;
833
834 minu = (GLfloat) srcrect->x / texture->w;
835 minu *= texturedata->texw;
836 maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
837 maxu *= texturedata->texw;
838 minv = (GLfloat) srcrect->y / texture->h;
839 minv *= texturedata->texh;
840 maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
841 maxv *= texturedata->texh;
842
843 data->glBindTexture(texturedata->type, texturedata->texture);
844
845 if (texture->modMode) {
846 data->glColor4f((GLfloat) texture->r * inv255f,
847 (GLfloat) texture->g * inv255f,
848 (GLfloat) texture->b * inv255f,
849 (GLfloat) texture->a * inv255f);
850 } else {
851 data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
852 }
853
854 if (texture->blendMode != data->blendMode) {
855 switch (texture->blendMode) {
856 case SDL_TEXTUREBLENDMODE_NONE:
857 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
858 data->glDisable(GL_BLEND);
859 break;
860 case SDL_TEXTUREBLENDMODE_MASK:
861 case SDL_TEXTUREBLENDMODE_BLEND:
862 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
863 data->glEnable(GL_BLEND);
864 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
865 break;
866 case SDL_TEXTUREBLENDMODE_ADD:
867 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
868 data->glEnable(GL_BLEND);
869 data->glBlendFunc(GL_SRC_ALPHA, GL_ONE);
870 break;
871 case SDL_TEXTUREBLENDMODE_MOD:
872 data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
873 data->glEnable(GL_BLEND);
874 data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
875 break;
876 }
877 data->blendMode = texture->blendMode;
878 }
879
880 if (texture->scaleMode != data->scaleMode) {
881 switch (texture->scaleMode) {
882 case SDL_TEXTURESCALEMODE_NONE:
883 case SDL_TEXTURESCALEMODE_FAST:
884 data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
885 GL_NEAREST);
886 data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
887 GL_NEAREST);
888 break;
889 case SDL_TEXTURESCALEMODE_SLOW:
890 case SDL_TEXTURESCALEMODE_BEST:
891 data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
892 GL_LINEAR);
893 data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
894 GL_LINEAR);
895 break;
896 }
897 data->scaleMode = texture->scaleMode;
898 }
899
900 data->glBegin(GL_TRIANGLE_STRIP);
901 data->glTexCoord2f(minu, minv);
902 data->glVertex2i(minx, miny);
903 data->glTexCoord2f(maxu, minv);
904 data->glVertex2i(maxx, miny);
905 data->glTexCoord2f(minu, maxv);
906 data->glVertex2i(minx, maxy);
907 data->glTexCoord2f(maxu, maxv);
908 data->glVertex2i(maxx, maxy);
909 data->glEnd();
910
911 return 0;
912 }
913
914 static void
915 GL_RenderPresent(SDL_Renderer * renderer)
916 {
917 SDL_GL_SwapWindow(renderer->window);
918 }
919
920 static void
921 GL_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
922 {
923 GL_RenderData *renderdata = (GL_RenderData *) renderer->driverdata;
924 GL_TextureData *data = (GL_TextureData *) texture->driverdata;
925
926 if (!data) {
927 return;
928 }
929 if (data->texture) {
930 renderdata->glDeleteTextures(1, &data->texture);
931 }
932 if (data->palette) {
933 SDL_free(data->palette);
934 }
935 if (data->pixels) {
936 SDL_free(data->pixels);
937 }
938 SDL_FreeDirtyRects(&data->dirty);
939 SDL_free(data);
940 texture->driverdata = NULL;
941 }
942
943 static void
944 GL_DestroyRenderer(SDL_Renderer * renderer)
945 {
946 GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
947
948 if (data) {
949 if (data->context) {
950 /* SDL_GL_MakeCurrent(0, NULL); *//* doesn't do anything */
951 SDL_GL_DeleteContext(data->context);
952 }
953 SDL_free(data);
954 }
955 SDL_free(renderer);
956 }
957
958 #endif /* SDL_VIDEO_RENDER_OGL */
959
960 /* vi: set ts=4 sw=4 expandtab: */