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