Home | History | Annotate | Download | only in ataricommon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2004 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 (at) 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 */
   1089