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