Mercurial > sdl-ios-xcode
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: */ |