Mercurial > sdl-ios-xcode
diff src/video/ataricommon/SDL_atarigl.c @ 991:12b13601a544
Final touches to OSMesa OpenGL support on Atari, using loadable libraries. Hope SDL 1.2.8 is out soon.
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Fri, 26 Nov 2004 16:16:50 +0000 |
parents | 475166d13b44 |
children | 0324ce32b2d9 |
line wrap: on
line diff
--- a/src/video/ataricommon/SDL_atarigl.c Fri Nov 26 16:13:24 2004 +0000 +++ b/src/video/ataricommon/SDL_atarigl.c Fri Nov 26 16:16:50 2004 +0000 @@ -24,125 +24,198 @@ /*--- Includes ---*/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> #ifdef HAVE_OPENGL #include <GL/osmesa.h> #endif +#include <mint/osbind.h> + #include "SDL_video.h" #include "SDL_error.h" #include "SDL_endian.h" #include "SDL_atarigl_c.h" +#ifdef ENABLE_OSMESA_SHARED +#include "SDL_loadso.h" +#endif -/*--- Variables ---*/ +/*--- Defines ---*/ + +#define PATH_OSMESA_LDG "osmesa.ldg" +#define PATH_MESAGL_LDG "mesa_gl.ldg" +#define PATH_TINYGL_LDG "tiny_gl.ldg" /*--- Functions prototypes ---*/ -static void ConvertNull(SDL_Surface *surface); -static void Convert565To555be(SDL_Surface *surface); -static void Convert565To555le(SDL_Surface *surface); -static void Convert565le(SDL_Surface *surface); -static void ConvertBGRAToABGR(SDL_Surface *surface); +static void SDL_AtariGL_UnloadLibrary(_THIS); + +static void CopyShadowNull(_THIS, SDL_Surface *surface); +static void CopyShadowDirect(_THIS, SDL_Surface *surface); +static void CopyShadow8888To555(_THIS, SDL_Surface *surface); +static void CopyShadow8888To565(_THIS, SDL_Surface *surface); + +static void ConvertNull(_THIS, SDL_Surface *surface); +static void Convert565To555be(_THIS, SDL_Surface *surface); +static void Convert565To555le(_THIS, SDL_Surface *surface); +static void Convert565le(_THIS, SDL_Surface *surface); +static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface); + +static int InitNew(_THIS, SDL_Surface *current); +static int InitOld(_THIS, SDL_Surface *current); /*--- Public functions ---*/ int SDL_AtariGL_Init(_THIS, SDL_Surface *current) { #ifdef HAVE_OPENGL - GLenum osmesa_format; - SDL_PixelFormat *pixel_format; - Uint32 redmask; - - SDL_AtariGL_Quit(this); /* Destroy previous context if exist */ - - /* Init OpenGL context using OSMesa */ - gl_convert = ConvertNull; + if (gl_oldmesa) { + gl_active = InitOld(this, current); + } else { + gl_active = InitNew(this, current); + } +#endif - pixel_format = current->format; - redmask = pixel_format->Rmask; - switch (pixel_format->BitsPerPixel) { - case 15: - /* 1555, big and little endian, unsupported */ - osmesa_format = OSMESA_RGB_565; - if (redmask == 31<<10) { - gl_convert = Convert565To555be; - } else { - gl_convert = Convert565To555le; - } - break; - case 16: - if (redmask == 31<<11) { - osmesa_format = OSMESA_RGB_565; - } else { - /* 565, little endian, unsupported */ - osmesa_format = OSMESA_RGB_565; - gl_convert = Convert565le; - } - break; - case 24: - if (redmask == 255<<16) { - osmesa_format = OSMESA_RGB; - } else { - osmesa_format = OSMESA_BGR; - } - break; - case 32: - if (redmask == 255<<16) { - osmesa_format = OSMESA_ARGB; - } else if (redmask == 255<<8) { - osmesa_format = OSMESA_BGRA; - } else if (redmask == 255<<24) { - osmesa_format = OSMESA_RGBA; - } else { - /* ABGR format unsupported */ - osmesa_format = OSMESA_BGRA; - gl_convert = ConvertBGRAToABGR; - } - break; - default: - osmesa_format = OSMESA_COLOR_INDEX; - break; - } - - gl_ctx = OSMesaCreateContextExt( osmesa_format, this->gl_config.depth_size, - this->gl_config.stencil_size, this->gl_config.accum_red_size + - this->gl_config.accum_green_size + this->gl_config.accum_blue_size + - this->gl_config.accum_alpha_size, NULL ); - - gl_active = (gl_ctx != NULL); return (gl_active); -#else - return 0; -#endif } void SDL_AtariGL_Quit(_THIS) { #ifdef HAVE_OPENGL - /* Shutdown OpenGL context */ - if (gl_ctx) { - OSMesaDestroyContext(gl_ctx); - gl_ctx = NULL; + if (!gl_active) { + return; } -#endif + + if (gl_oldmesa) { + /* Old mesa implementations */ + if (this->gl_data->OSMesaDestroyLDG) { + this->gl_data->OSMesaDestroyLDG(); + } + if (gl_shadow) { + Mfree(gl_shadow); + gl_shadow = NULL; + } + } else { + /* New mesa implementation */ + if (gl_ctx) { + if (this->gl_data->OSMesaDestroyContext) { + this->gl_data->OSMesaDestroyContext(gl_ctx); + } + gl_ctx = NULL; + } + } + + SDL_AtariGL_UnloadLibrary(this); + +#endif /* HAVE_OPENGL */ gl_active = 0; } int SDL_AtariGL_LoadLibrary(_THIS, const char *path) { #ifdef HAVE_OPENGL - /* Library is always opened */ + +#ifdef ENABLE_OSMESA_SHARED + void *handle; + + if (gl_active) { + SDL_SetError("OpenGL context already created"); + return -1; + } + + /* Unload previous driver */ + SDL_AtariGL_UnloadLibrary(this); + + /* Load library given by path */ + handle = SDL_LoadObject(path); + if (handle == NULL) { + /* Try to load another one */ + path = getenv("SDL_VIDEO_GL_DRIVER"); + if ( path != NULL ) { + handle = SDL_LoadObject(path); + } + + /* If it does not work, try some other */ + if (handle == NULL) { + path = PATH_OSMESA_LDG; + handle = SDL_LoadObject(path); + } + + if (handle == NULL) { + path = PATH_MESAGL_LDG; + handle = SDL_LoadObject(path); + } + + if (handle == NULL) { + path = PATH_TINYGL_LDG; + handle = SDL_LoadObject(path); + } + } + + if (handle == NULL) { + SDL_SetError("Could not load OpenGL library"); + return -1; + } + + /* Load functions pointers (osmesa.ldg) */ + this->gl_data->OSMesaCreateContextExt = SDL_LoadFunction(handle, "OSMesaCreateContextExt"); + this->gl_data->OSMesaDestroyContext = SDL_LoadFunction(handle, "OSMesaDestroyContext"); + this->gl_data->OSMesaMakeCurrent = SDL_LoadFunction(handle, "OSMesaMakeCurrent"); + this->gl_data->OSMesaPixelStore = SDL_LoadFunction(handle, "OSMesaPixelStore"); + this->gl_data->OSMesaGetProcAddress = SDL_LoadFunction(handle, "OSMesaGetProcAddress"); + this->gl_data->glGetIntegerv = SDL_LoadFunction(handle, "glGetIntegerv"); + + /* Load old functions pointers (mesa_gl.ldg, tiny_gl.ldg) */ + this->gl_data->OSMesaCreateLDG = SDL_LoadFunction(handle, "OSMesaCreateLDG"); + this->gl_data->OSMesaDestroyLDG = SDL_LoadFunction(handle, "OSMesaDestroyLDG"); + + gl_oldmesa = 0; + + if ( (this->gl_data->OSMesaCreateContextExt == NULL) || + (this->gl_data->OSMesaDestroyContext == NULL) || + (this->gl_data->OSMesaMakeCurrent == NULL) || + (this->gl_data->OSMesaPixelStore == NULL) || + (this->gl_data->glGetIntegerv == NULL) || + (this->gl_data->OSMesaGetProcAddress == NULL)) { + /* Hum, maybe old library ? */ + if ( (this->gl_data->OSMesaCreateLDG == NULL) || + (this->gl_data->OSMesaDestroyLDG == NULL)) { + SDL_SetError("Could not retrieve OpenGL functions"); + return -1; + } else { + gl_oldmesa = 1; + } + } + + this->gl_config.dll_handle = handle; + if ( path ) { + strncpy(this->gl_config.driver_path, path, + sizeof(this->gl_config.driver_path)-1); + } else { + strcpy(this->gl_config.driver_path, ""); + } + +#endif this->gl_config.driver_loaded = 1; + + return 0; +#else + return -1; #endif - return 0; } void *SDL_AtariGL_GetProcAddress(_THIS, const char *proc) { void *func = NULL; #ifdef HAVE_OPENGL - if (gl_ctx != NULL) { - func = OSMesaGetProcAddress(proc); + + if (this->gl_config.dll_handle) { + func = SDL_LoadFunction(this->gl_config.dll_handle, (void *)proc); + } else if (this->gl_data->OSMesaGetProcAddress) { + func = this->gl_data->OSMesaGetProcAddress(proc); } + #endif return func; } @@ -153,7 +226,13 @@ GLenum mesa_attrib; SDL_Surface *surface; - if (gl_ctx == NULL) { + if (this->gl_config.dll_handle) { + if (this->gl_data->glGetIntegerv == NULL) { + return -1; + } + } + + if (!gl_active) { return -1; } @@ -196,7 +275,7 @@ return -1; } - glGetIntegerv(mesa_attrib, value); + this->gl_data->glGetIntegerv(mesa_attrib, value); return 0; #else return -1; @@ -209,7 +288,18 @@ SDL_Surface *surface; GLenum type; - if (gl_ctx == NULL) { + if (gl_oldmesa && gl_active) { + return 0; + } + + if (this->gl_config.dll_handle) { + if ((this->gl_data->OSMesaMakeCurrent == NULL) || + (this->gl_data->OSMesaPixelStore == NULL)) { + return -1; + } + } + + if (!gl_active) { SDL_SetError("Invalid OpenGL context"); return -1; } @@ -222,13 +312,13 @@ type = GL_UNSIGNED_BYTE; } - if (!OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h)) { + if (!(this->gl_data->OSMesaMakeCurrent(gl_ctx, surface->pixels, type, surface->w, surface->h))) { SDL_SetError("Can not make OpenGL context current"); return -1; } /* OSMesa draws upside down */ - OSMesaPixelStore(OSMESA_Y_UP, 0); + this->gl_data->OSMesaPixelStore(OSMESA_Y_UP, 0); return 0; #else @@ -239,21 +329,296 @@ void SDL_AtariGL_SwapBuffers(_THIS) { #ifdef HAVE_OPENGL - if (gl_ctx == NULL) { - return; + if (gl_active) { + gl_copyshadow(this, this->screen); + gl_convert(this, this->screen); } +#endif +} - gl_convert(this->screen); +void SDL_AtariGL_InitPointers(_THIS) +{ +#if defined(HAVE_OPENGL) + this->gl_data->OSMesaCreateContextExt = OSMesaCreateContextExt; + this->gl_data->OSMesaDestroyContext = OSMesaDestroyContext; + this->gl_data->OSMesaMakeCurrent = OSMesaMakeCurrent; + this->gl_data->OSMesaPixelStore = OSMesaPixelStore; + this->gl_data->OSMesaGetProcAddress = OSMesaGetProcAddress; + this->gl_data->glGetIntegerv = glGetIntegerv; #endif } /*--- Private functions ---*/ -static void ConvertNull(SDL_Surface *surface) +static void SDL_AtariGL_UnloadLibrary(_THIS) +{ +#if defined(HAVE_OPENGL) + if (this->gl_config.dll_handle) { + SDL_UnloadObject(this->gl_config.dll_handle); + this->gl_config.dll_handle = NULL; + + /* Restore pointers to static library */ + this->gl_data->OSMesaCreateContextExt = OSMesaCreateContextExt; + this->gl_data->OSMesaDestroyContext = OSMesaDestroyContext; + this->gl_data->OSMesaMakeCurrent = OSMesaMakeCurrent; + this->gl_data->OSMesaPixelStore = OSMesaPixelStore; + this->gl_data->OSMesaGetProcAddress = OSMesaGetProcAddress; + this->gl_data->glGetIntegerv = glGetIntegerv; + + this->gl_data->OSMesaCreateLDG = NULL; + this->gl_data->OSMesaDestroyLDG = NULL; + } +#endif +} + +/*--- Creation of an OpenGL context using new/old functions ---*/ + +static int InitNew(_THIS, SDL_Surface *current) +{ + GLenum osmesa_format; + SDL_PixelFormat *pixel_format; + Uint32 redmask; + + if (this->gl_config.dll_handle) { + if (this->gl_data->OSMesaCreateContextExt == NULL) { + return 0; + } + } + + /* Init OpenGL context using OSMesa */ + gl_convert = ConvertNull; + gl_copyshadow = CopyShadowNull; + + pixel_format = current->format; + redmask = pixel_format->Rmask; + switch (pixel_format->BitsPerPixel) { + case 15: + /* 1555, big and little endian, unsupported */ + gl_pixelsize = 2; + osmesa_format = OSMESA_RGB_565; + if (redmask == 31<<10) { + gl_convert = Convert565To555be; + } else { + gl_convert = Convert565To555le; + } + break; + case 16: + gl_pixelsize = 2; + if (redmask == 31<<11) { + osmesa_format = OSMESA_RGB_565; + } else { + /* 565, little endian, unsupported */ + osmesa_format = OSMESA_RGB_565; + gl_convert = Convert565le; + } + break; + case 24: + gl_pixelsize = 3; + if (redmask == 255<<16) { + osmesa_format = OSMESA_RGB; + } else { + osmesa_format = OSMESA_BGR; + } + break; + case 32: + gl_pixelsize = 4; + if (redmask == 255<<16) { + osmesa_format = OSMESA_ARGB; + } else if (redmask == 255<<8) { + osmesa_format = OSMESA_BGRA; + } else if (redmask == 255<<24) { + osmesa_format = OSMESA_RGBA; + } else { + /* ABGR format unsupported */ + osmesa_format = OSMESA_BGRA; + gl_convert = ConvertBGRAToABGR; + } + break; + default: + gl_pixelsize = 1; + osmesa_format = OSMESA_COLOR_INDEX; + break; + } + + gl_ctx = this->gl_data->OSMesaCreateContextExt( + osmesa_format, this->gl_config.depth_size, + this->gl_config.stencil_size, this->gl_config.accum_red_size + + this->gl_config.accum_green_size + this->gl_config.accum_blue_size + + this->gl_config.accum_alpha_size, NULL ); + + return (gl_ctx != NULL); +} + +static int InitOld(_THIS, SDL_Surface *current) +{ + GLenum osmesa_format; + SDL_PixelFormat *pixel_format; + Uint32 redmask; + + if (this->gl_config.dll_handle) { + if (this->gl_data->OSMesaCreateLDG == NULL) { + return 0; + } + } + + /* Init OpenGL context using OSMesa */ + gl_convert = ConvertNull; + gl_copyshadow = CopyShadowNull; + + pixel_format = current->format; + redmask = pixel_format->Rmask; + switch (pixel_format->BitsPerPixel) { + case 15: + /* 15 bits unsupported */ + gl_pixelsize = 2; + osmesa_format = OSMESA_ARGB; + if (redmask == 31<<10) { + gl_copyshadow = CopyShadow8888To555; + } else { + gl_copyshadow = CopyShadow8888To565; + gl_convert = Convert565To555le; + } + break; + case 16: + /* 16 bits unsupported */ + gl_pixelsize = 2; + osmesa_format = OSMESA_ARGB; + gl_copyshadow = CopyShadow8888To565; + if (redmask != 31<<11) { + /* 565, little endian, unsupported */ + gl_convert = Convert565le; + } + break; + case 24: + gl_pixelsize = 3; + gl_copyshadow = CopyShadowDirect; + if (redmask == 255<<16) { + osmesa_format = OSMESA_RGB; + } else { + osmesa_format = OSMESA_BGR; + } + break; + case 32: + gl_pixelsize = 4; + gl_copyshadow = CopyShadowDirect; + if (redmask == 255<<16) { + osmesa_format = OSMESA_ARGB; + } else if (redmask == 255<<8) { + osmesa_format = OSMESA_BGRA; + } else if (redmask == 255<<24) { + osmesa_format = OSMESA_RGBA; + } else { + /* ABGR format unsupported */ + osmesa_format = OSMESA_BGRA; + gl_convert = ConvertBGRAToABGR; + } + break; + default: + gl_pixelsize = 1; + gl_copyshadow = CopyShadowDirect; + osmesa_format = OSMESA_COLOR_INDEX; + break; + } + + gl_shadow = this->gl_data->OSMesaCreateLDG( + osmesa_format, GL_UNSIGNED_BYTE, current->w, current->h + ); + + return (gl_shadow != NULL); +} + +/*--- Conversions routines from shadow buffer to the screen ---*/ + +static void CopyShadowNull(_THIS, SDL_Surface *surface) { } -static void Convert565To555be(SDL_Surface *surface) +static void CopyShadowDirect(_THIS, SDL_Surface *surface) +{ + int y, srcpitch, dstpitch; + Uint8 *srcline, *dstline; + + srcline = gl_shadow; + srcpitch = surface->w * gl_pixelsize; + dstline = surface->pixels; + dstpitch = surface->pitch; + + for (y=0; y<surface->h; y++) { + memcpy(dstline, srcline, srcpitch); + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadow8888To555(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint32 *srcline, *srccol; + + srcline = (Uint32 *)gl_shadow; + srcpitch = surface->w; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + for (x=0; x<surface->w; x++) { + Uint32 srccolor; + Uint16 dstcolor; + + srccolor = *srccol++; + dstcolor = (srccolor>>9) & (31<<10); + dstcolor |= (srccolor>>6) & (31<<5); + dstcolor |= (srccolor>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +static void CopyShadow8888To565(_THIS, SDL_Surface *surface) +{ + int x,y, srcpitch, dstpitch; + Uint16 *dstline, *dstcol; + Uint32 *srcline, *srccol; + + srcline = (Uint32 *)gl_shadow; + srcpitch = surface->w; + dstline = surface->pixels; + dstpitch = surface->pitch >>1; + + for (y=0; y<surface->h; y++) { + srccol = srcline; + dstcol = dstline; + + for (x=0; x<surface->w; x++) { + Uint32 srccolor; + Uint16 dstcolor; + + srccolor = *srccol++; + dstcolor = (srccolor>>8) & (31<<11); + dstcolor |= (srccolor>>5) & (63<<5); + dstcolor |= (srccolor>>3) & 31; + *dstcol++ = dstcolor; + } + + srcline += srcpitch; + dstline += dstpitch; + } +} + +/*--- Conversions routines in the screen ---*/ + +static void ConvertNull(_THIS, SDL_Surface *surface) +{ +} + +static void Convert565To555be(_THIS, SDL_Surface *surface) { int x,y, pitch; unsigned short *line, *pixel; @@ -272,7 +637,7 @@ } } -static void Convert565To555le(SDL_Surface *surface) +static void Convert565To555le(_THIS, SDL_Surface *surface) { int x,y, pitch; unsigned short *line, *pixel; @@ -292,7 +657,7 @@ } } -static void Convert565le(SDL_Surface *surface) +static void Convert565le(_THIS, SDL_Surface *surface) { int x,y, pitch; unsigned short *line, *pixel; @@ -311,7 +676,7 @@ } } -static void ConvertBGRAToABGR(SDL_Surface *surface) +static void ConvertBGRAToABGR(_THIS, SDL_Surface *surface) { int x,y, pitch; unsigned long *line, *pixel;