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