Home | History | Annotate | Download | only in ataricommon
      1 /*
      2     SDL - Simple DirectMedia Layer
      3     Copyright (C) 1997-2012 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 #if SDL_VIDEO_OPENGL
     52 static void SDL_AtariGL_UnloadLibrary(_THIS);
     53 
     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 #if SDL_VIDEO_OPENGL
    393 static void SDL_AtariGL_UnloadLibrary(_THIS)
    394 {
    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 }
    403 
    404 /*--- Creation of an OpenGL context using new/old functions ---*/
    405 
    406 static int InitNew(_THIS, SDL_Surface *current)
    407 {
    408 	GLenum osmesa_format;
    409 	SDL_PixelFormat *pixel_format;
    410 	Uint32	redmask;
    411 	int recreatecontext;
    412 	GLint newaccumsize;
    413 
    414 	if (this->gl_config.dll_handle) {
    415 		if (this->gl_data->OSMesaCreateContextExt == NULL) {
    416 			return 0;
    417 		}
    418 	}
    419 
    420 	/* Init OpenGL context using OSMesa */
    421 	gl_convert = ConvertNull;
    422 	gl_copyshadow = CopyShadowNull;
    423 	gl_upsidedown = SDL_FALSE;
    424 
    425 	pixel_format = current->format;
    426 	redmask = pixel_format->Rmask;
    427 	switch (pixel_format->BitsPerPixel) {
    428 		case 15:
    429 			/* 1555, big and little endian, unsupported */
    430 			gl_pixelsize = 2;
    431 			osmesa_format = OSMESA_RGB_565;
    432 			if (redmask == 31<<10) {
    433 				gl_convert = Convert565To555be;
    434 			} else {
    435 				gl_convert = Convert565To555le;
    436 			}
    437 			break;
    438 		case 16:
    439 			gl_pixelsize = 2;
    440 			if (redmask == 31<<11) {
    441 				osmesa_format = OSMESA_RGB_565;
    442 			} else {
    443 				/* 565, little endian, unsupported */
    444 				osmesa_format = OSMESA_RGB_565;
    445 				gl_convert = Convert565le;
    446 			}
    447 			break;
    448 		case 24:
    449 			gl_pixelsize = 3;
    450 			if (redmask == 255<<16) {
    451 				osmesa_format = OSMESA_RGB;
    452 			} else {
    453 				osmesa_format = OSMESA_BGR;
    454 			}
    455 			break;
    456 		case 32:
    457 			gl_pixelsize = 4;
    458 			if (redmask == 255<<16) {
    459 				osmesa_format = OSMESA_ARGB;
    460 			} else if (redmask == 255<<8) {
    461 				osmesa_format = OSMESA_BGRA;
    462 			} else if (redmask == 255<<24) {
    463 				osmesa_format = OSMESA_RGBA;
    464 			} else {
    465 				/* ABGR format unsupported */
    466 				osmesa_format = OSMESA_BGRA;
    467 				gl_convert = ConvertBGRAToABGR;
    468 			}
    469 			break;
    470 		default:
    471 			gl_pixelsize = 1;
    472 			osmesa_format = OSMESA_COLOR_INDEX;
    473 			break;
    474 	}
    475 
    476 	/* Try to keep current context if possible */
    477 	newaccumsize =
    478 		this->gl_config.accum_red_size +
    479 		this->gl_config.accum_green_size +
    480 		this->gl_config.accum_blue_size +
    481 		this->gl_config.accum_alpha_size;
    482 	recreatecontext=1;
    483 	if (gl_ctx &&
    484 		(gl_curformat == osmesa_format) &&
    485 		(gl_curdepth == this->gl_config.depth_size) &&
    486 		(gl_curstencil == this->gl_config.stencil_size) &&
    487 		(gl_curaccum == newaccumsize)) {
    488 		recreatecontext = 0;
    489 	}
    490 	if (recreatecontext) {
    491 		SDL_AtariGL_Quit(this, SDL_FALSE);
    492 
    493 		gl_ctx = this->gl_data->OSMesaCreateContextExt(
    494 			osmesa_format, this->gl_config.depth_size,
    495 			this->gl_config.stencil_size, newaccumsize, NULL );
    496 
    497 		if (gl_ctx) {
    498 			gl_curformat = osmesa_format;
    499 			gl_curdepth = this->gl_config.depth_size;
    500 			gl_curstencil = this->gl_config.stencil_size;
    501 			gl_curaccum = newaccumsize;
    502 		} else {
    503 			gl_curformat = 0;
    504 			gl_curdepth = 0;
    505 			gl_curstencil = 0;
    506 			gl_curaccum = 0;
    507 		}
    508 	}
    509 
    510 	return (gl_ctx != NULL);
    511 }
    512 
    513 
    514 static int InitOld(_THIS, SDL_Surface *current)
    515 {
    516 	GLenum osmesa_format;
    517 	SDL_PixelFormat *pixel_format;
    518 	Uint32	redmask;
    519 	int recreatecontext, tinygl_present;
    520 
    521 	if (this->gl_config.dll_handle) {
    522 		if (this->gl_data->OSMesaCreateLDG == NULL) {
    523 			return 0;
    524 		}
    525 	}
    526 
    527 	/* TinyGL only supports VDI_RGB (OSMESA_RGB) */
    528 	tinygl_present=0;
    529 	if (this->gl_config.dll_handle) {
    530 		if (this->gl_data->glFinish == NULL) {
    531 			tinygl_present=1;
    532 		}
    533 	}
    534 
    535 	/* Init OpenGL context using OSMesa */
    536 	gl_convert = ConvertNull;
    537 	gl_copyshadow = CopyShadowNull;
    538 	gl_upsidedown = SDL_FALSE;
    539 
    540 	pixel_format = current->format;
    541 	redmask = pixel_format->Rmask;
    542 	switch (pixel_format->BitsPerPixel) {
    543 		case 15:
    544 			/* 15 bits unsupported */
    545 			if (tinygl_present) {
    546 				gl_pixelsize = 3;
    547 				osmesa_format = VDI_RGB;
    548 				if (redmask == 31<<10) {
    549 					gl_copyshadow = CopyShadowRGBTo555;
    550 				} else {
    551 					gl_copyshadow = CopyShadowRGBTo565;
    552 					gl_convert = Convert565To555le;
    553 				}
    554 			} else {
    555 				gl_pixelsize = 4;
    556 				gl_upsidedown = SDL_TRUE;
    557 				osmesa_format = OSMESA_ARGB;
    558 				if (redmask == 31<<10) {
    559 					gl_copyshadow = CopyShadow8888To555;
    560 				} else {
    561 					gl_copyshadow = CopyShadow8888To565;
    562 					gl_convert = Convert565To555le;
    563 				}
    564 			}
    565 			break;
    566 		case 16:
    567 			/* 16 bits unsupported */
    568 			if (tinygl_present) {
    569 				gl_pixelsize = 3;
    570 				osmesa_format = VDI_RGB;
    571 				gl_copyshadow = CopyShadowRGBTo565;
    572 				if (redmask != 31<<11) {
    573 					/* 565, little endian, unsupported */
    574 					gl_convert = Convert565le;
    575 				}
    576 			} else {
    577 				gl_pixelsize = 4;
    578 				gl_upsidedown = SDL_TRUE;
    579 				osmesa_format = OSMESA_ARGB;
    580 				gl_copyshadow = CopyShadow8888To565;
    581 				if (redmask != 31<<11) {
    582 					/* 565, little endian, unsupported */
    583 					gl_convert = Convert565le;
    584 				}
    585 			}
    586 			break;
    587 		case 24:
    588 			gl_pixelsize = 3;
    589 			if (tinygl_present) {
    590 				osmesa_format = VDI_RGB;
    591 				gl_copyshadow = CopyShadowDirect;
    592 				if (redmask != 255<<16) {
    593 					gl_copyshadow = CopyShadowRGBSwap;
    594 				}
    595 			} else {
    596 				gl_copyshadow = CopyShadowDirect;
    597 				gl_upsidedown = SDL_TRUE;
    598 				if (redmask == 255<<16) {
    599 					osmesa_format = OSMESA_RGB;
    600 				} else {
    601 					osmesa_format = OSMESA_BGR;
    602 				}
    603 			}
    604 			break;
    605 		case 32:
    606 			if (tinygl_present) {
    607 				gl_pixelsize = 3;
    608 				osmesa_format = VDI_RGB;
    609 				gl_copyshadow = CopyShadowRGBToARGB;
    610 				if (redmask == 255) {
    611 					gl_convert = CopyShadowRGBToABGR;
    612 				} else if (redmask == 255<<8) {
    613 					gl_convert = CopyShadowRGBToBGRA;
    614 				} else if (redmask == 255<<24) {
    615 					gl_convert = CopyShadowRGBToRGBA;
    616 				}
    617 			} else {
    618 				gl_pixelsize = 4;
    619 				gl_upsidedown = SDL_TRUE;
    620 				gl_copyshadow = CopyShadowDirect;
    621 				if (redmask == 255<<16) {
    622 					osmesa_format = OSMESA_ARGB;
    623 				} else if (redmask == 255<<8) {
    624 					osmesa_format = OSMESA_BGRA;
    625 				} else if (redmask == 255<<24) {
    626 					osmesa_format = OSMESA_RGBA;
    627 				} else {
    628 					/* ABGR format unsupported */
    629 					osmesa_format = OSMESA_BGRA;
    630 					gl_convert = ConvertBGRAToABGR;
    631 				}
    632 			}
    633 			break;
    634 		default:
    635 			if (tinygl_present) {
    636 				SDL_AtariGL_Quit(this, SDL_FALSE);
    637 				return 0;
    638 			}
    639 			gl_pixelsize = 1;
    640 			gl_copyshadow = CopyShadowDirect;
    641 			osmesa_format = OSMESA_COLOR_INDEX;
    642 			break;
    643 	}
    644 
    645 	/* Try to keep current context if possible */
    646 	recreatecontext=1;
    647 	if (gl_shadow &&
    648 		(gl_curformat == osmesa_format) &&
    649 		(gl_curwidth == current->w) &&
    650 		(gl_curheight == current->h)) {
    651 		recreatecontext = 0;
    652 	}
    653 	if (recreatecontext) {
    654 		SDL_AtariGL_Quit(this, SDL_FALSE);
    655 
    656 		gl_shadow = this->gl_data->OSMesaCreateLDG(
    657 			osmesa_format, GL_UNSIGNED_BYTE, current->w, current->h
    658 		);
    659 
    660 		if (gl_shadow) {
    661 			gl_curformat = osmesa_format;
    662 			gl_curwidth = current->w;
    663 			gl_curheight = current->h;
    664 		} else {
    665 			gl_curformat = 0;
    666 			gl_curwidth = 0;
    667 			gl_curheight = 0;
    668 		}
    669 	}
    670 
    671 	return (gl_shadow != NULL);
    672 }
    673 
    674 /*--- Conversions routines from shadow buffer to the screen ---*/
    675 
    676 static void CopyShadowNull(_THIS, SDL_Surface *surface)
    677 {
    678 }
    679 
    680 static void CopyShadowDirect(_THIS, SDL_Surface *surface)
    681 {
    682 	int y, srcpitch, dstpitch;
    683 	Uint8 *srcline, *dstline;
    684 
    685 	srcline = gl_shadow;
    686 	srcpitch = surface->w * gl_pixelsize;
    687 	dstline = surface->pixels;
    688 	dstpitch = surface->pitch;
    689 	if (gl_upsidedown) {
    690 		srcline += (surface->h-1)*srcpitch;
    691 		srcpitch = -srcpitch;
    692 	}
    693 
    694 	for (y=0; y<surface->h; y++) {
    695 		SDL_memcpy(dstline, srcline, srcpitch);
    696 
    697 		srcline += srcpitch;
    698 		dstline += dstpitch;
    699 	}
    700 }
    701 
    702 static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface)
    703 {
    704 	int x,y, srcpitch, dstpitch;
    705 	Uint16 *dstline, *dstcol;
    706 	Uint8 *srcline, *srccol;
    707 
    708 	srcline = (Uint8 *)gl_shadow;
    709 	srcpitch = surface->w * gl_pixelsize;
    710 	dstline = surface->pixels;
    711 	dstpitch = surface->pitch >>1;
    712 	if (gl_upsidedown) {
    713 		srcline += (surface->h-1)*srcpitch;
    714 		srcpitch = -srcpitch;
    715 	}
    716 
    717 	for (y=0; y<surface->h; y++) {
    718 		srccol = srcline;
    719 		dstcol = dstline;
    720 		for (x=0; x<surface->w; x++) {
    721 			Uint16 dstcolor;
    722 
    723 			dstcolor = ((*srccol++)<<7) & (31<<10);
    724 			dstcolor |= ((*srccol++)<<2) & (31<<5);
    725 			dstcolor |= ((*srccol++)>>3) & 31;
    726 			*dstcol++ = dstcolor;
    727 		}
    728 
    729 		srcline += srcpitch;
    730 		dstline += dstpitch;
    731 	}
    732 }
    733 
    734 static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface)
    735 {
    736 	int x,y, srcpitch, dstpitch;
    737 	Uint16 *dstline, *dstcol;
    738 	Uint8 *srcline, *srccol;
    739 
    740 	srcline = (Uint8 *)gl_shadow;
    741 	srcpitch = surface->w * gl_pixelsize;
    742 	dstline = surface->pixels;
    743 	dstpitch = surface->pitch >>1;
    744 	if (gl_upsidedown) {
    745 		srcline += (surface->h-1)*srcpitch;
    746 		srcpitch = -srcpitch;
    747 	}
    748 
    749 	for (y=0; y<surface->h; y++) {
    750 		srccol = srcline;
    751 		dstcol = dstline;
    752 
    753 		for (x=0; x<surface->w; x++) {
    754 			Uint16 dstcolor;
    755 
    756 			dstcolor = ((*srccol++)<<8) & (31<<11);
    757 			dstcolor |= ((*srccol++)<<3) & (63<<5);
    758 			dstcolor |= ((*srccol++)>>3) & 31;
    759 			*dstcol++ = dstcolor;
    760 		}
    761 
    762 		srcline += srcpitch;
    763 		dstline += dstpitch;
    764 	}
    765 }
    766 
    767 static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface)
    768 {
    769 	int x,y, srcpitch, dstpitch;
    770 	Uint8 *dstline, *dstcol;
    771 	Uint8 *srcline, *srccol;
    772 
    773 	srcline = (Uint8 *)gl_shadow;
    774 	srcpitch = surface->w * gl_pixelsize;
    775 	dstline = surface->pixels;
    776 	dstpitch = surface->pitch;
    777 	if (gl_upsidedown) {
    778 		srcline += (surface->h-1)*srcpitch;
    779 		srcpitch = -srcpitch;
    780 	}
    781 
    782 	for (y=0; y<surface->h; y++) {
    783 		srccol = srcline;
    784 		dstcol = dstline;
    785 
    786 		for (x=0; x<surface->w; x++) {
    787 			*dstcol++ = srccol[2];
    788 			*dstcol++ = srccol[1];
    789 			*dstcol++ = srccol[0];
    790 			srccol += 3;
    791 		}
    792 
    793 		srcline += srcpitch;
    794 		dstline += dstpitch;
    795 	}
    796 }
    797 
    798 static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface)
    799 {
    800 	int x,y, srcpitch, dstpitch;
    801 	Uint32 *dstline, *dstcol;
    802 	Uint8 *srcline, *srccol;
    803 
    804 	srcline = (Uint8 *)gl_shadow;
    805 	srcpitch = surface->w * gl_pixelsize;
    806 	dstline = surface->pixels;
    807 	dstpitch = surface->pitch >>2;
    808 	if (gl_upsidedown) {
    809 		srcline += (surface->h-1)*srcpitch;
    810 		srcpitch = -srcpitch;
    811 	}
    812 
    813 	for (y=0; y<surface->h; y++) {
    814 		srccol = srcline;
    815 		dstcol = dstline;
    816 
    817 		for (x=0; x<surface->w; x++) {
    818 			Uint32	dstcolor;
    819 
    820 			dstcolor = (*srccol++)<<16;
    821 			dstcolor |= (*srccol++)<<8;
    822 			dstcolor |= *srccol++;
    823 
    824 			*dstcol++ = dstcolor;
    825 		}
    826 
    827 		srcline += srcpitch;
    828 		dstline += dstpitch;
    829 	}
    830 }
    831 
    832 static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface)
    833 {
    834 	int x,y, srcpitch, dstpitch;
    835 	Uint32 *dstline, *dstcol;
    836 	Uint8 *srcline, *srccol;
    837 
    838 	srcline = (Uint8 *)gl_shadow;
    839 	srcpitch = surface->w * gl_pixelsize;
    840 	dstline = surface->pixels;
    841 	dstpitch = surface->pitch >>2;
    842 	if (gl_upsidedown) {
    843 		srcline += (surface->h-1)*srcpitch;
    844 		srcpitch = -srcpitch;
    845 	}
    846 
    847 	for (y=0; y<surface->h; y++) {
    848 		srccol = srcline;
    849 		dstcol = dstline;
    850 
    851 		for (x=0; x<surface->w; x++) {
    852 			Uint32	dstcolor;
    853 
    854 			dstcolor = *srccol++;
    855 			dstcolor |= (*srccol++)<<8;
    856 			dstcolor |= (*srccol++)<<16;
    857 
    858 			*dstcol++ = dstcolor;
    859 		}
    860 
    861 		srcline += srcpitch;
    862 		dstline += dstpitch;
    863 	}
    864 }
    865 
    866 static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface)
    867 {
    868 	int x,y, srcpitch, dstpitch;
    869 	Uint32 *dstline, *dstcol;
    870 	Uint8 *srcline, *srccol;
    871 
    872 	srcline = (Uint8 *)gl_shadow;
    873 	srcpitch = surface->w * gl_pixelsize;
    874 	dstline = surface->pixels;
    875 	dstpitch = surface->pitch >>2;
    876 	if (gl_upsidedown) {
    877 		srcline += (surface->h-1)*srcpitch;
    878 		srcpitch = -srcpitch;
    879 	}
    880 
    881 	for (y=0; y<surface->h; y++) {
    882 		srccol = srcline;
    883 		dstcol = dstline;
    884 
    885 		for (x=0; x<surface->w; x++) {
    886 			Uint32	dstcolor;
    887 
    888 			dstcolor = (*srccol++)<<8;
    889 			dstcolor |= (*srccol++)<<16;
    890 			dstcolor |= (*srccol++)<<24;
    891 
    892 			*dstcol++ = dstcolor;
    893 		}
    894 
    895 		srcline += srcpitch;
    896 		dstline += dstpitch;
    897 	}
    898 }
    899 
    900 static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface)
    901 {
    902 	int x,y, srcpitch, dstpitch;
    903 	Uint32 *dstline, *dstcol;
    904 	Uint8 *srcline, *srccol;
    905 
    906 	srcline = (Uint8 *)gl_shadow;
    907 	srcpitch = surface->w * gl_pixelsize;
    908 	dstline = surface->pixels;
    909 	dstpitch = surface->pitch >>2;
    910 	if (gl_upsidedown) {
    911 		srcline += (surface->h-1)*srcpitch;
    912 		srcpitch = -srcpitch;
    913 	}
    914 
    915 	for (y=0; y<surface->h; y++) {
    916 		srccol = srcline;
    917 		dstcol = dstline;
    918 
    919 		for (x=0; x<surface->w; x++) {
    920 			Uint32	dstcolor;
    921 
    922 			dstcolor = (*srccol++)<<24;
    923 			dstcolor |= (*srccol++)<<16;
    924 			dstcolor |= (*srccol++)<<8;
    925 
    926 			*dstcol++ = dstcolor;
    927 		}
    928 
    929 		srcline += srcpitch;
    930 		dstline += dstpitch;
    931 	}
    932 }
    933 
    934 static void CopyShadow8888To555(_THIS, SDL_Surface *surface)
    935 {
    936 	int x,y, srcpitch, dstpitch;
    937 	Uint16 *dstline, *dstcol;
    938 	Uint32 *srcline, *srccol;
    939 
    940 	srcline = (Uint32 *)gl_shadow;
    941 	srcpitch = (surface->w * gl_pixelsize) >>2;
    942 	dstline = surface->pixels;
    943 	dstpitch = surface->pitch >>1;
    944 	if (gl_upsidedown) {
    945 		srcline += (surface->h-1)*srcpitch;
    946 		srcpitch = -srcpitch;
    947 	}
    948 
    949 	for (y=0; y<surface->h; y++) {
    950 		srccol = srcline;
    951 		dstcol = dstline;
    952 		for (x=0; x<surface->w; x++) {
    953 			Uint32 srccolor;
    954 			Uint16 dstcolor;
    955 
    956 			srccolor = *srccol++;
    957 			dstcolor = (srccolor>>9) & (31<<10);
    958 			dstcolor |= (srccolor>>6) & (31<<5);
    959 			dstcolor |= (srccolor>>3) & 31;
    960 			*dstcol++ = dstcolor;
    961 		}
    962 
    963 		srcline += srcpitch;
    964 		dstline += dstpitch;
    965 	}
    966 }
    967 
    968 static void CopyShadow8888To565(_THIS, SDL_Surface *surface)
    969 {
    970 	int x,y, srcpitch, dstpitch;
    971 	Uint16 *dstline, *dstcol;
    972 	Uint32 *srcline, *srccol;
    973 
    974 	srcline = (Uint32 *)gl_shadow;
    975 	srcpitch = (surface->w * gl_pixelsize) >> 2;
    976 	dstline = surface->pixels;
    977 	dstpitch = surface->pitch >>1;
    978 	if (gl_upsidedown) {
    979 		srcline += (surface->h-1)*srcpitch;
    980 		srcpitch = -srcpitch;
    981 	}
    982 
    983 	for (y=0; y<surface->h; y++) {
    984 		srccol = srcline;
    985 		dstcol = dstline;
    986 
    987 		for (x=0; x<surface->w; x++) {
    988 			Uint32 srccolor;
    989 			Uint16 dstcolor;
    990 
    991 			srccolor = *srccol++;
    992 			dstcolor = (srccolor>>8) & (31<<11);
    993 			dstcolor |= (srccolor>>5) & (63<<5);
    994 			dstcolor |= (srccolor>>3) & 31;
    995 			*dstcol++ = dstcolor;
    996 		}
    997 
    998 		srcline += srcpitch;
    999 		dstline += dstpitch;
   1000 	}
   1001 }
   1002 
   1003 /*--- Conversions routines in the screen ---*/
   1004 
   1005 static void ConvertNull(_THIS, SDL_Surface *surface)
   1006 {
   1007 }
   1008 
   1009 static void Convert565To555be(_THIS, SDL_Surface *surface)
   1010 {
   1011 	int x,y, pitch;
   1012 	unsigned short *line, *pixel;
   1013 
   1014 	line = surface->pixels;
   1015 	pitch = surface->pitch >> 1;
   1016 	for (y=0; y<surface->h; y++) {
   1017 		pixel = line;
   1018 		for (x=0; x<surface->w; x++) {
   1019 			unsigned short color = *pixel;
   1020 
   1021 			*pixel++ = (color & 0x1f)|((color>>1) & 0xffe0);
   1022 		}
   1023 
   1024 		line += pitch;
   1025 	}
   1026 }
   1027 
   1028 static void Convert565To555le(_THIS, SDL_Surface *surface)
   1029 {
   1030 	int x,y, pitch;
   1031 	unsigned short *line, *pixel;
   1032 
   1033 	line = surface->pixels;
   1034 	pitch = surface->pitch >>1;
   1035 	for (y=0; y<surface->h; y++) {
   1036 		pixel = line;
   1037 		for (x=0; x<surface->w; x++) {
   1038 			unsigned short color = *pixel;
   1039 
   1040 			color = (color & 0x1f)|((color>>1) & 0xffe0);
   1041 			*pixel++ = SDL_Swap16(color);
   1042 		}
   1043 
   1044 		line += pitch;
   1045 	}
   1046 }
   1047 
   1048 static void Convert565le(_THIS, SDL_Surface *surface)
   1049 {
   1050 	int x,y, pitch;
   1051 	unsigned short *line, *pixel;
   1052 
   1053 	line = surface->pixels;
   1054 	pitch = surface->pitch >>1;
   1055 	for (y=0; y<surface->h; y++) {
   1056 		pixel = line;
   1057 		for (x=0; x<surface->w; x++) {
   1058 			unsigned short color = *pixel;
   1059 
   1060 			*pixel++ = SDL_Swap16(color);
   1061 		}
   1062 
   1063 		line += pitch;
   1064 	}
   1065 }
   1066 
   1067 static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface)
   1068 {
   1069 	int x,y, pitch;
   1070 	unsigned long *line, *pixel;
   1071 
   1072 	line = surface->pixels;
   1073 	pitch = surface->pitch >>2;
   1074 	for (y=0; y<surface->h; y++) {
   1075 		pixel = line;
   1076 		for (x=0; x<surface->w; x++) {
   1077 			unsigned long color = *pixel;
   1078 
   1079 			*pixel++ = (color<<24)|(color>>8);
   1080 		}
   1081 
   1082 		line += pitch;
   1083 	}
   1084 }
   1085 
   1086 #endif /* SDL_VIDEO_OPENGL */
   1087