src/video/ataricommon/SDL_atarigl.c
author Patrice Mandin
Tue, 30 Nov 2004 16:14:05 +0000
changeset 1000 fbeac9312843
parent 995 22fc5f45bbb7
child 1002 13aa96c76e86
permissions -rw-r--r--
TinyGL only support RGB24 color buffer
     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 
   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 
   543 	pixel_format = current->format;
   544 	redmask = pixel_format->Rmask;
   545 	switch (pixel_format->BitsPerPixel) {
   546 		case 15:
   547 			/* 15 bits unsupported */
   548 			gl_pixelsize = 2;
   549 			if (tinygl_present) {
   550 				osmesa_format = VDI_RGB;
   551 				if (redmask == 31<<10) {
   552 					gl_copyshadow = CopyShadowRGBTo555;
   553 				} else {
   554 					gl_copyshadow = CopyShadowRGBTo565;
   555 					gl_convert = Convert565To555le;
   556 				}
   557 			} else {
   558 				osmesa_format = OSMESA_ARGB;
   559 				if (redmask == 31<<10) {
   560 					gl_copyshadow = CopyShadow8888To555;
   561 				} else {
   562 					gl_copyshadow = CopyShadow8888To565;
   563 					gl_convert = Convert565To555le;
   564 				}
   565 			}
   566 			break;
   567 		case 16:
   568 			/* 16 bits unsupported */
   569 			gl_pixelsize = 2;
   570 			if (tinygl_present) {
   571 				osmesa_format = VDI_RGB;
   572 				gl_copyshadow = CopyShadowRGBTo565;
   573 				if (redmask != 31<<11) {
   574 					/* 565, little endian, unsupported */
   575 					gl_convert = Convert565le;
   576 				}
   577 			} else {
   578 				osmesa_format = OSMESA_ARGB;
   579 				gl_copyshadow = CopyShadow8888To565;
   580 				if (redmask != 31<<11) {
   581 					/* 565, little endian, unsupported */
   582 					gl_convert = Convert565le;
   583 				}
   584 			}
   585 			break;
   586 		case 24:
   587 			gl_pixelsize = 3;
   588 			if (tinygl_present) {
   589 				osmesa_format = VDI_RGB;
   590 				gl_copyshadow = CopyShadowDirect;
   591 				if (redmask != 255<<16) {
   592 					gl_copyshadow = CopyShadowRGBSwap;
   593 				}
   594 			} else {
   595 				gl_copyshadow = CopyShadowDirect;
   596 				if (redmask == 255<<16) {
   597 					osmesa_format = OSMESA_RGB;
   598 				} else {
   599 					osmesa_format = OSMESA_BGR;
   600 				}
   601 			}
   602 			break;
   603 		case 32:
   604 			gl_pixelsize = 4;
   605 			if (tinygl_present) {
   606 				osmesa_format = VDI_RGB;
   607 				gl_copyshadow = CopyShadowRGBToARGB;
   608 				if (redmask == 255) {
   609 					gl_convert = CopyShadowRGBToABGR;
   610 				} else if (redmask == 255<<8) {
   611 					gl_convert = CopyShadowRGBToBGRA;
   612 				} else if (redmask == 255<<24) {
   613 					gl_convert = CopyShadowRGBToRGBA;
   614 				}
   615 			} else {
   616 				gl_copyshadow = CopyShadowDirect;
   617 				if (redmask == 255<<16) {
   618 					osmesa_format = OSMESA_ARGB;
   619 				} else if (redmask == 255<<8) {
   620 					osmesa_format = OSMESA_BGRA;
   621 				} else if (redmask == 255<<24) {
   622 					osmesa_format = OSMESA_RGBA;
   623 				} else {
   624 					/* ABGR format unsupported */
   625 					osmesa_format = OSMESA_BGRA;
   626 					gl_convert = ConvertBGRAToABGR;
   627 				}
   628 			}
   629 			break;
   630 		default:
   631 			if (tinygl_present) {
   632 				SDL_AtariGL_Quit(this, SDL_FALSE);
   633 				return 0;
   634 			}
   635 			gl_pixelsize = 1;
   636 			gl_copyshadow = CopyShadowDirect;
   637 			osmesa_format = OSMESA_COLOR_INDEX;
   638 			break;
   639 	}
   640 
   641 	/* Try to keep current context if possible */
   642 	recreatecontext=1;
   643 	if (gl_shadow &&
   644 		(gl_curformat == osmesa_format) &&
   645 		(gl_curwidth == current->w) &&
   646 		(gl_curheight == current->h)) {
   647 		recreatecontext = 0;
   648 	}
   649 	if (recreatecontext) {
   650 		SDL_AtariGL_Quit(this, SDL_FALSE);
   651 
   652 		gl_shadow = this->gl_data->OSMesaCreateLDG(
   653 			osmesa_format, GL_UNSIGNED_BYTE, current->w, current->h
   654 		);
   655 
   656 		if (gl_shadow) {
   657 			gl_curformat = osmesa_format;
   658 			gl_curwidth = current->w;
   659 			gl_curheight = current->h;
   660 		} else {
   661 			gl_curformat = 0;
   662 			gl_curwidth = 0;
   663 			gl_curheight = 0;
   664 		}
   665 	}
   666 
   667 	return (gl_shadow != NULL);
   668 }
   669 
   670 /*--- Conversions routines from shadow buffer to the screen ---*/
   671 
   672 static void CopyShadowNull(_THIS, SDL_Surface *surface)
   673 {
   674 }
   675 
   676 static void CopyShadowDirect(_THIS, SDL_Surface *surface)
   677 {
   678 	int y, srcpitch, dstpitch;
   679 	Uint8 *srcline, *dstline;
   680 
   681 	srcline = gl_shadow;
   682 	srcpitch = surface->w * gl_pixelsize;
   683 	dstline = surface->pixels;
   684 	dstpitch = surface->pitch;
   685 
   686 	for (y=0; y<surface->h; y++) {
   687 		memcpy(dstline, srcline, srcpitch);
   688 
   689 		srcline += srcpitch;
   690 		dstline += dstpitch;
   691 	}
   692 }
   693 
   694 static void CopyShadowRGBTo555(_THIS, SDL_Surface *surface)
   695 {
   696 	int x,y, srcpitch, dstpitch;
   697 	Uint16 *dstline, *dstcol;
   698 	Uint8 *srcline, *srccol;
   699 
   700 	srcline = (Uint8 *)gl_shadow;
   701 	srcpitch = surface->w *3;
   702 	dstline = surface->pixels;
   703 	dstpitch = surface->pitch >>1;
   704 
   705 	for (y=0; y<surface->h; y++) {
   706 		srccol = srcline;
   707 		dstcol = dstline;
   708 		for (x=0; x<surface->w; x++) {
   709 			Uint16 dstcolor;
   710 			
   711 			dstcolor = ((*srccol++)>>9) & (31<<10);
   712 			dstcolor |= ((*srccol++)>>6) & (31<<5);
   713 			dstcolor |= ((*srccol++)>>3) & 31;
   714 			*dstcol++ = dstcolor;
   715 		}
   716 
   717 		srcline += srcpitch;
   718 		dstline += dstpitch;
   719 	}
   720 }
   721 
   722 static void CopyShadowRGBTo565(_THIS, SDL_Surface *surface)
   723 {
   724 	int x,y, srcpitch, dstpitch;
   725 	Uint16 *dstline, *dstcol;
   726 	Uint8 *srcline, *srccol;
   727 
   728 	srcline = (Uint8 *)gl_shadow;
   729 	srcpitch = surface->w *3;
   730 	dstline = surface->pixels;
   731 	dstpitch = surface->pitch >>1;
   732 
   733 	for (y=0; y<surface->h; y++) {
   734 		srccol = srcline;
   735 		dstcol = dstline;
   736 
   737 		for (x=0; x<surface->w; x++) {
   738 			Uint16 dstcolor;
   739 			
   740 			dstcolor = ((*srccol++)>>8) & (31<<11);
   741 			dstcolor |= ((*srccol++)>>5) & (63<<5);
   742 			dstcolor |= ((*srccol++)>>3) & 31;
   743 			*dstcol++ = dstcolor;
   744 		}
   745 
   746 		srcline += srcpitch;
   747 		dstline += dstpitch;
   748 	}
   749 }
   750 
   751 static void CopyShadowRGBSwap(_THIS, SDL_Surface *surface)
   752 {
   753 	int x,y, srcpitch, dstpitch;
   754 	Uint8 *dstline, *dstcol;
   755 	Uint8 *srcline, *srccol;
   756 
   757 	srcline = (Uint8 *)gl_shadow;
   758 	srcpitch = surface->w *3;
   759 	dstline = surface->pixels;
   760 	dstpitch = surface->pitch;
   761 
   762 	for (y=0; y<surface->h; y++) {
   763 		srccol = srcline;
   764 		dstcol = dstline;
   765 
   766 		for (x=0; x<surface->w; x++) {
   767 			*dstcol++ = srccol[2];
   768 			*dstcol++ = srccol[1];
   769 			*dstcol++ = srccol[0];
   770 			srccol += 3;
   771 		}
   772 
   773 		srcline += srcpitch;
   774 		dstline += dstpitch;
   775 	}
   776 }
   777 
   778 static void CopyShadowRGBToARGB(_THIS, SDL_Surface *surface)
   779 {
   780 	int x,y, srcpitch, dstpitch;
   781 	Uint32 *dstline, *dstcol;
   782 	Uint8 *srcline, *srccol;
   783 
   784 	srcline = (Uint8 *)gl_shadow;
   785 	srcpitch = surface->w *3;
   786 	dstline = surface->pixels;
   787 	dstpitch = surface->pitch >>2;
   788 
   789 	for (y=0; y<surface->h; y++) {
   790 		srccol = srcline;
   791 		dstcol = dstline;
   792 
   793 		for (x=0; x<surface->w; x++) {
   794 			Uint32	dstcolor;
   795 
   796 			dstcolor = (*srccol++)<<16;
   797 			dstcolor |= (*srccol++)<<8;
   798 			dstcolor |= *srccol++;
   799 
   800 			*dstcol++ = dstcolor;
   801 		}
   802 
   803 		srcline += srcpitch;
   804 		dstline += dstpitch;
   805 	}
   806 }
   807 
   808 static void CopyShadowRGBToABGR(_THIS, SDL_Surface *surface)
   809 {
   810 	int x,y, srcpitch, dstpitch;
   811 	Uint32 *dstline, *dstcol;
   812 	Uint8 *srcline, *srccol;
   813 
   814 	srcline = (Uint8 *)gl_shadow;
   815 	srcpitch = surface->w *3;
   816 	dstline = surface->pixels;
   817 	dstpitch = surface->pitch >>2;
   818 
   819 	for (y=0; y<surface->h; y++) {
   820 		srccol = srcline;
   821 		dstcol = dstline;
   822 
   823 		for (x=0; x<surface->w; x++) {
   824 			Uint32	dstcolor;
   825 
   826 			dstcolor = *srccol++;
   827 			dstcolor |= (*srccol++)<<8;
   828 			dstcolor |= (*srccol++)<<16;
   829 
   830 			*dstcol++ = dstcolor;
   831 		}
   832 
   833 		srcline += srcpitch;
   834 		dstline += dstpitch;
   835 	}
   836 }
   837 
   838 static void CopyShadowRGBToBGRA(_THIS, SDL_Surface *surface)
   839 {
   840 	int x,y, srcpitch, dstpitch;
   841 	Uint32 *dstline, *dstcol;
   842 	Uint8 *srcline, *srccol;
   843 
   844 	srcline = (Uint8 *)gl_shadow;
   845 	srcpitch = surface->w *3;
   846 	dstline = surface->pixels;
   847 	dstpitch = surface->pitch >>2;
   848 
   849 	for (y=0; y<surface->h; y++) {
   850 		srccol = srcline;
   851 		dstcol = dstline;
   852 
   853 		for (x=0; x<surface->w; x++) {
   854 			Uint32	dstcolor;
   855 
   856 			dstcolor = (*srccol++)<<8;
   857 			dstcolor |= (*srccol++)<<16;
   858 			dstcolor |= (*srccol++)<<24;
   859 
   860 			*dstcol++ = dstcolor;
   861 		}
   862 
   863 		srcline += srcpitch;
   864 		dstline += dstpitch;
   865 	}
   866 }
   867 
   868 static void CopyShadowRGBToRGBA(_THIS, SDL_Surface *surface)
   869 {
   870 	int x,y, srcpitch, dstpitch;
   871 	Uint32 *dstline, *dstcol;
   872 	Uint8 *srcline, *srccol;
   873 
   874 	srcline = (Uint8 *)gl_shadow;
   875 	srcpitch = surface->w *3;
   876 	dstline = surface->pixels;
   877 	dstpitch = surface->pitch >>2;
   878 
   879 	for (y=0; y<surface->h; y++) {
   880 		srccol = srcline;
   881 		dstcol = dstline;
   882 
   883 		for (x=0; x<surface->w; x++) {
   884 			Uint32	dstcolor;
   885 
   886 			dstcolor = (*srccol++)<<24;
   887 			dstcolor |= (*srccol++)<<16;
   888 			dstcolor |= (*srccol++)<<8;
   889 
   890 			*dstcol++ = dstcolor;
   891 		}
   892 
   893 		srcline += srcpitch;
   894 		dstline += dstpitch;
   895 	}
   896 }
   897 
   898 static void CopyShadow8888To555(_THIS, SDL_Surface *surface)
   899 {
   900 	int x,y, srcpitch, dstpitch;
   901 	Uint16 *dstline, *dstcol;
   902 	Uint32 *srcline, *srccol;
   903 
   904 	srcline = (Uint32 *)gl_shadow;
   905 	srcpitch = surface->w;
   906 	dstline = surface->pixels;
   907 	dstpitch = surface->pitch >>1;
   908 
   909 	for (y=0; y<surface->h; y++) {
   910 		srccol = srcline;
   911 		dstcol = dstline;
   912 		for (x=0; x<surface->w; x++) {
   913 			Uint32 srccolor;
   914 			Uint16 dstcolor;
   915 			
   916 			srccolor = *srccol++;
   917 			dstcolor = (srccolor>>9) & (31<<10);
   918 			dstcolor |= (srccolor>>6) & (31<<5);
   919 			dstcolor |= (srccolor>>3) & 31;
   920 			*dstcol++ = dstcolor;
   921 		}
   922 
   923 		srcline += srcpitch;
   924 		dstline += dstpitch;
   925 	}
   926 }
   927 
   928 static void CopyShadow8888To565(_THIS, SDL_Surface *surface)
   929 {
   930 	int x,y, srcpitch, dstpitch;
   931 	Uint16 *dstline, *dstcol;
   932 	Uint32 *srcline, *srccol;
   933 
   934 	srcline = (Uint32 *)gl_shadow;
   935 	srcpitch = surface->w;
   936 	dstline = surface->pixels;
   937 	dstpitch = surface->pitch >>1;
   938 
   939 	for (y=0; y<surface->h; y++) {
   940 		srccol = srcline;
   941 		dstcol = dstline;
   942 
   943 		for (x=0; x<surface->w; x++) {
   944 			Uint32 srccolor;
   945 			Uint16 dstcolor;
   946 			
   947 			srccolor = *srccol++;
   948 			dstcolor = (srccolor>>8) & (31<<11);
   949 			dstcolor |= (srccolor>>5) & (63<<5);
   950 			dstcolor |= (srccolor>>3) & 31;
   951 			*dstcol++ = dstcolor;
   952 		}
   953 
   954 		srcline += srcpitch;
   955 		dstline += dstpitch;
   956 	}
   957 }
   958 
   959 /*--- Conversions routines in the screen ---*/
   960 
   961 static void ConvertNull(_THIS, SDL_Surface *surface)
   962 {
   963 }
   964 
   965 static void Convert565To555be(_THIS, SDL_Surface *surface)
   966 {
   967 	int x,y, pitch;
   968 	unsigned short *line, *pixel;
   969 
   970 	line = surface->pixels;
   971 	pitch = surface->pitch >> 1;
   972 	for (y=0; y<surface->h; y++) {
   973 		pixel = line;
   974 		for (x=0; x<surface->w; x++) {
   975 			unsigned short color = *pixel;
   976 
   977 			*pixel++ = (color & 0x1f)|((color>>1) & 0xffe0);
   978 		}
   979 
   980 		line += pitch;
   981 	}
   982 }
   983 
   984 static void Convert565To555le(_THIS, SDL_Surface *surface)
   985 {
   986 	int x,y, pitch;
   987 	unsigned short *line, *pixel;
   988 
   989 	line = surface->pixels;
   990 	pitch = surface->pitch >>1;
   991 	for (y=0; y<surface->h; y++) {
   992 		pixel = line;
   993 		for (x=0; x<surface->w; x++) {
   994 			unsigned short color = *pixel;
   995 
   996 			color = (color & 0x1f)|((color>>1) & 0xffe0);
   997 			*pixel++ = SDL_Swap16(color);
   998 		}
   999 
  1000 		line += pitch;
  1001 	}
  1002 }
  1003 
  1004 static void Convert565le(_THIS, SDL_Surface *surface)
  1005 {
  1006 	int x,y, pitch;
  1007 	unsigned short *line, *pixel;
  1008 
  1009 	line = surface->pixels;
  1010 	pitch = surface->pitch >>1;
  1011 	for (y=0; y<surface->h; y++) {
  1012 		pixel = line;
  1013 		for (x=0; x<surface->w; x++) {
  1014 			unsigned short color = *pixel;
  1015 
  1016 			*pixel++ = SDL_Swap16(color);
  1017 		}
  1018 
  1019 		line += pitch;
  1020 	}
  1021 }
  1022 
  1023 static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface)
  1024 {
  1025 	int x,y, pitch;
  1026 	unsigned long *line, *pixel;
  1027 
  1028 	line = surface->pixels;
  1029 	pitch = surface->pitch >>2;
  1030 	for (y=0; y<surface->h; y++) {
  1031 		pixel = line;
  1032 		for (x=0; x<surface->w; x++) {
  1033 			unsigned long color = *pixel;
  1034 
  1035 			*pixel++ = (color<<24)|(color>>8);
  1036 		}
  1037 
  1038 		line += pitch;
  1039 	}
  1040 }
  1041 
  1042 #endif /* HAVE_OPENGL */