e14743d1 |
1 | /* |
2 | SDL - Simple DirectMedia Layer |
3 | Copyright (C) 1997-2009 Sam Lantinga |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 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 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public |
16 | License along with this library; if not, write to the Free |
17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | |
19 | Sam Lantinga |
20 | slouken@libsdl.org |
21 | */ |
22 | #include "SDL_config.h" |
23 | |
24 | /* Atari OSMesa.ldg implementation of SDL OpenGL support */ |
25 | |
26 | /*--- Includes ---*/ |
27 | |
28 | #if SDL_VIDEO_OPENGL |
29 | #include <GL/osmesa.h> |
30 | #endif |
31 | |
32 | #include <mint/osbind.h> |
33 | |
34 | #include "SDL_endian.h" |
35 | #include "SDL_video.h" |
36 | #include "SDL_atarigl_c.h" |
37 | #if SDL_VIDEO_OPENGL_OSMESA_DYNAMIC |
38 | #include "SDL_loadso.h" |
39 | #endif |
40 | |
41 | /*--- Defines ---*/ |
42 | |
43 | #define PATH_OSMESA_LDG "osmesa.ldg" |
44 | #define PATH_MESAGL_LDG "mesa_gl.ldg" |
45 | #define PATH_TINYGL_LDG "tiny_gl.ldg" |
46 | |
47 | #define VDI_RGB 0xf |
48 | |
49 | /*--- Functions prototypes ---*/ |
50 | |
51 | static void SDL_AtariGL_UnloadLibrary(_THIS); |
52 | |
53 | #if SDL_VIDEO_OPENGL |
54 | static void CopyShadowNull(_THIS, SDL_Surface *surface); |
55 | static void CopyShadowDirect(_THIS, SDL_Surface *surface); |
56 | static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface); |
57 | static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface); |
58 | static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface); |
59 | static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface); |
60 | static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface); |
61 | static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface); |
62 | static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface); |
63 | static void CopyShadow8888To555(_THIS, SDL_Surface *surface); |
64 | static void CopyShadow8888To565(_THIS, SDL_Surface *surface); |
65 | |
66 | static void ConvertNull(_THIS, SDL_Surface *surface); |
67 | static void Convert565To555be(_THIS, SDL_Surface *surface); |
68 | static void Convert565To555le(_THIS, SDL_Surface *surface); |
69 | static void Convert565le(_THIS, SDL_Surface *surface); |
70 | static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface); |
71 | |
72 | static int InitNew(_THIS, SDL_Surface *current); |
73 | static int InitOld(_THIS, SDL_Surface *current); |
74 | #endif |
75 | |
76 | /*--- Public functions ---*/ |
77 | |
78 | int SDL_AtariGL_Init(_THIS, SDL_Surface *current) |
79 | { |
80 | #if SDL_VIDEO_OPENGL |
81 | if (gl_oldmesa) { |
82 | gl_active = InitOld(this, current); |
83 | } else { |
84 | gl_active = InitNew(this, current); |
85 | } |
86 | #endif |
87 | |
88 | return (gl_active); |
89 | } |
90 | |
91 | void SDL_AtariGL_Quit(_THIS, SDL_bool unload) |
92 | { |
93 | #if SDL_VIDEO_OPENGL |
94 | if (gl_oldmesa) { |
95 | /* Old mesa implementations */ |
96 | if (this->gl_data->OSMesaDestroyLDG) { |
97 | this->gl_data->OSMesaDestroyLDG(); |
98 | } |
99 | if (gl_shadow) { |
100 | Mfree(gl_shadow); |
101 | gl_shadow = NULL; |
102 | } |
103 | } else { |
104 | /* New mesa implementation */ |
105 | if (gl_ctx) { |
106 | if (this->gl_data->OSMesaDestroyContext) { |
107 | this->gl_data->OSMesaDestroyContext(gl_ctx); |
108 | } |
109 | gl_ctx = NULL; |
110 | } |
111 | } |
112 | |
113 | if (unload) { |
114 | SDL_AtariGL_UnloadLibrary(this); |
115 | } |
116 | |
117 | #endif /* SDL_VIDEO_OPENGL */ |
118 | gl_active = 0; |
119 | } |
120 | |
121 | int SDL_AtariGL_LoadLibrary(_THIS, const char *path) |
122 | { |
123 | #if SDL_VIDEO_OPENGL |
124 | |
125 | #if SDL_VIDEO_OPENGL_OSMESA_DYNAMIC |
126 | void *handle; |
127 | SDL_bool cancel_load; |
128 | |
129 | if (gl_active) { |
130 | SDL_SetError("OpenGL context already created"); |
131 | return -1; |
132 | } |
133 | |
134 | /* Unload previous driver */ |
135 | SDL_AtariGL_UnloadLibrary(this); |
136 | |
137 | /* Load library given by path */ |
138 | handle = SDL_LoadObject(path); |
139 | if (handle == NULL) { |
140 | /* Try to load another one */ |
141 | path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); |
142 | if ( path != NULL ) { |
143 | handle = SDL_LoadObject(path); |
144 | } |
145 | |
146 | /* If it does not work, try some other */ |
147 | if (handle == NULL) { |
148 | path = PATH_OSMESA_LDG; |
149 | handle = SDL_LoadObject(path); |
150 | } |
151 | |
152 | if (handle == NULL) { |
153 | path = PATH_MESAGL_LDG; |
154 | handle = SDL_LoadObject(path); |
155 | } |
156 | |
157 | if (handle == NULL) { |
158 | path = PATH_TINYGL_LDG; |
159 | handle = SDL_LoadObject(path); |
160 | } |
161 | } |
162 | |
163 | if (handle == NULL) { |
164 | SDL_SetError("Could not load OpenGL library"); |
165 | return -1; |
166 | } |
167 | |
168 | this->gl_data->glGetIntegerv = SDL_LoadFunction(handle, "glGetIntegerv"); |
169 | this->gl_data->glFinish = SDL_LoadFunction(handle, "glFinish"); |
170 | this->gl_data->glFlush = SDL_LoadFunction(handle, "glFlush"); |
171 | |
172 | cancel_load = SDL_FALSE; |
173 | if (this->gl_data->glGetIntegerv == NULL) { |
174 | cancel_load = SDL_TRUE; |
175 | } else { |
176 | /* We need either glFinish (OSMesa) or glFlush (TinyGL) */ |
177 | if ((this->gl_data->glFinish == NULL) && |
178 | (this->gl_data->glFlush == NULL)) { |
179 | cancel_load = SDL_TRUE; |
180 | } |
181 | } |
182 | if (cancel_load) { |
183 | SDL_SetError("Could not retrieve OpenGL functions"); |
184 | SDL_UnloadObject(handle); |
185 | /* Restore pointers to static library */ |
186 | SDL_AtariGL_InitPointers(this); |
187 | return -1; |
188 | } |
189 | |
190 | /* Load functions pointers (osmesa.ldg) */ |
191 | this->gl_data->OSMesaCreateContextExt = SDL_LoadFunction(handle, "OSMesaCreateContextExt"); |
192 | this->gl_data->OSMesaDestroyContext = SDL_LoadFunction(handle, "OSMesaDestroyContext"); |
193 | this->gl_data->OSMesaMakeCurrent = SDL_LoadFunction(handle, "OSMesaMakeCurrent"); |
194 | this->gl_data->OSMesaPixelStore = SDL_LoadFunction(handle, "OSMesaPixelStore"); |
195 | this->gl_data->OSMesaGetProcAddress = SDL_LoadFunction(handle, "OSMesaGetProcAddress"); |
196 | |
197 | /* Load old functions pointers (mesa_gl.ldg, tiny_gl.ldg) */ |
198 | this->gl_data->OSMesaCreateLDG = SDL_LoadFunction(handle, "OSMesaCreateLDG"); |
199 | this->gl_data->OSMesaDestroyLDG = SDL_LoadFunction(handle, "OSMesaDestroyLDG"); |
200 | |
201 | gl_oldmesa = 0; |
202 | |
203 | if ( (this->gl_data->OSMesaCreateContextExt == NULL) || |
204 | (this->gl_data->OSMesaDestroyContext == NULL) || |
205 | (this->gl_data->OSMesaMakeCurrent == NULL) || |
206 | (this->gl_data->OSMesaPixelStore == NULL) || |
207 | (this->gl_data->OSMesaGetProcAddress == NULL)) { |
208 | /* Hum, maybe old library ? */ |
209 | if ( (this->gl_data->OSMesaCreateLDG == NULL) || |
210 | (this->gl_data->OSMesaDestroyLDG == NULL)) { |
211 | SDL_SetError("Could not retrieve OSMesa functions"); |
212 | SDL_UnloadObject(handle); |
213 | /* Restore pointers to static library */ |
214 | SDL_AtariGL_InitPointers(this); |
215 | return -1; |
216 | } else { |
217 | gl_oldmesa = 1; |
218 | } |
219 | } |
220 | |
221 | this->gl_config.dll_handle = handle; |
222 | if ( path ) { |
223 | SDL_strlcpy(this->gl_config.driver_path, path, |
224 | SDL_arraysize(this->gl_config.driver_path)); |
225 | } else { |
226 | *this->gl_config.driver_path = '\0'; |
227 | } |
228 | |
229 | #endif |
230 | this->gl_config.driver_loaded = 1; |
231 | |
232 | return 0; |
233 | #else |
234 | return -1; |
235 | #endif |
236 | } |
237 | |
238 | void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc) |
239 | { |
240 | void *func = NULL; |
241 | #if SDL_VIDEO_OPENGL |
242 | |
243 | if (this->gl_config.dll_handle) { |
244 | func = SDL_LoadFunction(this->gl_config.dll_handle, (void *)proc); |
245 | } else if (this->gl_data->OSMesaGetProcAddress) { |
246 | func = this->gl_data->OSMesaGetProcAddress(proc); |
247 | } |
248 | |
249 | #endif |
250 | return func; |
251 | } |
252 | |
253 | int SDL_AtariGL_GetAttribute(_THIS, SDL_GLattr attrib, int* value) |
254 | { |
255 | #if SDL_VIDEO_OPENGL |
256 | GLenum mesa_attrib; |
257 | SDL_Surface *surface; |
258 | |
259 | if (!gl_active) { |
260 | return -1; |
261 | } |
262 | |
263 | switch(attrib) { |
264 | case SDL_GL_RED_SIZE: |
265 | mesa_attrib = GL_RED_BITS; |
266 | break; |
267 | case SDL_GL_GREEN_SIZE: |
268 | mesa_attrib = GL_GREEN_BITS; |
269 | break; |
270 | case SDL_GL_BLUE_SIZE: |
271 | mesa_attrib = GL_BLUE_BITS; |
272 | break; |
273 | case SDL_GL_ALPHA_SIZE: |
274 | mesa_attrib = GL_ALPHA_BITS; |
275 | break; |
276 | case SDL_GL_DOUBLEBUFFER: |
277 | surface = this->screen; |
278 | *value = ((surface->flags & SDL_DOUBLEBUF)==SDL_DOUBLEBUF); |
279 | return 0; |
280 | case SDL_GL_DEPTH_SIZE: |
281 | mesa_attrib = GL_DEPTH_BITS; |
282 | break; |
283 | case SDL_GL_STENCIL_SIZE: |
284 | mesa_attrib = GL_STENCIL_BITS; |
285 | break; |
286 | case SDL_GL_ACCUM_RED_SIZE: |
287 | mesa_attrib = GL_ACCUM_RED_BITS; |
288 | break; |
289 | case SDL_GL_ACCUM_GREEN_SIZE: |
290 | mesa_attrib = GL_ACCUM_GREEN_BITS; |
291 | break; |
292 | case SDL_GL_ACCUM_BLUE_SIZE: |
293 | mesa_attrib = GL_ACCUM_BLUE_BITS; |
294 | break; |
295 | case SDL_GL_ACCUM_ALPHA_SIZE: |
296 | mesa_attrib = GL_ACCUM_ALPHA_BITS; |
297 | break; |
298 | default : |
299 | return -1; |
300 | } |
301 | |
302 | this->gl_data->glGetIntegerv(mesa_attrib, value); |
303 | return 0; |
304 | #else |
305 | return -1; |
306 | #endif |
307 | } |
308 | |
309 | int SDL_AtariGL_MakeCurrent(_THIS) |
310 | { |
311 | #if SDL_VIDEO_OPENGL |
312 | SDL_Surface *surface; |
313 | GLenum type; |
314 | |
315 | if (gl_oldmesa && gl_active) { |
316 | return 0; |
317 | } |
318 | |
319 | if (this->gl_config.dll_handle) { |
320 | if ((this->gl_data->OSMesaMakeCurrent == NULL) || |
321 | (this->gl_data->OSMesaPixelStore == NULL)) { |
322 | return -1; |
323 | } |
324 | } |
325 | |
326 | if (!gl_active) { |
327 | SDL_SetError("Invalid OpenGL context"); |
328 | return -1; |
329 | } |
330 | |
331 | surface = this->screen; |
332 | |
333 | if ((surface->format->BitsPerPixel == 15) || (surface->format->BitsPerPixel == 16)) { |
334 | type = GL_UNSIGNED_SHORT_5_6_5; |
335 | } else { |
336 | type = GL_UNSIGNED_BYTE; |
337 | } |
338 | |
339 | if (!(this->gl_data->OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h))) { |
340 | SDL_SetError("Can not make OpenGL context current"); |
341 | return -1; |
342 | } |
343 | |
344 | /* OSMesa draws upside down */ |
345 | this->gl_data->OSMesaPixelStore(OSMESA_Y_UP, 0); |
346 | |
347 | return 0; |
348 | #else |
349 | return -1; |
350 | #endif |
351 | } |
352 | |
353 | void SDL_AtariGL_SwapBuffers(_THIS) |
354 | { |
355 | #if SDL_VIDEO_OPENGL |
356 | if (gl_active) { |
357 | if (this->gl_config.dll_handle) { |
358 | if (this->gl_data->glFinish) { |
359 | this->gl_data->glFinish(); |
360 | } else if (this->gl_data->glFlush) { |
361 | this->gl_data->glFlush(); |
362 | } |
363 | } else { |
364 | this->gl_data->glFinish(); |
365 | } |
366 | gl_copyshadow(this, this->screen); |
367 | gl_convert(this, this->screen); |
368 | } |
369 | #endif |
370 | } |
371 | |
372 | void SDL_AtariGL_InitPointers(_THIS) |
373 | { |
374 | #if SDL_VIDEO_OPENGL |
375 | this->gl_data->OSMesaCreateContextExt = OSMesaCreateContextExt; |
376 | this->gl_data->OSMesaDestroyContext = OSMesaDestroyContext; |
377 | this->gl_data->OSMesaMakeCurrent = OSMesaMakeCurrent; |
378 | this->gl_data->OSMesaPixelStore = OSMesaPixelStore; |
379 | this->gl_data->OSMesaGetProcAddress = OSMesaGetProcAddress; |
380 | |
381 | this->gl_data->glGetIntegerv = glGetIntegerv; |
382 | this->gl_data->glFinish = glFinish; |
383 | this->gl_data->glFlush = glFlush; |
384 | |
385 | this->gl_data->OSMesaCreateLDG = NULL; |
386 | this->gl_data->OSMesaDestroyLDG = NULL; |
387 | #endif |
388 | } |
389 | |
390 | /*--- Private functions ---*/ |
391 | |
392 | static void SDL_AtariGL_UnloadLibrary(_THIS) |
393 | { |
394 | #if SDL_VIDEO_OPENGL |
395 | if (this->gl_config.dll_handle) { |
396 | SDL_UnloadObject(this->gl_config.dll_handle); |
397 | this->gl_config.dll_handle = NULL; |
398 | |
399 | /* Restore pointers to static library */ |
400 | SDL_AtariGL_InitPointers(this); |
401 | } |
402 | #endif |
403 | } |
404 | |
405 | /*--- Creation of an OpenGL context using new/old functions ---*/ |
406 | |
407 | #if SDL_VIDEO_OPENGL |
408 | static int InitNew(_THIS, SDL_Surface *current) |
409 | { |
410 | GLenum osmesa_format; |
411 | SDL_PixelFormat *pixel_format; |
412 | Uint32 redmask; |
413 | int recreatecontext; |
414 | GLint newaccumsize; |
415 | |
416 | if (this->gl_config.dll_handle) { |
417 | if (this->gl_data->OSMesaCreateContextExt == NULL) { |
418 | return 0; |
419 | } |
420 | } |
421 | |
422 | /* Init OpenGL context using OSMesa */ |
423 | gl_convert = ConvertNull; |
424 | gl_copyshadow = CopyShadowNull; |
425 | gl_upsidedown = SDL_FALSE; |
426 | |
427 | pixel_format = current->format; |
428 | redmask = pixel_format->Rmask; |
429 | switch (pixel_format->BitsPerPixel) { |
430 | case 15: |
431 | /* 1555, big and little endian, unsupported */ |
432 | gl_pixelsize = 2; |
433 | osmesa_format = OSMESA_RGB_565; |
434 | if (redmask == 31<<10) { |
435 | gl_convert = Convert565To555be; |
436 | } else { |
437 | gl_convert = Convert565To555le; |
438 | } |
439 | break; |
440 | case 16: |
441 | gl_pixelsize = 2; |
442 | if (redmask == 31<<11) { |
443 | osmesa_format = OSMESA_RGB_565; |
444 | } else { |
445 | /* 565, little endian, unsupported */ |
446 | osmesa_format = OSMESA_RGB_565; |
447 | gl_convert = Convert565le; |
448 | } |
449 | break; |
450 | case 24: |
451 | gl_pixelsize = 3; |
452 | if (redmask == 255<<16) { |
453 | osmesa_format = OSMESA_RGB; |
454 | } else { |
455 | osmesa_format = OSMESA_BGR; |
456 | } |
457 | break; |
458 | case 32: |
459 | gl_pixelsize = 4; |
460 | if (redmask == 255<<16) { |
461 | osmesa_format = OSMESA_ARGB; |
462 | } else if (redmask == 255<<8) { |
463 | osmesa_format = OSMESA_BGRA; |
464 | } else if (redmask == 255<<24) { |
465 | osmesa_format = OSMESA_RGBA; |
466 | } else { |
467 | /* ABGR format unsupported */ |
468 | osmesa_format = OSMESA_BGRA; |
469 | gl_convert = ConvertBGRAToABGR; |
470 | } |
471 | break; |
472 | default: |
473 | gl_pixelsize = 1; |
474 | osmesa_format = OSMESA_COLOR_INDEX; |
475 | break; |
476 | } |
477 | |
478 | /* Try to keep current context if possible */ |
479 | newaccumsize = |
480 | this->gl_config.accum_red_size + |
481 | this->gl_config.accum_green_size + |
482 | this->gl_config.accum_blue_size + |
483 | this->gl_config.accum_alpha_size; |
484 | recreatecontext=1; |
485 | if (gl_ctx && |
486 | (gl_curformat == osmesa_format) && |
487 | (gl_curdepth == this->gl_config.depth_size) && |
488 | (gl_curstencil == this->gl_config.stencil_size) && |
489 | (gl_curaccum == newaccumsize)) { |
490 | recreatecontext = 0; |
491 | } |
492 | if (recreatecontext) { |
493 | SDL_AtariGL_Quit(this, SDL_FALSE); |
494 | |
495 | gl_ctx = this->gl_data->OSMesaCreateContextExt( |
496 | osmesa_format, this->gl_config.depth_size, |
497 | this->gl_config.stencil_size, newaccumsize, NULL ); |
498 | |
499 | if (gl_ctx) { |
500 | gl_curformat = osmesa_format; |
501 | gl_curdepth = this->gl_config.depth_size; |
502 | gl_curstencil = this->gl_config.stencil_size; |
503 | gl_curaccum = newaccumsize; |
504 | } else { |
505 | gl_curformat = 0; |
506 | gl_curdepth = 0; |
507 | gl_curstencil = 0; |
508 | gl_curaccum = 0; |
509 | } |
510 | } |
511 | |
512 | return (gl_ctx != NULL); |
513 | } |
514 | |
515 | |
516 | static int InitOld(_THIS, SDL_Surface *current) |
517 | { |
518 | GLenum osmesa_format; |
519 | SDL_PixelFormat *pixel_format; |
520 | Uint32 redmask; |
521 | int recreatecontext, tinygl_present; |
522 | |
523 | if (this->gl_config.dll_handle) { |
524 | if (this->gl_data->OSMesaCreateLDG == NULL) { |
525 | return 0; |
526 | } |
527 | } |
528 | |
529 | /* TinyGL only supports VDI_RGB (OSMESA_RGB) */ |
530 | tinygl_present=0; |
531 | if (this->gl_config.dll_handle) { |
532 | if (this->gl_data->glFinish == NULL) { |
533 | tinygl_present=1; |
534 | } |
535 | } |
536 | |
537 | /* Init OpenGL context using OSMesa */ |
538 | gl_convert = ConvertNull; |
539 | gl_copyshadow = CopyShadowNull; |
540 | gl_upsidedown = SDL_FALSE; |
541 | |
542 | pixel_format = current->format; |
543 | redmask = pixel_format->Rmask; |
544 | switch (pixel_format->BitsPerPixel) { |
545 | case 15: |
546 | /* 15 bits unsupported */ |
547 | if (tinygl_present) { |
548 | gl_pixelsize = 3; |
549 | osmesa_format = VDI_RGB; |
550 | if (redmask == 31<<10) { |
551 | gl_copyshadow = CopyShadowRGBTo555; |
552 | } else { |
553 | gl_copyshadow = CopyShadowRGBTo565; |
554 | gl_convert = Convert565To555le; |
555 | } |
556 | } else { |
557 | gl_pixelsize = 4; |
558 | gl_upsidedown = SDL_TRUE; |
559 | osmesa_format = OSMESA_ARGB; |
560 | if (redmask == 31<<10) { |
561 | gl_copyshadow = CopyShadow8888To555; |
562 | } else { |
563 | gl_copyshadow = CopyShadow8888To565; |
564 | gl_convert = Convert565To555le; |
565 | } |
566 | } |
567 | break; |
568 | case 16: |
569 | /* 16 bits unsupported */ |
570 | if (tinygl_present) { |
571 | gl_pixelsize = 3; |
572 | osmesa_format = VDI_RGB; |
573 | gl_copyshadow = CopyShadowRGBTo565; |
574 | if (redmask != 31<<11) { |
575 | /* 565, little endian, unsupported */ |
576 | gl_convert = Convert565le; |
577 | } |
578 | } else { |
579 | gl_pixelsize = 4; |
580 | gl_upsidedown = SDL_TRUE; |
581 | osmesa_format = OSMESA_ARGB; |
582 | gl_copyshadow = CopyShadow8888To565; |
583 | if (redmask != 31<<11) { |
584 | /* 565, little endian, unsupported */ |
585 | gl_convert = Convert565le; |
586 | } |
587 | } |
588 | break; |
589 | case 24: |
590 | gl_pixelsize = 3; |
591 | if (tinygl_present) { |
592 | osmesa_format = VDI_RGB; |
593 | gl_copyshadow = CopyShadowDirect; |
594 | if (redmask != 255<<16) { |
595 | gl_copyshadow = CopyShadowRGBSwap; |
596 | } |
597 | } else { |
598 | gl_copyshadow = CopyShadowDirect; |
599 | gl_upsidedown = SDL_TRUE; |
600 | if (redmask == 255<<16) { |
601 | osmesa_format = OSMESA_RGB; |
602 | } else { |
603 | osmesa_format = OSMESA_BGR; |
604 | } |
605 | } |
606 | break; |
607 | case 32: |
608 | if (tinygl_present) { |
609 | gl_pixelsize = 3; |
610 | osmesa_format = VDI_RGB; |
611 | gl_copyshadow = CopyShadowRGBToARGB; |
612 | if (redmask == 255) { |
613 | gl_convert = CopyShadowRGBToABGR; |
614 | } else if (redmask == 255<<8) { |
615 | gl_convert = CopyShadowRGBToBGRA; |
616 | } else if (redmask == 255<<24) { |
617 | gl_convert = CopyShadowRGBToRGBA; |
618 | } |
619 | } else { |
620 | gl_pixelsize = 4; |
621 | gl_upsidedown = SDL_TRUE; |
622 | gl_copyshadow = CopyShadowDirect; |
623 | if (redmask == 255<<16) { |
624 | osmesa_format = OSMESA_ARGB; |
625 | } else if (redmask == 255<<8) { |
626 | osmesa_format = OSMESA_BGRA; |
627 | } else if (redmask == 255<<24) { |
628 | osmesa_format = OSMESA_RGBA; |
629 | } else { |
630 | /* ABGR format unsupported */ |
631 | osmesa_format = OSMESA_BGRA; |
632 | gl_convert = ConvertBGRAToABGR; |
633 | } |
634 | } |
635 | break; |
636 | default: |
637 | if (tinygl_present) { |
638 | SDL_AtariGL_Quit(this, SDL_FALSE); |
639 | return 0; |
640 | } |
641 | gl_pixelsize = 1; |
642 | gl_copyshadow = CopyShadowDirect; |
643 | osmesa_format = OSMESA_COLOR_INDEX; |
644 | break; |
645 | } |
646 | |
647 | /* Try to keep current context if possible */ |
648 | recreatecontext=1; |
649 | if (gl_shadow && |
650 | (gl_curformat == osmesa_format) && |
651 | (gl_curwidth == current->w) && |
652 | (gl_curheight == current->h)) { |
653 | recreatecontext = 0; |
654 | } |
655 | if (recreatecontext) { |
656 | SDL_AtariGL_Quit(this, SDL_FALSE); |
657 | |
658 | gl_shadow = this->gl_data->OSMesaCreateLDG( |
659 | osmesa_format, GL_UNSIGNED_BYTE, current->w, current->h |
660 | ); |
661 | |
662 | if (gl_shadow) { |
663 | gl_curformat = osmesa_format; |
664 | gl_curwidth = current->w; |
665 | gl_curheight = current->h; |
666 | } else { |
667 | gl_curformat = 0; |
668 | gl_curwidth = 0; |
669 | gl_curheight = 0; |
670 | } |
671 | } |
672 | |
673 | return (gl_shadow != NULL); |
674 | } |
675 | |
676 | /*--- Conversions routines from shadow buffer to the screen ---*/ |
677 | |
678 | static void CopyShadowNull(_THIS, SDL_Surface *surface) |
679 | { |
680 | } |
681 | |
682 | static void CopyShadowDirect(_THIS, SDL_Surface *surface) |
683 | { |
684 | int y, srcpitch, dstpitch; |
685 | Uint8 *srcline, *dstline; |
686 | |
687 | srcline = gl_shadow; |
688 | srcpitch = surface->w * gl_pixelsize; |
689 | dstline = surface->pixels; |
690 | dstpitch = surface->pitch; |
691 | if (gl_upsidedown) { |
692 | srcline += (surface->h-1)*srcpitch; |
693 | srcpitch = -srcpitch; |
694 | } |
695 | |
696 | for (y=0; y<surface->h; y++) { |
697 | SDL_memcpy(dstline, srcline, srcpitch); |
698 | |
699 | srcline += srcpitch; |
700 | dstline += dstpitch; |
701 | } |
702 | } |
703 | |
704 | static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface) |
705 | { |
706 | int x,y, srcpitch, dstpitch; |
707 | Uint16 *dstline, *dstcol; |
708 | Uint8 *srcline, *srccol; |
709 | |
710 | srcline = (Uint8 *)gl_shadow; |
711 | srcpitch = surface->w * gl_pixelsize; |
712 | dstline = surface->pixels; |
713 | dstpitch = surface->pitch >>1; |
714 | if (gl_upsidedown) { |
715 | srcline += (surface->h-1)*srcpitch; |
716 | srcpitch = -srcpitch; |
717 | } |
718 | |
719 | for (y=0; y<surface->h; y++) { |
720 | srccol = srcline; |
721 | dstcol = dstline; |
722 | for (x=0; x<surface->w; x++) { |
723 | Uint16 dstcolor; |
724 | |
725 | dstcolor = ((*srccol++)<<7) & (31<<10); |
726 | dstcolor |= ((*srccol++)<<2) & (31<<5); |
727 | dstcolor |= ((*srccol++)>>3) & 31; |
728 | *dstcol++ = dstcolor; |
729 | } |
730 | |
731 | srcline += srcpitch; |
732 | dstline += dstpitch; |
733 | } |
734 | } |
735 | |
736 | static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface) |
737 | { |
738 | int x,y, srcpitch, dstpitch; |
739 | Uint16 *dstline, *dstcol; |
740 | Uint8 *srcline, *srccol; |
741 | |
742 | srcline = (Uint8 *)gl_shadow; |
743 | srcpitch = surface->w * gl_pixelsize; |
744 | dstline = surface->pixels; |
745 | dstpitch = surface->pitch >>1; |
746 | if (gl_upsidedown) { |
747 | srcline += (surface->h-1)*srcpitch; |
748 | srcpitch = -srcpitch; |
749 | } |
750 | |
751 | for (y=0; y<surface->h; y++) { |
752 | srccol = srcline; |
753 | dstcol = dstline; |
754 | |
755 | for (x=0; x<surface->w; x++) { |
756 | Uint16 dstcolor; |
757 | |
758 | dstcolor = ((*srccol++)<<8) & (31<<11); |
759 | dstcolor |= ((*srccol++)<<3) & (63<<5); |
760 | dstcolor |= ((*srccol++)>>3) & 31; |
761 | *dstcol++ = dstcolor; |
762 | } |
763 | |
764 | srcline += srcpitch; |
765 | dstline += dstpitch; |
766 | } |
767 | } |
768 | |
769 | static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface) |
770 | { |
771 | int x,y, srcpitch, dstpitch; |
772 | Uint8 *dstline, *dstcol; |
773 | Uint8 *srcline, *srccol; |
774 | |
775 | srcline = (Uint8 *)gl_shadow; |
776 | srcpitch = surface->w * gl_pixelsize; |
777 | dstline = surface->pixels; |
778 | dstpitch = surface->pitch; |
779 | if (gl_upsidedown) { |
780 | srcline += (surface->h-1)*srcpitch; |
781 | srcpitch = -srcpitch; |
782 | } |
783 | |
784 | for (y=0; y<surface->h; y++) { |
785 | srccol = srcline; |
786 | dstcol = dstline; |
787 | |
788 | for (x=0; x<surface->w; x++) { |
789 | *dstcol++ = srccol[2]; |
790 | *dstcol++ = srccol[1]; |
791 | *dstcol++ = srccol[0]; |
792 | srccol += 3; |
793 | } |
794 | |
795 | srcline += srcpitch; |
796 | dstline += dstpitch; |
797 | } |
798 | } |
799 | |
800 | static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface) |
801 | { |
802 | int x,y, srcpitch, dstpitch; |
803 | Uint32 *dstline, *dstcol; |
804 | Uint8 *srcline, *srccol; |
805 | |
806 | srcline = (Uint8 *)gl_shadow; |
807 | srcpitch = surface->w * gl_pixelsize; |
808 | dstline = surface->pixels; |
809 | dstpitch = surface->pitch >>2; |
810 | if (gl_upsidedown) { |
811 | srcline += (surface->h-1)*srcpitch; |
812 | srcpitch = -srcpitch; |
813 | } |
814 | |
815 | for (y=0; y<surface->h; y++) { |
816 | srccol = srcline; |
817 | dstcol = dstline; |
818 | |
819 | for (x=0; x<surface->w; x++) { |
820 | Uint32 dstcolor; |
821 | |
822 | dstcolor = (*srccol++)<<16; |
823 | dstcolor |= (*srccol++)<<8; |
824 | dstcolor |= *srccol++; |
825 | |
826 | *dstcol++ = dstcolor; |
827 | } |
828 | |
829 | srcline += srcpitch; |
830 | dstline += dstpitch; |
831 | } |
832 | } |
833 | |
834 | static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface) |
835 | { |
836 | int x,y, srcpitch, dstpitch; |
837 | Uint32 *dstline, *dstcol; |
838 | Uint8 *srcline, *srccol; |
839 | |
840 | srcline = (Uint8 *)gl_shadow; |
841 | srcpitch = surface->w * gl_pixelsize; |
842 | dstline = surface->pixels; |
843 | dstpitch = surface->pitch >>2; |
844 | if (gl_upsidedown) { |
845 | srcline += (surface->h-1)*srcpitch; |
846 | srcpitch = -srcpitch; |
847 | } |
848 | |
849 | for (y=0; y<surface->h; y++) { |
850 | srccol = srcline; |
851 | dstcol = dstline; |
852 | |
853 | for (x=0; x<surface->w; x++) { |
854 | Uint32 dstcolor; |
855 | |
856 | dstcolor = *srccol++; |
857 | dstcolor |= (*srccol++)<<8; |
858 | dstcolor |= (*srccol++)<<16; |
859 | |
860 | *dstcol++ = dstcolor; |
861 | } |
862 | |
863 | srcline += srcpitch; |
864 | dstline += dstpitch; |
865 | } |
866 | } |
867 | |
868 | static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface) |
869 | { |
870 | int x,y, srcpitch, dstpitch; |
871 | Uint32 *dstline, *dstcol; |
872 | Uint8 *srcline, *srccol; |
873 | |
874 | srcline = (Uint8 *)gl_shadow; |
875 | srcpitch = surface->w * gl_pixelsize; |
876 | dstline = surface->pixels; |
877 | dstpitch = surface->pitch >>2; |
878 | if (gl_upsidedown) { |
879 | srcline += (surface->h-1)*srcpitch; |
880 | srcpitch = -srcpitch; |
881 | } |
882 | |
883 | for (y=0; y<surface->h; y++) { |
884 | srccol = srcline; |
885 | dstcol = dstline; |
886 | |
887 | for (x=0; x<surface->w; x++) { |
888 | Uint32 dstcolor; |
889 | |
890 | dstcolor = (*srccol++)<<8; |
891 | dstcolor |= (*srccol++)<<16; |
892 | dstcolor |= (*srccol++)<<24; |
893 | |
894 | *dstcol++ = dstcolor; |
895 | } |
896 | |
897 | srcline += srcpitch; |
898 | dstline += dstpitch; |
899 | } |
900 | } |
901 | |
902 | static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface) |
903 | { |
904 | int x,y, srcpitch, dstpitch; |
905 | Uint32 *dstline, *dstcol; |
906 | Uint8 *srcline, *srccol; |
907 | |
908 | srcline = (Uint8 *)gl_shadow; |
909 | srcpitch = surface->w * gl_pixelsize; |
910 | dstline = surface->pixels; |
911 | dstpitch = surface->pitch >>2; |
912 | if (gl_upsidedown) { |
913 | srcline += (surface->h-1)*srcpitch; |
914 | srcpitch = -srcpitch; |
915 | } |
916 | |
917 | for (y=0; y<surface->h; y++) { |
918 | srccol = srcline; |
919 | dstcol = dstline; |
920 | |
921 | for (x=0; x<surface->w; x++) { |
922 | Uint32 dstcolor; |
923 | |
924 | dstcolor = (*srccol++)<<24; |
925 | dstcolor |= (*srccol++)<<16; |
926 | dstcolor |= (*srccol++)<<8; |
927 | |
928 | *dstcol++ = dstcolor; |
929 | } |
930 | |
931 | srcline += srcpitch; |
932 | dstline += dstpitch; |
933 | } |
934 | } |
935 | |
936 | static void CopyShadow8888To555(_THIS, SDL_Surface *surface) |
937 | { |
938 | int x,y, srcpitch, dstpitch; |
939 | Uint16 *dstline, *dstcol; |
940 | Uint32 *srcline, *srccol; |
941 | |
942 | srcline = (Uint32 *)gl_shadow; |
943 | srcpitch = (surface->w * gl_pixelsize) >>2; |
944 | dstline = surface->pixels; |
945 | dstpitch = surface->pitch >>1; |
946 | if (gl_upsidedown) { |
947 | srcline += (surface->h-1)*srcpitch; |
948 | srcpitch = -srcpitch; |
949 | } |
950 | |
951 | for (y=0; y<surface->h; y++) { |
952 | srccol = srcline; |
953 | dstcol = dstline; |
954 | for (x=0; x<surface->w; x++) { |
955 | Uint32 srccolor; |
956 | Uint16 dstcolor; |
957 | |
958 | srccolor = *srccol++; |
959 | dstcolor = (srccolor>>9) & (31<<10); |
960 | dstcolor |= (srccolor>>6) & (31<<5); |
961 | dstcolor |= (srccolor>>3) & 31; |
962 | *dstcol++ = dstcolor; |
963 | } |
964 | |
965 | srcline += srcpitch; |
966 | dstline += dstpitch; |
967 | } |
968 | } |
969 | |
970 | static void CopyShadow8888To565(_THIS, SDL_Surface *surface) |
971 | { |
972 | int x,y, srcpitch, dstpitch; |
973 | Uint16 *dstline, *dstcol; |
974 | Uint32 *srcline, *srccol; |
975 | |
976 | srcline = (Uint32 *)gl_shadow; |
977 | srcpitch = (surface->w * gl_pixelsize) >> 2; |
978 | dstline = surface->pixels; |
979 | dstpitch = surface->pitch >>1; |
980 | if (gl_upsidedown) { |
981 | srcline += (surface->h-1)*srcpitch; |
982 | srcpitch = -srcpitch; |
983 | } |
984 | |
985 | for (y=0; y<surface->h; y++) { |
986 | srccol = srcline; |
987 | dstcol = dstline; |
988 | |
989 | for (x=0; x<surface->w; x++) { |
990 | Uint32 srccolor; |
991 | Uint16 dstcolor; |
992 | |
993 | srccolor = *srccol++; |
994 | dstcolor = (srccolor>>8) & (31<<11); |
995 | dstcolor |= (srccolor>>5) & (63<<5); |
996 | dstcolor |= (srccolor>>3) & 31; |
997 | *dstcol++ = dstcolor; |
998 | } |
999 | |
1000 | srcline += srcpitch; |
1001 | dstline += dstpitch; |
1002 | } |
1003 | } |
1004 | |
1005 | /*--- Conversions routines in the screen ---*/ |
1006 | |
1007 | static void ConvertNull(_THIS, SDL_Surface *surface) |
1008 | { |
1009 | } |
1010 | |
1011 | static void Convert565To555be(_THIS, SDL_Surface *surface) |
1012 | { |
1013 | int x,y, pitch; |
1014 | unsigned short *line, *pixel; |
1015 | |
1016 | line = surface->pixels; |
1017 | pitch = surface->pitch >> 1; |
1018 | for (y=0; y<surface->h; y++) { |
1019 | pixel = line; |
1020 | for (x=0; x<surface->w; x++) { |
1021 | unsigned short color = *pixel; |
1022 | |
1023 | *pixel++ = (color & 0x1f)|((color>>1) & 0xffe0); |
1024 | } |
1025 | |
1026 | line += pitch; |
1027 | } |
1028 | } |
1029 | |
1030 | static void Convert565To555le(_THIS, SDL_Surface *surface) |
1031 | { |
1032 | int x,y, pitch; |
1033 | unsigned short *line, *pixel; |
1034 | |
1035 | line = surface->pixels; |
1036 | pitch = surface->pitch >>1; |
1037 | for (y=0; y<surface->h; y++) { |
1038 | pixel = line; |
1039 | for (x=0; x<surface->w; x++) { |
1040 | unsigned short color = *pixel; |
1041 | |
1042 | color = (color & 0x1f)|((color>>1) & 0xffe0); |
1043 | *pixel++ = SDL_Swap16(color); |
1044 | } |
1045 | |
1046 | line += pitch; |
1047 | } |
1048 | } |
1049 | |
1050 | static void Convert565le(_THIS, SDL_Surface *surface) |
1051 | { |
1052 | int x,y, pitch; |
1053 | unsigned short *line, *pixel; |
1054 | |
1055 | line = surface->pixels; |
1056 | pitch = surface->pitch >>1; |
1057 | for (y=0; y<surface->h; y++) { |
1058 | pixel = line; |
1059 | for (x=0; x<surface->w; x++) { |
1060 | unsigned short color = *pixel; |
1061 | |
1062 | *pixel++ = SDL_Swap16(color); |
1063 | } |
1064 | |
1065 | line += pitch; |
1066 | } |
1067 | } |
1068 | |
1069 | static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface) |
1070 | { |
1071 | int x,y, pitch; |
1072 | unsigned long *line, *pixel; |
1073 | |
1074 | line = surface->pixels; |
1075 | pitch = surface->pitch >>2; |
1076 | for (y=0; y<surface->h; y++) { |
1077 | pixel = line; |
1078 | for (x=0; x<surface->w; x++) { |
1079 | unsigned long color = *pixel; |
1080 | |
1081 | *pixel++ = (color<<24)|(color>>8); |
1082 | } |
1083 | |
1084 | line += pitch; |
1085 | } |
1086 | } |
1087 | |
1088 | #endif /* SDL_VIDEO_OPENGL */ |