src/video/ataricommon/SDL_atarigl.c
author Patrice Mandin
Thu, 25 Nov 2004 15:47:49 +0000
changeset 989 475166d13b44
child 991 12b13601a544
permissions -rw-r--r--
Factorize OSMesa OpenGL code for Atari drivers
     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 #ifdef HAVE_OPENGL
    28 #include <GL/osmesa.h>
    29 #endif
    30 
    31 #include "SDL_video.h"
    32 #include "SDL_error.h"
    33 #include "SDL_endian.h"
    34 #include "SDL_atarigl_c.h"
    35 
    36 /*--- Variables ---*/
    37 
    38 /*--- Functions prototypes ---*/
    39 
    40 static void ConvertNull(SDL_Surface *surface);
    41 static void Convert565To555be(SDL_Surface *surface);
    42 static void Convert565To555le(SDL_Surface *surface);
    43 static void Convert565le(SDL_Surface *surface);
    44 static void ConvertBGRAToABGR(SDL_Surface *surface);
    45 
    46 /*--- Public functions ---*/
    47 
    48 int SDL_AtariGL_Init(_THIS, SDL_Surface *current)
    49 {
    50 #ifdef HAVE_OPENGL
    51 	GLenum osmesa_format;
    52 	SDL_PixelFormat *pixel_format;
    53 	Uint32	redmask;
    54 
    55 	SDL_AtariGL_Quit(this);	/* Destroy previous context if exist */
    56 
    57 	/* Init OpenGL context using OSMesa */
    58 	gl_convert = ConvertNull;
    59 
    60 	pixel_format = current->format;
    61 	redmask = pixel_format->Rmask;
    62 	switch (pixel_format->BitsPerPixel) {
    63 		case 15:
    64 			/* 1555, big and little endian, unsupported */
    65 			osmesa_format = OSMESA_RGB_565;
    66 			if (redmask == 31<<10) {
    67 				gl_convert = Convert565To555be;
    68 			} else {
    69 				gl_convert = Convert565To555le;
    70 			}
    71 			break;
    72 		case 16:
    73 			if (redmask == 31<<11) {
    74 				osmesa_format = OSMESA_RGB_565;
    75 			} else {
    76 				/* 565, little endian, unsupported */
    77 				osmesa_format = OSMESA_RGB_565;
    78 				gl_convert = Convert565le;
    79 			}
    80 			break;
    81 		case 24:
    82 			if (redmask == 255<<16) {
    83 				osmesa_format = OSMESA_RGB;
    84 			} else {
    85 				osmesa_format = OSMESA_BGR;
    86 			}
    87 			break;
    88 		case 32:
    89 			if (redmask == 255<<16) {
    90 				osmesa_format = OSMESA_ARGB;
    91 			} else if (redmask == 255<<8) {
    92 				osmesa_format = OSMESA_BGRA;
    93 			} else if (redmask == 255<<24) {
    94 				osmesa_format = OSMESA_RGBA;
    95 			} else {
    96 				/* ABGR format unsupported */
    97 				osmesa_format = OSMESA_BGRA;
    98 				gl_convert = ConvertBGRAToABGR;
    99 			}
   100 			break;
   101 		default:
   102 			osmesa_format = OSMESA_COLOR_INDEX;
   103 			break;
   104 	}
   105 
   106 	gl_ctx = OSMesaCreateContextExt( osmesa_format, this->gl_config.depth_size,
   107 		this->gl_config.stencil_size, this->gl_config.accum_red_size +
   108 		this->gl_config.accum_green_size + this->gl_config.accum_blue_size +
   109 		this->gl_config.accum_alpha_size, NULL );
   110 
   111 	gl_active = (gl_ctx != NULL);
   112 	return (gl_active);
   113 #else
   114 	return 0;
   115 #endif
   116 }
   117 
   118 void SDL_AtariGL_Quit(_THIS)
   119 {
   120 #ifdef HAVE_OPENGL
   121 	/* Shutdown OpenGL context */
   122 	if (gl_ctx) {
   123 		OSMesaDestroyContext(gl_ctx);
   124 		gl_ctx = NULL;
   125 	}
   126 #endif
   127 	gl_active = 0;
   128 }
   129 
   130 int SDL_AtariGL_LoadLibrary(_THIS, const char *path)
   131 {
   132 #ifdef HAVE_OPENGL
   133 	/* Library is always opened */
   134 	this->gl_config.driver_loaded = 1;
   135 #endif
   136 	return 0;
   137 }
   138 
   139 void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc)
   140 {
   141 	void *func = NULL;
   142 #ifdef HAVE_OPENGL
   143 	if (gl_ctx != NULL) {
   144 		func = OSMesaGetProcAddress(proc);
   145 	}
   146 #endif
   147 	return func;
   148 }
   149 
   150 int SDL_AtariGL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
   151 {
   152 #ifdef HAVE_OPENGL
   153 	GLenum mesa_attrib;
   154 	SDL_Surface *surface;
   155 
   156 	if (gl_ctx == NULL) {
   157 		return -1;
   158 	}
   159 
   160 	switch(attrib) {
   161 		case SDL_GL_RED_SIZE:
   162 			mesa_attrib = GL_RED_BITS;
   163 			break;
   164 		case SDL_GL_GREEN_SIZE:
   165 			mesa_attrib = GL_GREEN_BITS;
   166 			break;
   167 		case SDL_GL_BLUE_SIZE:
   168 			mesa_attrib = GL_BLUE_BITS;
   169 			break;
   170 		case SDL_GL_ALPHA_SIZE:
   171 			mesa_attrib = GL_ALPHA_BITS;
   172 			break;
   173 		case SDL_GL_DOUBLEBUFFER:
   174 			surface = this->screen;
   175 			*value = ((surface->flags & SDL_DOUBLEBUF)==SDL_DOUBLEBUF);
   176 			return 0;
   177 		case SDL_GL_DEPTH_SIZE:
   178 			mesa_attrib = GL_DEPTH_BITS;
   179 			break;
   180 		case SDL_GL_STENCIL_SIZE:
   181 			mesa_attrib = GL_STENCIL_BITS;
   182 			break;
   183 		case SDL_GL_ACCUM_RED_SIZE:
   184 			mesa_attrib = GL_ACCUM_RED_BITS;
   185 			break;
   186 		case SDL_GL_ACCUM_GREEN_SIZE:
   187 			mesa_attrib = GL_ACCUM_GREEN_BITS;
   188 			break;
   189 		case SDL_GL_ACCUM_BLUE_SIZE:
   190 			mesa_attrib = GL_ACCUM_BLUE_BITS;
   191 			break;
   192 		case SDL_GL_ACCUM_ALPHA_SIZE:
   193 			mesa_attrib = GL_ACCUM_ALPHA_BITS;
   194 			break;
   195 		default :
   196 			return -1;
   197 	}
   198 
   199 	glGetIntegerv(mesa_attrib, value);
   200 	return 0;
   201 #else
   202 	return -1;
   203 #endif
   204 }
   205 
   206 int SDL_AtariGL_MakeCurrent(_THIS)
   207 {
   208 #ifdef HAVE_OPENGL
   209 	SDL_Surface *surface;
   210 	GLenum type;
   211 
   212 	if (gl_ctx == NULL) {
   213 		SDL_SetError("Invalid OpenGL context");
   214 		return -1;
   215 	}
   216 
   217 	surface = this->screen;
   218 	
   219 	if ((surface->format->BitsPerPixel == 15) || (surface->format->BitsPerPixel == 16)) {
   220 		type = GL_UNSIGNED_SHORT_5_6_5;
   221 	} else {
   222 		type = GL_UNSIGNED_BYTE;
   223 	}
   224 
   225 	if (!OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h)) {
   226 		SDL_SetError("Can not make OpenGL context current");
   227 		return -1;
   228 	}
   229 
   230 	/* OSMesa draws upside down */
   231 	OSMesaPixelStore(OSMESA_Y_UP, 0);
   232 
   233 	return 0;
   234 #else
   235 	return -1;
   236 #endif
   237 }
   238 
   239 void SDL_AtariGL_SwapBuffers(_THIS)
   240 {
   241 #ifdef HAVE_OPENGL
   242 	if (gl_ctx == NULL) {
   243 		return;
   244 	}
   245 
   246 	gl_convert(this->screen);
   247 #endif
   248 }
   249 
   250 /*--- Private functions ---*/
   251 
   252 static void ConvertNull(SDL_Surface *surface)
   253 {
   254 }
   255 
   256 static void Convert565To555be(SDL_Surface *surface)
   257 {
   258 	int x,y, pitch;
   259 	unsigned short *line, *pixel;
   260 
   261 	line = surface->pixels;
   262 	pitch = surface->pitch >> 1;
   263 	for (y=0; y<surface->h; y++) {
   264 		pixel = line;
   265 		for (x=0; x<surface->w; x++) {
   266 			unsigned short color = *pixel;
   267 
   268 			*pixel++ = (color & 0x1f)|((color>>1) & 0xffe0);
   269 		}
   270 
   271 		line += pitch;
   272 	}
   273 }
   274 
   275 static void Convert565To555le(SDL_Surface *surface)
   276 {
   277 	int x,y, pitch;
   278 	unsigned short *line, *pixel;
   279 
   280 	line = surface->pixels;
   281 	pitch = surface->pitch >>1;
   282 	for (y=0; y<surface->h; y++) {
   283 		pixel = line;
   284 		for (x=0; x<surface->w; x++) {
   285 			unsigned short color = *pixel;
   286 
   287 			color = (color & 0x1f)|((color>>1) & 0xffe0);
   288 			*pixel++ = SDL_Swap16(color);
   289 		}
   290 
   291 		line += pitch;
   292 	}
   293 }
   294 
   295 static void Convert565le(SDL_Surface *surface)
   296 {
   297 	int x,y, pitch;
   298 	unsigned short *line, *pixel;
   299 
   300 	line = surface->pixels;
   301 	pitch = surface->pitch >>1;
   302 	for (y=0; y<surface->h; y++) {
   303 		pixel = line;
   304 		for (x=0; x<surface->w; x++) {
   305 			unsigned short color = *pixel;
   306 
   307 			*pixel++ = SDL_Swap16(color);
   308 		}
   309 
   310 		line += pitch;
   311 	}
   312 }
   313 
   314 static void ConvertBGRAToABGR(SDL_Surface *surface)
   315 {
   316 	int x,y, pitch;
   317 	unsigned long *line, *pixel;
   318 
   319 	line = surface->pixels;
   320 	pitch = surface->pitch >>2;
   321 	for (y=0; y<surface->h; y++) {
   322 		pixel = line;
   323 		for (x=0; x<surface->w; x++) {
   324 			unsigned long color = *pixel;
   325 
   326 			*pixel++ = (color<<24)|(color>>8);
   327 		}
   328 
   329 		line += pitch;
   330 	}
   331 }