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