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