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