diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80d2ac9..fa457f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -31,13 +31,13 @@ jobs: run: | sudo apt-get update sudo apt-get install \ - libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl1.2-dev ninja-build + libsdl2-image-dev libsdl2-mixer-dev libsdl2-dev ninja-build - name: Setup macOS dependencies if: runner.os == 'macOS' run: | brew install \ - sdl_image sdl_mixer sdl12-compat ninja + sdl2_image sdl2_mixer sdl2 ninja - name: Set up Windows dependencies if: matrix.platform.shell == 'msys2 {0}' @@ -48,9 +48,9 @@ jobs: ${{ matrix.platform.msys-env }}-gcc ${{ matrix.platform.msys-env }}-cmake ${{ matrix.platform.msys-env }}-ninja - ${{ matrix.platform.msys-env }}-SDL_image - ${{ matrix.platform.msys-env }}-SDL_mixer - ${{ matrix.platform.msys-env }}-SDL + ${{ matrix.platform.msys-env }}-SDL2_image + ${{ matrix.platform.msys-env }}-SDL2_mixer + ${{ matrix.platform.msys-env }}-SDL2 - name: Configure CMake run: cmake -B build -G Ninja diff --git a/CMakeLists.txt b/CMakeLists.txt index 77652f5..dbbe3f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,14 +12,34 @@ if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MA add_compile_options(-Wall -Wextra -pedantic -Werror) endif() -find_package(OpenGL REQUIRED) -find_package(SDL REQUIRED) -find_package(SDL_image REQUIRED) -find_package(SDL_mixer REQUIRED) +find_package(SDL2 REQUIRED) +find_package(SDL2_image QUIET) +find_package(SDL2_mixer QUIET) + +if(NOT SDL2_image_FOUND OR NOT SDL2_mixer_FOUND) + find_package(PkgConfig QUIET) + if(PkgConfig_FOUND AND NOT SDL2_image_FOUND) + pkg_check_modules(SDL2_image IMPORTED_TARGET SDL2_image) + endif() + if(PkgConfig_FOUND AND NOT SDL2_mixer_FOUND) + pkg_check_modules(SDL2_mixer IMPORTED_TARGET SDL2_mixer) + endif() +endif() + +if(NOT SDL2_image_FOUND) + message(FATAL_ERROR "SDL2_image not found") +endif() + +if(NOT SDL2_mixer_FOUND) + message(FATAL_ERROR "SDL2_mixer not found") +endif() + +if(APPLE) + find_library(FRAMEWORK_FOUNDATION Foundation) +endif() set(C_FILES audio.c - glSDL.c menu.c menuitems.c preferences.c @@ -55,30 +75,30 @@ set_property(TARGET flobopuyo PROPERTY CXX_EXTENSIONS OFF) target_compile_definitions(flobopuyo PRIVATE USE_AUDIO - PRIVATE HAVE_OPENGL PRIVATE DATADIR=\"${CMAKE_SOURCE_DIR}/data\" ) -if(APPLE) - target_compile_definitions(flobopuyo - PRIVATE GL_SILENCE_DEPRECATION - ) -endif() - target_include_directories(flobopuyo PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ) target_include_directories(flobopuyo SYSTEM - PRIVATE ${SDL_INCLUDE_DIRS} - PRIVATE ${SDL_IMAGE_INCLUDE_DIRS} - PRIVATE ${SDL_MIXER_INCLUDE_DIRS} + PRIVATE ${SDL2_INCLUDE_DIRS} + PRIVATE ${SDL2_IMAGE_INCLUDE_DIRS} + PRIVATE ${SDL2_MIXER_INCLUDE_DIRS} ) -target_link_libraries(flobopuyo - ${OPENGL_LIBRARIES} - ${SDL_LIBRARIES} - ${SDL_IMAGE_LIBRARIES} - ${SDL_MIXER_LIBRARIES} +target_link_libraries(flobopuyo PRIVATE + $<$:mingw32> + $<$:${FRAMEWORK_FOUNDATION}> + SDL2::SDL2main + SDL2::SDL2 + #SDL2_image::SDL2_image + #PkgConfig::SDL2_image + #$,PkgConfig::SDL2_image, PkgConfig::SDL2_image> + $ + $ + $ + $ ) diff --git a/InputManager.cpp b/InputManager.cpp index 5a8ba04..bee3a7b 100644 --- a/InputManager.cpp +++ b/InputManager.cpp @@ -16,16 +16,16 @@ static const SdlKeyName sdlKeyDictionnary[] = { { SDLK_ESCAPE, "Escape" }, { SDLK_SPACE, "Space" }, { SDLK_DELETE, "Delete" }, - { SDLK_KP0, "KP 0" }, - { SDLK_KP1, "KP 1" }, - { SDLK_KP2, "KP 2" }, - { SDLK_KP3, "KP 3" }, - { SDLK_KP4, "KP 4" }, - { SDLK_KP5, "KP 5" }, - { SDLK_KP6, "KP 6" }, - { SDLK_KP7, "KP 7" }, - { SDLK_KP8, "KP 8" }, - { SDLK_KP9, "KP 9" }, + { SDLK_KP_0, "KP 0" }, + { SDLK_KP_1, "KP 1" }, + { SDLK_KP_2, "KP 2" }, + { SDLK_KP_3, "KP 3" }, + { SDLK_KP_4, "KP 4" }, + { SDLK_KP_5, "KP 5" }, + { SDLK_KP_6, "KP 6" }, + { SDLK_KP_7, "KP 7" }, + { SDLK_KP_8, "KP 8" }, + { SDLK_KP_9, "KP 9" }, { SDLK_UP, "Up Arrow" }, { SDLK_DOWN, "Down Arrow" }, { SDLK_LEFT, "Left Arrow" }, @@ -50,27 +50,27 @@ static const SdlKeyName sdlKeyDictionnary[] = { { SDLK_F13, "F13" }, { SDLK_F14, "F14" }, { SDLK_F15, "F15" }, - { SDLK_NUMLOCK, "Num Lock" }, + { SDLK_NUMLOCKCLEAR, "Num Lock" }, { SDLK_CAPSLOCK, "Caps Lock" }, - { SDLK_SCROLLOCK, "Scroll Lock"}, + { SDLK_SCROLLLOCK, "Scroll Lock"}, { SDLK_RSHIFT, "Right Shift"}, { SDLK_LSHIFT, "Left Shift" }, { SDLK_RCTRL, "Right Ctrl" }, { SDLK_LCTRL, "Left Ctrl" }, { SDLK_RALT, "Right Alt" }, { SDLK_LALT, "Left Alt" }, - { SDLK_RMETA, "Right Meta" }, - { SDLK_LMETA, "Left Meta" }, - { SDLK_RSUPER, "Right Windows" }, - { SDLK_LSUPER, "Left Windows" }, + //{ SDLK_RMETA, "Right Meta" }, + //{ SDLK_LMETA, "Left Meta" }, + { SDLK_RGUI, "Right Windows" }, + { SDLK_LGUI, "Left Windows" }, { SDLK_MODE, "Mode Shift" }, { SDLK_HELP, "Help" }, - { SDLK_PRINT, "Print Screen" }, + { SDLK_PRINTSCREEN, "Print Screen" }, { SDLK_SYSREQ, "Sys Rq" }, - { SDLK_BREAK, "Break" }, + { SDLK_PAUSE, "Break" }, { SDLK_MENU, "Menu" }, - { SDLK_POWER, "Power" }, - { SDLK_EURO, "Euro" } + { SDLK_POWER, "Power" }//, + //{ SDLK_EURO, "Euro" } }; static const int sdlKeyDictionnarySize = sizeof(sdlKeyDictionnary) / sizeof(SdlKeyName); diff --git a/InputManager.h b/InputManager.h index eb4b1b3..4d75669 100644 --- a/InputManager.h +++ b/InputManager.h @@ -1,7 +1,7 @@ #ifndef _INPUT_SW_MAN_H #define _INPUT_SW_MAN_H -#include +#include #include const int JOYSTICK_THRESHOLD = 25000; diff --git a/IosImgProcess.cpp b/IosImgProcess.cpp index 0f9a410..b358946 100644 --- a/IosImgProcess.cpp +++ b/IosImgProcess.cpp @@ -1,5 +1,6 @@ #include "IosImgProcess.h" -#include +#include +#include #include #include #include @@ -18,31 +19,29 @@ int imgListSize = 0; IIM_Surface * IIM_Load_DisplayFormat (const char *fname) { char path[1024]; - SDL_Surface *tmpsurf, *retsurf; + SDL_Surface *retsurf; snprintf(path, 1024, "%s/gfx/%s", dataFolder, fname); - tmpsurf = IMG_Load (path); - if (tmpsurf==0) { + retsurf = IMG_Load (path); + if (retsurf==0) { fprintf(stderr,"Could not load %s\n", path); exit(1); } - retsurf = SDL_DisplayFormat (tmpsurf); - SDL_FreeSurface (tmpsurf); return IIM_RegisterImg(retsurf, false); } IIM_Surface * IIM_Load_DisplayFormatAlpha (const char *fname) { char path[1024]; - SDL_Surface *tmpsurf, *retsurf; + SDL_Surface *retsurf; snprintf(path, 1024, "%s/gfx/%s", dataFolder, fname); - tmpsurf = IMG_Load (path); - if (tmpsurf==0) { + retsurf = IMG_Load (path); + if (retsurf==0) { fprintf(stderr,"Could not load %s\n", path); exit(1); } - retsurf = SDL_DisplayFormatAlpha (tmpsurf); - SDL_SetAlpha (retsurf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); - SDL_FreeSurface (tmpsurf); + //retsurf = SDL_DisplayFormatAlpha (tmpsurf); + //SDL_SetAlpha (retsurf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); + //SDL_FreeSurface (tmpsurf); return IIM_RegisterImg(retsurf, true); } @@ -68,29 +67,6 @@ IIM_Surface * IIM_RegisterImg(SDL_Surface *img, bool isAlpha) return &(imgList[imgListSize++]); } -void IIM_ReConvertAll(void) -{ - for (int i=0; isurf; - isrc->surf = SDL_DisplayFormatAlpha(ret); - SDL_SetAlpha(isrc->surf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); - SDL_FreeSurface(ret); - return IIM_RegisterImg(ret2, true); + //SDL_Surface *ret2 = SDL_DisplayFormatAlpha(ret); + //SDL_SetAlpha(ret2, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); + //SDL_FreeSurface(ret); + //ret = isrc->surf; + //isrc->surf = SDL_DisplayFormatAlpha(ret); + //SDL_SetAlpha(isrc->surf, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); + //SDL_FreeSurface(ret); + return IIM_RegisterImg(ret, true); } IIM_Surface *iim_surface_set_value(IIM_Surface *isrc, float value) @@ -376,10 +352,10 @@ IIM_Surface *iim_surface_set_value(IIM_Surface *isrc, float value) } SDL_UnlockSurface(src); SDL_UnlockSurface(ret); - SDL_Surface *ret2 = SDL_DisplayFormatAlpha(ret); - SDL_SetAlpha(ret2, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); - SDL_FreeSurface(ret); - return IIM_RegisterImg(ret2, true); + //SDL_Surface *ret2 = SDL_DisplayFormatAlpha(ret); + //SDL_SetAlpha(ret2, SDL_SRCALPHA | (useGL?0:SDL_RLEACCEL), SDL_ALPHA_OPAQUE); + //SDL_FreeSurface(ret); + return IIM_RegisterImg(ret, true); } void iim_surface_convert_to_gray(IIM_Surface *isrc) @@ -397,6 +373,6 @@ void iim_surface_convert_to_gray(IIM_Surface *isrc) } } SDL_UnlockSurface(src); - isrc->surf = SDL_DisplayFormat(src); - SDL_FreeSurface(src); + //isrc->surf = SDL_DisplayFormat(src); + //SDL_FreeSurface(src); } diff --git a/IosImgProcess.h b/IosImgProcess.h index 8021981..5f90195 100644 --- a/IosImgProcess.h +++ b/IosImgProcess.h @@ -7,8 +7,7 @@ extern "C" { #include #endif -#include -#include +#include typedef struct _RGBA { Uint8 red; @@ -63,7 +62,6 @@ IIM_Surface * IIM_Load_DisplayFormat (const char *path); IIM_Surface * IIM_Load_DisplayFormatAlpha (const char *path); void IIM_Free(IIM_Surface *img); IIM_Surface * IIM_RegisterImg(SDL_Surface *img, bool isAlpha); -void IIM_ReConvertAll(void); #ifdef __cplusplus } diff --git a/PuyoCommander.cpp b/PuyoCommander.cpp index da4530f..3dd78dd 100644 --- a/PuyoCommander.cpp +++ b/PuyoCommander.cpp @@ -3,7 +3,6 @@ #include #include #include "GameControls.h" -#include "glSDL.h" #include "PuyoCommander.h" #include "PuyoStarter.h" #include "InputManager.h" @@ -109,6 +108,8 @@ const char *AI_NAMES[] = { "Fanzy", "Garou", "Big Rabbit", "Gizmo", extern SDL_Surface *display; +extern SDL_Window *window; +extern SDL_Renderer *renderer; extern IIM_Surface *image, *gameScreen; IIM_Surface *menuBGImage = 0; PuyoCommander *theCommander; @@ -546,14 +547,9 @@ MenuItems pause_menu_load (SoFont * font) PuyoCommander::PuyoCommander(bool fs, bool snd, bool audio) { - int init_flags = SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK; - - SDL_Delay(500); corona = NULL; fullscreen = GetBoolPreference(kFullScreen,fs); -#ifdef HAVE_OPENGL useGL = GetBoolPreference(kOpenGL,false); -#endif sound = GetBoolPreference(kMusic,snd); fx = GetBoolPreference(kAudioFX,audio); @@ -561,32 +557,12 @@ PuyoCommander::PuyoCommander(bool fs, bool snd, bool audio) int audio_volume = GetIntPreference(kAudioVolume, 80); initGameControls(); -#ifdef USE_DGA - /* This Hack Allows Hardware Surface on Linux */ - if (fullscreen) - setenv("SDL_VIDEODRIVER","dga",0); - - if (SDL_Init(init_flags) < 0) { - setenv("SDL_VIDEODRIVER","x11",1); - if (SDL_Init(init_flags) < 0) { - fprintf(stderr, "SDL initialisation error: %s\n", SDL_GetError()); - exit(1); - } - } - else { - if (fullscreen) - SDL_WM_GrabInput(SDL_GRAB_ON); - } -#else -#ifdef WIN32 - _putenv("SDL_VIDEODRIVER=windib"); -#endif - if ( SDL_Init(init_flags) < 0 ) { + + if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO|SDL_INIT_JOYSTICK) < 0 ) { fprintf(stderr, "SDL initialisation error: %s\n", SDL_GetError()); exit(1); } -#endif - SDL_WM_SetCaption("FloboPuyo", "FloboPuyo"); + initControllers(); initHiScores(AI_NAMES); @@ -601,14 +577,21 @@ PuyoCommander::PuyoCommander(bool fs, bool snd, bool audio) audio_music_set_volume(music_volume); #endif - display = SDL_SetVideoMode( 640, 480, 0, SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF|(fullscreen?SDL_FULLSCREEN:0)|(useGL?SDL_GLSDL:0)); - if ( display == NULL ) { - fprintf(stderr, "SDL_SetVideoMode error: %s\n", + //display = SDL_SetVideoMode( 640, 480, 0, SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF|(fullscreen?SDL_FULLSCREEN:0)|(useGL?SDL_GLSDL:0)); + window = SDL_CreateWindow("Flobopuyo", + SDL_WINDOWPOS_CENTERED, + SDL_WINDOWPOS_CENTERED, + 640, 480, + SDL_WINDOW_OPENGL); + if ( window == NULL ) { + fprintf(stderr, "SDL_CreateWindow error: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); - SDL_ShowCursor(SDL_DISABLE); + renderer = SDL_CreateRenderer(window, -1, 0); + display = SDL_CreateRGBSurface(0,640,480,32,0,0,0,0); + //SDL_ShowCursor(SDL_DISABLE); smallFont = SoFont_new(); SoFont_load (smallFont, IIM_Load_DisplayFormatAlpha ("font4b.png")); @@ -945,7 +928,7 @@ void PuyoCommander::optionMenuLoop(PuyoDrawable *d) if (menu_active_is (optionMenu, kFullScreen)) { fullscreen = menu_switch_on_off(optionMenu, kFullScreen); SetBoolPreference(kFullScreen,fullscreen); - if (useGL) + if (useGL) // FIXME { menu_hide(optionMenu); backLoop(mustRestartMenu,d); @@ -960,9 +943,10 @@ void PuyoCommander::optionMenuLoop(PuyoDrawable *d) #else SDL_QuitSubSystem(SDL_INIT_VIDEO); SDL_InitSubSystem(SDL_INIT_VIDEO); - display = SDL_SetVideoMode(640, 480, 0, +/* display = SDL_SetVideoMode(640, 480, 0, SDL_ANYFORMAT|SDL_HWSURFACE|SDL_DOUBLEBUF |(fullscreen?SDL_FULLSCREEN:0)|(useGL?SDL_GLSDL:0)); +*/ #endif /* IIM_ReConvertAll(); SoFont_Refresh(menuFont); @@ -1081,14 +1065,14 @@ void PuyoCommander::enterStringLoop(Menu *menu, const char *kItem, char out[256] default: break; } - SDL_EnableUNICODE( SDL_ENABLE ); + switch (e.type) { - case SDL_KEYDOWN: + case SDL_TEXTINPUT: { char ch = 0; if (((e.key.keysym.sym >= SDLK_a) && (e.key.keysym.sym <= SDLK_z)) || ((e.key.keysym.sym >= SDLK_0) && (e.key.keysym.sym <= SDLK_9))) - ch = e.key.keysym.unicode; + ch = '#'; // FIXME if (e.key.keysym.sym == SDLK_SPACE) ch = ' '; @@ -1108,7 +1092,6 @@ void PuyoCommander::enterStringLoop(Menu *menu, const char *kItem, char out[256] } break; } - SDL_EnableUNICODE( SDL_DISABLE ); } updateAll(NULL); } @@ -1350,7 +1333,7 @@ void PuyoCommander::startSingleGameLoop() #define TIME_TOLERANCE 4 -void PuyoCommander::updateAll(PuyoDrawable *starter, SDL_Surface *extra_surf) +void PuyoCommander::updateAll(PuyoDrawable *starter) { Uint32 now = 0; @@ -1414,15 +1397,6 @@ void PuyoCommander::updateAll(PuyoDrawable *starter, SDL_Surface *extra_surf) SDL_BlitSurface(tmpsurf, NULL, display, &rect); SDL_FreeSurface (tmpsurf); } - if (extra_surf) - { - SDL_Rect rect; - rect.x = 0; - rect.y = 480 - extra_surf->h; - rect.w = extra_surf->w; - rect.h = extra_surf->h; - SDL_BlitSurface(extra_surf, NULL, display, &rect); - } if (!starter) scrolling_text_draw(scrollingText, display, 460); @@ -1443,7 +1417,16 @@ void PuyoCommander::updateAll(PuyoDrawable *starter, SDL_Surface *extra_surf) menu_draw (twoPlayerGameMenu, display); menu_draw(menu_pause,display); doom_melt_display(melt, display); - SDL_Flip (display); + + //SDL_Flip (display); + SDL_Texture *sdlTexture = SDL_CreateTexture(renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + 640, 480); + SDL_UpdateTexture(sdlTexture, NULL, display->pixels, display->pitch); + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, sdlTexture, NULL, NULL); + SDL_RenderPresent(renderer); } // delay si machine trop rapide diff --git a/PuyoCommander.h b/PuyoCommander.h index 5749699..597800f 100644 --- a/PuyoCommander.h +++ b/PuyoCommander.h @@ -23,7 +23,7 @@ class PuyoCommander PuyoCommander(bool fullscreen,bool sound, bool audio); void run(); - void updateAll(PuyoDrawable *starter, SDL_Surface *extra_surf = NULL); + void updateAll(PuyoDrawable *starter); void showGameOver() { menu_show(gameOverMenu); } void hideGameOver() { menu_hide(gameOverMenu); } diff --git a/PuyoStarter.cpp b/PuyoStarter.cpp index 9334f48..1f96d50 100644 --- a/PuyoStarter.cpp +++ b/PuyoStarter.cpp @@ -207,8 +207,8 @@ PuyoStarter::PuyoStarter(PuyoCommander *commander, bool aiLeft, int aiLevel, IA_ background->w, background->h, 32, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask); - gameScreen = painter.gameScreen = IIM_RegisterImg(SDL_DisplayFormat(tmp), false); - SDL_FreeSurface(tmp); + gameScreen = painter.gameScreen = IIM_RegisterImg(tmp, false); + //SDL_FreeSurface(tmp); } painter.redrawAll(painter.gameScreen->surf); @@ -343,7 +343,6 @@ void PuyoStarter::run(int _score1, int _score2, int lives, int point1, int point this->score2 = _score2; SDL_Event event; int quit = 0; - SDL_EnableUNICODE(1); int keysDown[FPKEY_keyNumber] = {0,0,0,0,0,0,0,0,0,0}; gameSpeed = 20; diff --git a/PuyoView.cpp b/PuyoView.cpp index 976d2ab..7fef295 100644 --- a/PuyoView.cpp +++ b/PuyoView.cpp @@ -38,6 +38,8 @@ extern "C" { SDL_Painter painter; SDL_Surface *display; +SDL_Window *window; +SDL_Renderer *renderer; IIM_Surface *background, *fallingBlue, *fallingRed, *fallingGreen, *fallingViolet, *fallingYellow, *neutral; IIM_Surface *bigNeutral; IIM_Surface *puyoEyes; diff --git a/SDL_Painter.cpp b/SDL_Painter.cpp index 243b47c..2ed9237 100644 --- a/SDL_Painter.cpp +++ b/SDL_Painter.cpp @@ -1,8 +1,6 @@ #include "SDL_Painter.h" #include -// #define DEBUG - extern SDL_Surface *display; SDL_Painter::SDL_Painter(IIM_Surface *gameScreen, IIM_Surface *bg) @@ -128,36 +126,6 @@ void SDL_Painter::draw(SDL_Surface *surf) // Pour chaque rectangle // Chercher les elements de la liste actuelle qui intersectent // (note: j'assume que SDL fait ca aussi bien que nous) -#ifdef DEBUG - - SDL_SetClipRect(surf, NULL); - SDL_BlitSurface(backGround, NULL, surf, NULL); - - // Draw everything. - for (int i=0; i -#include -#include - -#define HAS_SDL_OPENGL_H 1 - -#if HAS_SDL_OPENGL_H -#include "SDL_opengl.h" -#else -#ifdef WIN32 -#include -#endif -#if defined(__APPLE__) && defined(__MACH__) -#include -#include -#else -#include -#include -#endif -#endif - -#define USING_GLSDL (IS_GLSDL_SURFACE(SDL_GetVideoSurface())) - -#define MAX_TEXINFOS 16384 - -static glSDL_TexInfo **texinfotab = NULL; -static GLint maxtexsize = 256; -static SDL_PixelFormat _RGBfmt, _RGBAfmt; -static int screen_was_locked = 0; - -static void _UnloadTexture(glSDL_TexInfo *txi); - -static int scale = 1; - -static SDL_Surface *fake_screen = NULL; - - -static int _glSDL_BlitGL(SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); - - -DBG(static void _print_glerror(int point) -{ - const char *err = ""; - switch(glGetError()) - { - case GL_NO_ERROR: - return; - case GL_INVALID_ENUM: - err = "GL_INVALID_ENUM"; - break; - case GL_INVALID_VALUE: - err = "GL_INVALID_VALUE"; - break; - case GL_INVALID_OPERATION: - err = "GL_INVALID_OPERATION"; - break; - case GL_STACK_OVERFLOW: - err = "GL_STACK_OVERFLOW"; - break; - case GL_STACK_UNDERFLOW: - err = "GL_STACK_UNDERFLOW"; - break; - case GL_OUT_OF_MEMORY: - err = "GL_OUT_OF_MEMORY"; - break; - default: - err = ""; - break; - } - fprintf(stderr,"OpenGL error \"%s\" at point %d.\n", err, point); -}) - - -/* Get texinfo for a surface. */ -glSDL_TexInfo *glSDL_GetTexInfo(SDL_Surface *surface) -{ - if(!surface) - return NULL; - if(!texinfotab) - return NULL; - if(!surface->unused1) - return NULL; - if(surface->unused1 > MAX_TEXINFOS) - return NULL; - - return texinfotab[surface->unused1 - 1]; -} - - -/* Allocate a "blank" texinfo for a suface. */ -glSDL_TexInfo *glSDL_AllocTexInfo(SDL_Surface *surface) -{ - int handle, i; - glSDL_TexInfo *txi; - if(!surface) - return NULL; - - if(!texinfotab) - { - texinfotab = (glSDL_TexInfo**)calloc(MAX_TEXINFOS, sizeof(glSDL_TexInfo *)); - if(!texinfotab) - return NULL; - } - - txi = glSDL_GetTexInfo(surface); - if(txi) - return txi; /* There already is one! --> */ - - /* Find a free handle... */ - handle = -1; - for(i = 0; i < MAX_TEXINFOS; ++i) - if(NULL == texinfotab[i]) - { - handle = i; - break; - } - - if(handle < 0) - { - DBG(fprintf(stderr, "glSDL: Out of handles!\n")); - return NULL; - } - - /* ...and hook a new texinfo struct up to it. */ - texinfotab[handle] = (glSDL_TexInfo*)calloc(1, sizeof(glSDL_TexInfo)); - if(!texinfotab[handle]) - return NULL; - - /* Connect the surface to the new TexInfo. */ - surface->unused1 = (Uint32)handle + 1; - - DBG2(fprintf(stderr, "glSDL: Allocated TexInfo %d.\n", handle)); - - return texinfotab[handle]; -} - - -static void _FreeTexInfo(Uint32 handle) -{ - if(handle >= MAX_TEXINFOS) - return; - if(!texinfotab[handle]) - return; - - _UnloadTexture(texinfotab[handle]); - texinfotab[handle]->textures = 0; - free(texinfotab[handle]->texture); - texinfotab[handle]->texture = NULL; - free(texinfotab[handle]); - texinfotab[handle] = NULL; - DBG2(fprintf(stderr, "glSDL: Freed TexInfo %d.\n", handle)); -} - - -/* Detach and free the texinfo of a surface. */ -void glSDL_FreeTexInfo(SDL_Surface *surface) -{ - if(!glSDL_GetTexInfo(surface)) - return; - - _FreeTexInfo(surface->unused1 - 1); - GLSDL_FIX_SURFACE(surface); -} - - -/* - * Calculate chopping/tiling of a surface to - * fit it into the smallest possible OpenGL - * texture. - */ -static int _CalcChop(glSDL_TexInfo *txi) -{ - int rows, vw, vh; - int vertical = 0; - int texsize; - int lastw, lasth, minsize; - - vw = txi->virt.w; - vh = txi->virt.h; - - DBG3(fprintf(stderr, "w=%d, h=%d ", vw, vh)); - if(vh > vw) - { - int t = vw; - vw = vh; - vh = t; - vertical = 1; - DBG3(fprintf(stderr, "(vertical) \t")); - } - - /* - * Check whether this is a "huge" surface - at least one dimension - * must be <= than the maximum texture size, or we'll have to chop - * in both directions. - */ - if(vh > maxtexsize) - { - fprintf(stderr, "glSDL: \"Huge\" surfaces not yet supported!\n"); - return 0; - } - - /* Calculate minimum size */ - rows = 1; - lastw = vw; - lasth = vh; - minsize = lastw > lasth ? lastw : lasth; - while(1) - { - int w, h, size; - ++rows; - w = vw / rows; - h = rows * vh; - size = w > h ? w : h; - if(size >= minsize) - { - --rows; - break; - } - minsize = size; - } - if(minsize > maxtexsize) - { - /* Handle multiple textures for very wide/tall surfaces. */ - minsize = maxtexsize; - DBG3(rows = (vw + minsize-1) / minsize); - } - DBG3(fprintf(stderr, "==> minsize=%d ", minsize)); - DBG3(fprintf(stderr, "(rows=%d) \t", rows)); - - /* Recalculate with nearest higher power-of-2 width. */ - for(texsize = 1; texsize < minsize; texsize <<= 1) - ; - txi->texsize = texsize; - rows = (vw + texsize-1) / texsize; - DBG3(fprintf(stderr, "==> texsize=%d (rows=%d) \t", texsize, rows)); - - /* Calculate number of tiles per texture */ - txi->tilespertex = txi->texsize / vh; - DBG3(fprintf(stderr, "tilespertex=%d \t", txi->tilespertex)); - - /* Calculate number of textures needed */ - txi->textures = (rows + txi->tilespertex-1) / txi->tilespertex; - txi->texture = (int*)malloc(txi->textures * sizeof(int)); - memset(txi->texture, -1, txi->textures * sizeof(int)); - DBG3(fprintf(stderr, "textures=%d, ", txi->textures)); - if(!txi->texture) - { - fprintf(stderr, "glSDL: INTERNAL ERROR: Failed to allocate" - " texture name table!\n"); - return -2; - } - - /* Set up tile size. (Only one axis supported here!) */ - if(1 == rows) - { - txi->tilemode = GLSDL_TM_SINGLE; - if(vertical) - { - txi->tilew = vh; - txi->tileh = vw; - } - else - { - txi->tilew = vw; - txi->tileh = vh; - } - } - else if(vertical) - { - txi->tilemode = GLSDL_TM_VERTICAL; - txi->tilew = vh; - txi->tileh = texsize; - } - else - { - txi->tilemode = GLSDL_TM_HORIZONTAL; - txi->tilew = texsize; - txi->tileh = vh; - } - - DBG3(fprintf(stderr, "tilew=%d, tileh=%d\n", txi->tilew, txi->tileh)); - return 0; -} - - -/* -TODO: - * Keep a list or tree of free texture space rectangles. - - * The space manager should actively try to merge - rectangles from the same texture. - -static int _AllocTexSpace(glSDL_TexInfo *txi) -{ - Make sure that _CalcChop() has been called. - - Try to find the smallest free area (one or more - tiles) in a single texture that would fit all - tiles of this surface. - - if that fails - { - Allocate a new texture of suitable size. - if that fails - { - Try to allocate space for each tile separately. - if that fails - return error --> - } - } - - Allocate the areas and link them to the texinfo. - return success --> -} -*/ - - -/* Add a glSDL_TexInfo struct to an SDL_Surface */ -static int glSDL_AddTexInfo(SDL_Surface *surface) -{ - glSDL_TexInfo *txi; - - if(!surface) - return -1; - if(IS_GLSDL_SURFACE(surface)) - return 0; /* Do nothing */ - - glSDL_AllocTexInfo(surface); - txi = glSDL_GetTexInfo(surface); - if(!txi) - return -2; /* Oops! Didn't get a texinfo... --> */ - - txi->virt.w = txi->lw = surface->w; - txi->virt.h = txi->lh = surface->h; - - if(_CalcChop(txi) < 0) - return -3; - - SDL_SetClipRect(surface, &txi->virt); - - return 0; -} - - -/* Create a surface of the prefered OpenGL RGB texture format */ -static SDL_Surface *_CreateRGBSurface(int w, int h) -{ - SDL_Surface *s; - Uint32 rmask, gmask, bmask; - int bits = 24; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0x00ff0000; - gmask = 0x0000ff00; - bmask = 0x000000ff; -#else - rmask = 0x000000ff; - gmask = 0x0000ff00; - bmask = 0x00ff0000; -#endif - s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, - bits, rmask, gmask, bmask, 0); - if(s) - GLSDL_FIX_SURFACE(s); - - glSDL_AddTexInfo(s); - return s; -} - - -/* Create a surface of the prefered OpenGL RGBA texture format */ -static SDL_Surface *_CreateRGBASurface(int w, int h) -{ - SDL_Surface *s; - Uint32 rmask, gmask, bmask, amask; - int bits = 32; -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - rmask = 0xff000000; - gmask = 0x00ff0000; - bmask = 0x0000ff00; - amask = 0x000000ff; -#else - rmask = 0x000000ff; - gmask = 0x0000ff00; - bmask = 0x00ff0000; - amask = 0xff000000; -#endif - s = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, - bits, rmask, gmask, bmask, amask); - if(s) - GLSDL_FIX_SURFACE(s); - - glSDL_AddTexInfo(s); - return s; -} - - -static void _init_formats(void) -{ - SDL_Surface *s = _CreateRGBSurface(1, 1); - if(!s) - return; - _RGBfmt = *(s->format); - glSDL_FreeSurface(s); - - s = _CreateRGBASurface(1, 1); - if(!s) - return; - _RGBAfmt = *(s->format); - glSDL_FreeSurface(s); -} - - -static int _FormatIsOk(SDL_Surface *surface) -{ - SDL_PixelFormat *pf; - if(!surface) - return 1; /* Well, there ain't much we can do anyway... */ - - pf = surface->format; - - /* Colorkeying requires an alpha channel! */ - if(surface->flags & SDL_SRCCOLORKEY) - if(!pf->Amask) - return 0; - - /* We need pitch == (width * BytesPerPixel) for glTex[Sub]Image2D() */ - if(surface->pitch != (surface->w * pf->BytesPerPixel)) - return 0; - - if(pf->Amask) - { - if(pf->BytesPerPixel != _RGBAfmt.BytesPerPixel) - return 0; - if(pf->Rmask != _RGBAfmt.Rmask) - return 0; - if(pf->Gmask != _RGBAfmt.Gmask) - return 0; - if(pf->Bmask != _RGBAfmt.Bmask) - return 0; - if(pf->Amask != _RGBAfmt.Amask) - return 0; - } - else - { - if(pf->BytesPerPixel != _RGBfmt.BytesPerPixel) - return 0; - if(pf->Rmask != _RGBfmt.Rmask) - return 0; - if(pf->Gmask != _RGBfmt.Gmask) - return 0; - if(pf->Bmask != _RGBfmt.Bmask) - return 0; - } - return 1; -} - - - -static void _key2alpha(SDL_Surface *surface) -{ - int x, y; -#ifdef CKSTATS - int transp = 0; -#endif - Uint32 ckey = surface->format->colorkey; - if(SDL_LockSurface(surface) < 0) - return; - - for(y = 0; y < surface->h; ++y) - { - Uint32 *px = (Uint32 *)((char *)surface->pixels + y*surface->pitch); - for(x = 0; x < surface->w; ++x) - if(px[x] == ckey) - { - px[x] = 0; -#ifdef CKSTATS - ++transp; -#endif - } - } -#ifdef CKSTATS - printf("glSDL: key2alpha(); %dx%d surface, %d opaque pixels.\n", - surface->w, surface->h, - surface->w * surface->h - transp); -#endif - SDL_UnlockSurface(surface); -} - - - -/*---------------------------------------------------------- - SDL style API -----------------------------------------------------------*/ - -static void _KillAllTextures(void) -{ - if(texinfotab) - { - unsigned i; -#ifdef LEAK_TRACKING - int leaked = 0; - for(i = 0; i < MAX_TEXINFOS; ++i) - if(texinfotab[i]) - { - ++leaked; - fprintf(stderr, "glSDL: Leaked TexInfo" - " %d! (%dx%d)\n", - i, - texinfotab[i]->virt.w, - texinfotab[i]->virt.h - ); - } - if(leaked) - fprintf(stderr, "glSDL: Leaked %d TexInfos!\n", leaked); -#endif - for(i = 0; i < MAX_TEXINFOS; ++i) - _FreeTexInfo(i); - free(texinfotab); - texinfotab = NULL; - } -} - -void glSDL_Quit(void) -{ - if(SDL_WasInit(SDL_INIT_VIDEO)) - { - SDL_Surface *screen = SDL_GetVideoSurface(); - glSDL_FreeTexInfo(screen); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - if(fake_screen) - { - glSDL_FreeTexInfo(fake_screen); - free(fake_screen); - fake_screen = NULL; - } - } -#ifndef LEAK_TRACKING - _KillAllTextures(); -#endif -} - - -void _glSDL_FullQuit(void) -{ -#ifdef LEAK_TRACKING - _KillAllTextures(); -#endif - glSDL_Quit(); - SDL_Quit(); -} - - -void glSDL_QuitSubSystem(Uint32 flags) -{ - if(flags & SDL_INIT_VIDEO) - glSDL_Quit(); - SDL_QuitSubSystem(flags); -} - - -SDL_Surface *glSDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) -{ - SDL_Surface *screen; - GLint gl_doublebuf; - if(!(flags & SDL_GLSDL)) - { - screen = SDL_SetVideoMode(width, height, bpp, flags); - if(screen) - GLSDL_FIX_SURFACE(screen); - return screen; - } - - if((SDL_Linked_Version()->major <= 1) && - (SDL_Linked_Version()->minor <= 2) && - (SDL_Linked_Version()->patch < 5)) - fprintf(stderr, "glSDL WARNING: Using SDL version" - " 1.2.5 or later is strongly" - " recommended!\n"); - -/* - * FIXME: Here's the place to insert proper handling of this call being - * used for resizing the window... For now, just make sure we - * don't end up with invalid texinfos and stuff no matter what. - */ - _KillAllTextures(); - - /* Remove flag to avoid confusion inside SDL - just in case! */ - flags &= ~SDL_GLSDL; - - flags |= SDL_OPENGL; - if(bpp == 15) - { - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - } - else if(bpp == 16) - { - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); - } - else if(bpp >= 24) - { - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - } - gl_doublebuf = flags & SDL_DOUBLEBUF; - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, gl_doublebuf); - - DBG(printf("desired = %d x %d\n", width, height);) - scale = 1; - while((width*scale < 640) && (height*scale < 480)) - ++scale; - DBG(printf("real = %d x %d\n", width*scale, height*scale);) - - screen = SDL_SetVideoMode(width*scale, height*scale, bpp, flags); - if(!screen) - return NULL; - - GLSDL_FIX_SURFACE(screen); - -#ifdef FAKE_MAXTEXSIZE - maxtexsize = FAKE_MAXTEXSIZE; -#else - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsize); -#endif - DBG(fprintf(stderr, "glSDL: Max texture size: %d\n", maxtexsize)); - - _init_formats(); - - if(glSDL_AddTexInfo(screen) < 0) - { - DBG(fprintf(stderr, "glSDL: Failed to add info to screen surface!\n")); - SDL_QuitSubSystem(SDL_INIT_VIDEO); - return NULL; - } - - glSDL_SetLogicSize(screen, width*scale, height*scale); - - /* - * Create a software shadow buffer of the requested size. - * This is used for blit-from-screen and simulation of - * direct software rendering. (Dog slow crap. It's only - * legitimate use is probably screen shots.) - */ - fake_screen = _CreateRGBSurface(screen->w / scale, - screen->h / scale); - return fake_screen; -} - - -SDL_Surface *glSDL_GetVideoSurface(void) -{ - if(fake_screen) - return fake_screen; - else - return SDL_GetVideoSurface(); -} - - -void glSDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) -{ - if(IS_GLSDL_SURFACE(screen)) - { -/* if(screen_was_locked) - { - int i; - for(i = 0; i < numrects; ++i) - _glSDL_BlitGL(fake_screen, rects + i, - vs, rects + i); - } - else -*/ - glSDL_Flip(screen); - } - else - SDL_UpdateRects(screen, numrects, rects); - screen_was_locked = 0; -} - - -void glSDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h) -{ - SDL_Rect r; - r.x = x; - r.y = y; - r.w = w; - r.h = h; - glSDL_UpdateRects(screen, 1, &r); -} - - -int glSDL_Flip(SDL_Surface *screen) -{ - if(!IS_GLSDL_SURFACE(screen)) - return SDL_Flip(screen); -/* -TODO: Perform all rendering here, after globally reordering/optimizing - all non-overlapping operations for the frame. (Reduce texture - changes, blend mode changes etc...) - -Disadvantage: - Won't mix well with user OpenGL calls - but then again, glSDL - isn't meant for OpenGL aware applications in the first place! -*/ - /* - * Some XFree86 DRI drivers won't sync *at all* - * without glFinish()! You may end up with commands - * for several frames buffered up before any actual - * rendering is done - and then, your program will - * stall until most of the rendering is completed. - * - * (Of course, this wouldn't be much of an issue - * if the drivers did retrace sync'ed flips, but as - * most of the drivers don't, there's no way ever an - * application is going to get smooth animation - * without this kludge.) - * - * Update: That bl**dy *DRIVER* should be fixed! - * We don't need this performance killing - * kludge. (I know for sure that my current - * driver doesn't have this problem.) - */ -#ifdef STUPID_GL_WORKAROUND - glFlush(); /* Just in case. *heh* */ - SDL_GL_SwapBuffers(); - glFinish(); /* And here we kill parallel execution... :-( */ -#else - SDL_GL_SwapBuffers(); -#endif - return 0; -} - - -void glSDL_FreeSurface(SDL_Surface *surface) -{ - if(!surface) - return; - glSDL_FreeTexInfo(surface); - SDL_FreeSurface(surface); -} - - -int glSDL_LockSurface(SDL_Surface *surface) -{ - if(!surface) - return 0; - - if(IS_GLSDL_SURFACE(surface)) - { - if((surface == fake_screen) || - (SDL_GetVideoSurface() == surface)) - { - if(scale > 1) - return -1; - - glSDL_Invalidate(fake_screen, NULL); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, - fake_screen->pitch / - fake_screen->format->BytesPerPixel); - - glReadPixels(0, 0, fake_screen->w, fake_screen->h, - GL_RGB, GL_UNSIGNED_BYTE, - fake_screen->pixels); - return 0; - } - else - { - glSDL_Invalidate(surface, NULL); - return SDL_LockSurface(surface); - } - } - else - return SDL_LockSurface(surface); -} - - -void glSDL_UnlockSurface(SDL_Surface *surface) -{ - if(!surface) - return; - - if(IS_GLSDL_SURFACE(surface)) - { - glSDL_UploadSurface(surface); - if((surface == fake_screen) || - (SDL_GetVideoSurface() == surface)) - _glSDL_BlitGL(fake_screen, NULL, - SDL_GetVideoSurface(), NULL); - } - else - SDL_UnlockSurface(surface); -} - - -int glSDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key) -{ - int res = SDL_SetColorKey(surface, flag, key); - if(res < 0) - return res; - /* - * If an application does this *after* SDL_DisplayFormat, - * we're basically screwed, unless we want to do an - * in-place surface conversion hack here. - * - * What we do is just kill the glSDL texinfo... No big - * deal in most cases, as glSDL only converts once anyway, - * *unless* you keep modifying the surface. - */ - if(IS_GLSDL_SURFACE(surface)) - glSDL_FreeTexInfo(surface); - return res; -} - - -int glSDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha) -{ - /* - * This is just parameters to OpenGL, so the actual - * "work" is done in glSDL_BlitSurface(). - */ - return SDL_SetAlpha(surface, flag, alpha); -} - - -SDL_bool glSDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect) -{ - SDL_bool res; - SDL_Surface *screen; - SDL_Rect fsr; - - if(!surface) - return SDL_FALSE; - - screen = SDL_GetVideoSurface(); - - res = SDL_SetClipRect(surface, rect); - if(!res) - return SDL_FALSE; - - if(!rect) - { - fsr.x = 0; - fsr.y = 0; - fsr.w = screen->w; - fsr.h = screen->h; - rect = &fsr; - } - - if(surface == fake_screen) - { - SDL_Rect r; - r.x = rect->x * scale; - r.y = rect->y * scale; - r.w = rect->w * scale; - r.h = rect->h * scale; - surface = screen; - SDL_SetClipRect(surface, &r); - } - - if( (screen == surface) && - IS_GLSDL_SURFACE(surface) ) - { - float xscale, yscale; - glSDL_TexInfo *txi = glSDL_GetTexInfo(surface); - rect = &surface->clip_rect; - glViewport( rect->x * scale, - screen->h - (rect->y + rect->h) * scale, - rect->w * scale, - rect->h * scale); - /* - * Note that this projection is upside down in - * relation to the OpenGL coordinate system. - */ - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - xscale = (float)txi->lw / (float)surface->w; - yscale = (float)txi->lh / (float)surface->h; - glOrtho( xscale*(float)rect->x, - xscale*(float)(rect->w+rect->x), - yscale*(float)(rect->h+rect->y), - yscale*(float)rect->y, - -1.0, 1.0); - return SDL_TRUE; - } - return res; -} - - -static struct -{ - int do_blend; - int do_texture; - GLint texture; - GLenum sfactor, dfactor; -} glstate; - -static void gl_reset(void) -{ - glstate.do_blend = -1; - glstate.do_blend = -1; - glstate.texture = -1; - glstate.sfactor = 0xffffffff; - glstate.dfactor = 0xffffffff; -} - -static __inline__ void gl_do_blend(int on) -{ - if(glstate.do_blend == on) - return; - - if(on) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); - glstate.do_blend = on; -} - -static __inline__ void gl_do_texture(int on) -{ - if(glstate.do_texture == on) - return; - - if(on) - glEnable(GL_TEXTURE_2D); - else - glDisable(GL_TEXTURE_2D); - glstate.do_texture = on; -} - -static __inline__ void gl_blendfunc(GLenum sfactor, GLenum dfactor) -{ - if((sfactor == glstate.sfactor) && (dfactor == glstate.dfactor)) - return; - - glBlendFunc(sfactor, dfactor); - - glstate.sfactor = sfactor; - glstate.dfactor = dfactor; -} - -static __inline__ void gl_texture(GLint tx) -{ - if(tx == glstate.texture) - return; - - glBindTexture(GL_TEXTURE_2D, tx); - glstate.texture = tx; -} - - -static int _glSDL_BlitFromGL(SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect) -{ - int i, sy0, dy0; - SDL_Rect sr, dr; - - if(scale > 1) - return -1; -/* -FIXME: Some clipping, perhaps...? :-) -*/ - /* In case the destination has an OpenGL texture... */ - glSDL_Invalidate(dst, dstrect); - - /* Abuse the fake screen buffer a little. */ - glPixelStorei(GL_UNPACK_ROW_LENGTH, fake_screen->pitch / - fake_screen->format->BytesPerPixel); - if(srcrect) - glReadPixels(srcrect->x, srcrect->y, srcrect->w, srcrect->h, - GL_RGB, GL_UNSIGNED_BYTE, fake_screen->pixels); - else - glReadPixels(0, 0, fake_screen->w, fake_screen->h, - GL_RGB, GL_UNSIGNED_BYTE, fake_screen->pixels); - - /* Blit to the actual target! (Vert. flip... Uuurgh!) */ - if(srcrect) - sr = *srcrect; - else - { - sr.x = sr.y = 0; - sr.w = dst->w; - } - - if(dstrect) - dr = *dstrect; - else - dr.x = dr.y = 0; - - i = srcrect->h; - sy0 = srcrect->y; - dy0 = dstrect->y + dstrect->h - 1; - while(i--) - { - sr.y = sy0 + i; - dr.y = dy0 - i; - sr.h = 1; - if(SDL_BlitSurface(fake_screen, &sr, dst, &dr) < 0) - return -1; - } - return 0; -} - - -static __inline__ void _BlitGL_single(glSDL_TexInfo *txi, - float x1, float y1, float x2, float y2, - int dx1, float dy1, float dx2, float dy2, - unsigned char alpha) -{ - /* Select texture */ - if(!txi->textures) - return; - if(-1 == txi->texture[0]) - return; - gl_texture(txi->texture[0]); - - glBegin(GL_QUADS); - glColor4ub(255, 255, 255, alpha); - glTexCoord2f(x1, y1); - glVertex2i(dx1, dy1); - glTexCoord2f(x2, y1); - glVertex2i(dx2, dy1); - glTexCoord2f(x2, y2); - glVertex2i(dx2, dy2); - glTexCoord2f(x1, y2); - glVertex2i(dx1, dy2); - glEnd(); -} - -static void _BlitGL_htile(glSDL_TexInfo *txi, - float x1, float y1, float x2, float y2, - int dx1, float dy1, float dx2, float dy2, - unsigned char alpha, float texscale) -{ - float tileh = (float)txi->tileh * texscale; - float tile = floor(x1); /* / 1.0 */ - float texsize = (float)txi->texsize; - int tex = (int)tile / txi->tilespertex; - float yo = ((int)tile % txi->tilespertex) * tileh; - - /* Select texture */ - if(tex >= txi->textures) - return; - if(-1 == txi->texture[tex]) - return; - gl_texture(txi->texture[tex]); - - glBegin(GL_QUADS); - while(1) - { - int thisdx1, thisdx2; - float thisx1 = x1 - tile; - float thisx2 = x2 - tile; - - /* Stop condition */ - if(tile >= x2) - break; - - /* Maybe select next texture? */ - if(yo + tileh > 1.0) - { - ++tex; - glEnd(); - if(tex >= txi->textures) - return; - if(-1 == txi->texture[tex]) - return; - gl_texture(txi->texture[tex]); - yo = 0.0; - glBegin(GL_QUADS); - } - - /* Left clip to current tile */ - if(thisx1 < 0.0) - { - thisdx1 = dx1 - (int)(thisx1 * texsize); - thisx1 = 0.0; - } - else - thisdx1 = dx1; - - /* Right clip to current tile */ - if(thisx2 > 1.0) - { - thisdx2 = dx2 - (int)((thisx2 - 1.0) * texsize); - thisx2 = 1.0; - } - else - thisdx2 = dx2; - - glColor4ub(255, 255, 255, alpha); - glTexCoord2f(thisx1, yo + y1); - glVertex2i(thisdx1, dy1); - glTexCoord2f(thisx2, yo + y1); - glVertex2i(thisdx2, dy1); - glTexCoord2f(thisx2, yo + y2); - glVertex2i(thisdx2, dy2); - glTexCoord2f(thisx1, yo + y2); - glVertex2i(thisdx1, dy2); - - tile += 1.0; - yo += tileh; - } - glEnd(); -} - -static void _BlitGL_vtile(glSDL_TexInfo *txi, - float x1, float y1, float x2, float y2, - int dx1, float dy1, float dx2, float dy2, - unsigned char alpha, float texscale) -{ - float tilew = (float)txi->tilew * texscale; - float tile = floor(y1); - float texsize = (float)txi->texsize; - float xo = tile * tilew; - int tex = ((int)tile * txi->tilew + txi->tilew-1) / txi->texsize; - - /* Select texture */ - if(tex >= txi->textures) - return; - if(-1 == txi->texture[tex]) - return; - gl_texture(txi->texture[tex]); - - glBegin(GL_QUADS); - while(1) - { - int newtex; - int thisdy1, thisdy2; - float thisy1 = y1 - tile; - float thisy2 = y2 - tile; - - /* Stop condition */ - if(tile >= y2) - break; - - /* Maybe select next texture? */ - newtex = ((int)tile * txi->tilew + txi->tilew-1) / - txi->texsize; - if(newtex != tex) - { - tex = newtex; - glEnd(); - if(tex >= txi->textures) - return; - if(-1 == txi->texture[tex]) - return; - gl_texture(txi->texture[tex]); - xo = 0.0; - glBegin(GL_QUADS); - } - - /* Left clip to current tile */ - if(thisy1 < 0.0) - { - thisdy1 = dy1 - (int)(thisy1 * texsize); - thisy1 = 0.0; - } - else - thisdy1 = dy1; - - /* Right clip to current tile */ - if(thisy2 > 1.0) - { - thisdy2 = dy2 - (int)((thisy2 - 1.0) * texsize); - thisy2 = 1.0; - } - else - thisdy2 = dy2; - - glColor4ub(255, 255, 255, alpha); - glTexCoord2f(xo + x1, thisy1); - glVertex2i(dx1, thisdy1); - glTexCoord2f(xo + x2, thisy1); - glVertex2i(dx2, thisdy1); - glTexCoord2f(xo + x2, thisy2); - glVertex2i(dx2, thisdy2); - glTexCoord2f(xo + x1, thisy2); - glVertex2i(dx1, thisdy2); - - tile += 1.0; - xo += tilew; - } - glEnd(); -} - -static int _glSDL_BlitGL(SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect) -{ - glSDL_TexInfo *txi; - float x1, y1, x2, y2; - int dx1, dy1, dx2, dy2; - float texscale; - unsigned char alpha; - if(!src || !dst) - return -1; - - /* Cull off-screen blits. */ - if(dstrect) - { - if(dstrect->x > dst->w) - return 0; - if(dstrect->y > dst->h) - return 0; - if(srcrect) - { - if(dstrect->x + srcrect->w < 0) - return 0; - if(dstrect->y + srcrect->h < 0) - return 0; - } - else - { - if(dstrect->x + src->w < 0) - return 0; - if(dstrect->y + src->h < 0) - return 0; - } - } - - /* Make sure we have a source with a valid texture */ - glSDL_UploadSurface(src); - txi = glSDL_GetTexInfo(src); - - /* Set up blending */ - if(src->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY)) - { - gl_blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gl_do_blend(1); - } - else - gl_do_blend(0); - - /* Enable texturing */ - gl_do_texture(1); - - /* Calculate texcoords */ - if(!srcrect) - srcrect = &txi->virt; - texscale = 1.0 / (float)txi->texsize; - x1 = (float)srcrect->x * texscale; - y1 = (float)srcrect->y * texscale; - x2 = (float)(srcrect->x+srcrect->w) * texscale; - y2 = (float)(srcrect->y+srcrect->h) * texscale; - - /* Calculate screen coords. */ - dx2 = srcrect->w * (float)txi->lw / (float)txi->virt.w; - dy2 = srcrect->h * (float)txi->lh / (float)txi->virt.h; - if(dstrect) - { - dx1 = dstrect->x; - dy1 = dstrect->y; - /* - * FIXME: dstrect should be filled in with the *clipped* - * rect for full SDL compatibility. This hack - * might break some apps... - */ - dstrect->w = dx2; - dstrect->h = dy2; - } - else - dx1 = dy1 = 0; - dx2 += dx1; - dy2 += dy1; - - /* - * Note that we actually *prevent* the use of "full surface alpha" - * and alpha channel in combination - to stay SDL 2D compatible. - */ - if((src->flags & SDL_SRCALPHA) && - (!src->format->Amask || (src->flags & SDL_SRCCOLORKEY))) - alpha = src->format->alpha; - else - alpha = 255; - - /* Render! */ - switch(txi->tilemode) - { - case GLSDL_TM_SINGLE: - _BlitGL_single(txi, x1, y1, x2, y2, - dx1, dy1, dx2, dy2, - alpha); - break; - case GLSDL_TM_HORIZONTAL: - _BlitGL_htile(txi, x1, y1, x2, y2, - dx1, dy1, dx2, dy2, - alpha, texscale); - break; - case GLSDL_TM_VERTICAL: - _BlitGL_vtile(txi, x1, y1, x2, y2, - dx1, dy1, dx2, dy2, - alpha, texscale); - break; - case GLSDL_TM_HUGE: - /* TODO */ - break; - } - - return 0; -} - - -int glSDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect) -{ - SDL_Surface *vs; - if(!src || !dst) - return -1; - - /* - * Figure out what to do: - * Not using glSDL: SDL_BlitSurface() - * screen->screen: _glSDL_BlitFromGL() + _glSDL_BlitGL() - * surface->screen: _glSDL_BlitGL() - * screen->surface: _glSDL_BlitFromGL() - * surface->surface: SDL_BlitSurface() - */ - if(!USING_GLSDL) - return SDL_BlitSurface(src, srcrect, dst, dstrect); - - vs = SDL_GetVideoSurface(); - if(src == fake_screen) - src = vs; - if(dst == fake_screen) - dst = vs; - if(src == vs) - { - if(dst == vs) - { -/* -FIXME: Any OpenGL extensions for this...? -*/ - _glSDL_BlitFromGL(srcrect, fake_screen, dstrect); - return _glSDL_BlitGL(fake_screen, srcrect, - dst, dstrect); - } - else - { - return _glSDL_BlitFromGL(srcrect, dst, dstrect); - } - } - else - { - if(dst == vs) - { - return _glSDL_BlitGL(src, srcrect, - dst, dstrect); - } - else - { - glSDL_Invalidate(dst, dstrect); - return SDL_BlitSurface(src, srcrect, dst, dstrect); - } - } -} - - -int glSDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color) -{ - SDL_Surface *vs = SDL_GetVideoSurface(); - int dx1, dy1, dx2, dy2; - Uint32 r, g, b; - - /* - * Some ugly reverse conversion for compatibility... - * (We must do this before losing the dst pointer, - * as the pixel formats of the screen and the - * fake_screen may differ!) - */ - r = color & dst->format->Rmask; - r = r >> dst->format->Rshift; - r = r << dst->format->Rloss; - - g = color & dst->format->Gmask; - g = g >> dst->format->Gshift; - g = g << dst->format->Gloss; - - b = color & dst->format->Bmask; - b = b >> dst->format->Bshift; - b = b << dst->format->Bloss; - - if(dst == fake_screen) - dst = vs; - - if(vs != dst) - glSDL_Invalidate(dst, dstrect); - - if((vs != dst) || !USING_GLSDL) - return SDL_FillRect(dst, dstrect, color); - - gl_do_texture(0); - gl_do_blend(0); - - if(!dstrect) - dstrect = &dst->clip_rect; - - dx1 = dstrect->x; - dy1 = dstrect->y; - dx2 = dx1 + dstrect->w; - dy2 = dy1 + dstrect->h; - - glBegin(GL_QUADS); - glColor3ub(r, g, b); - glVertex2i(dx1, dy1); - glVertex2i(dx2, dy1); - glVertex2i(dx2, dy2); - glVertex2i(dx1, dy2); - glEnd(); - - return 0; -} - - -SDL_Surface *glSDL_DisplayFormat(SDL_Surface *surface) -{ - SDL_Surface *s, *tmp; - if(USING_GLSDL) - { - int use_rgba = (surface->flags & SDL_SRCCOLORKEY) || - ((surface->flags & SDL_SRCALPHA) && - surface->format->Amask); - if(use_rgba) - tmp = SDL_ConvertSurface(surface, &_RGBAfmt, SDL_SWSURFACE); - else - tmp = SDL_ConvertSurface(surface, &_RGBfmt, SDL_SWSURFACE); - if(!tmp) - return NULL; - GLSDL_FIX_SURFACE(tmp); - SDL_SetAlpha(tmp, 0, 0); - - if(surface->flags & SDL_SRCCOLORKEY) - { - /* - * We drop colorkey data here, but we have to, - * or we'll run into trouble when converting, - * in particular from indexed color formats. - */ - SDL_SetColorKey(tmp, SDL_SRCCOLORKEY, - surface->format->colorkey); - _key2alpha(tmp); - } - SDL_SetColorKey(tmp, 0, 0); - - if(use_rgba) - s = _CreateRGBASurface(surface->w, surface->h); - else - s = _CreateRGBSurface(surface->w, surface->h); - if(!s) - { - glSDL_FreeSurface(tmp); - return NULL; - } - SDL_BlitSurface(tmp, NULL, s, NULL); - glSDL_FreeSurface(tmp); - - if(surface->flags & SDL_SRCALPHA) - SDL_SetAlpha(s, SDL_SRCALPHA, - surface->format->alpha); - return s; - } - else - { - s = SDL_DisplayFormat(surface); - if(s) - GLSDL_FIX_SURFACE(s); - return s; - } -} - - -SDL_Surface *glSDL_DisplayFormatAlpha(SDL_Surface *surface) -{ - SDL_Surface *s, *tmp; - if(USING_GLSDL) - { - tmp = SDL_ConvertSurface(surface, &_RGBAfmt, SDL_SWSURFACE); - if(!tmp) - return NULL; - GLSDL_FIX_SURFACE(tmp); - - SDL_SetAlpha(tmp, 0, 0); - SDL_SetColorKey(tmp, 0, 0); - s = _CreateRGBASurface(surface->w, surface->h); - if(!s) - { - glSDL_FreeSurface(tmp); - return NULL; - } - SDL_BlitSurface(tmp, NULL, s, NULL); - glSDL_FreeSurface(tmp); - - if(surface->flags & SDL_SRCCOLORKEY) - { - SDL_SetColorKey(s, SDL_SRCCOLORKEY, - surface->format->colorkey); - _key2alpha(s); - } - if(surface->flags & SDL_SRCALPHA) - SDL_SetAlpha(s, SDL_SRCALPHA, - surface->format->alpha); - return s; - } - else - { - s = SDL_DisplayFormatAlpha(surface); - if(s) - GLSDL_FIX_SURFACE(s); - return s; - } -} - - -SDL_Surface *glSDL_ConvertSurface - (SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags) -{ - SDL_Surface *s = SDL_ConvertSurface(src, fmt, flags); - if(s) - GLSDL_FIX_SURFACE(s); - return s; -} - - -SDL_Surface *glSDL_CreateRGBSurface - (Uint32 flags, int width, int height, int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) -{ - SDL_Surface *s = SDL_CreateRGBSurface(flags, width, height, depth, - Rmask, Gmask, Bmask, Amask); - if(s) - GLSDL_FIX_SURFACE(s); - return s; -} - - -SDL_Surface *glSDL_CreateRGBSurfaceFrom(void *pixels, - int width, int height, int depth, int pitch, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask) -{ - SDL_Surface *s = SDL_CreateRGBSurfaceFrom(pixels, - width, height, depth, pitch, - Rmask, Gmask, Bmask, Amask); - if(s) - GLSDL_FIX_SURFACE(s); - return s; -} - - -SDL_Surface *glSDL_LoadBMP(const char *file) -{ - SDL_Surface *s = SDL_LoadBMP(file); - if(s) - GLSDL_FIX_SURFACE(s); - return s; -} - - -int glSDL_SaveBMP(SDL_Surface *surface, const char *file) -{ - SDL_Rect r; - SDL_Surface *buf; - SDL_Surface *screen = SDL_GetVideoSurface(); - - if(!USING_GLSDL) - return SDL_SaveBMP(surface, file); - - if((surface != screen) && (surface != fake_screen)) - return SDL_SaveBMP(surface, file); - - buf = _CreateRGBSurface(fake_screen->w, fake_screen->h); - - r.x = 0; - r.y = 0; - r.w = fake_screen->w; - r.h = fake_screen->h; - if(_glSDL_BlitFromGL(&r, buf, &r) < 0) - return -1; - - return SDL_SaveBMP(buf, file); - - glSDL_FreeSurface(buf); -} - - - - -/*---------------------------------------------------------- - glSDL specific API extensions -----------------------------------------------------------*/ - -void glSDL_Invalidate(SDL_Surface *surface, SDL_Rect *area) -{ - glSDL_TexInfo *txi; - if(!surface) - return; - txi = glSDL_GetTexInfo(surface); - if(!txi) - return; - if(!area) - { - txi->invalid_area.x = 0; - txi->invalid_area.y = 0; - txi->invalid_area.w = surface->w; - txi->invalid_area.h = surface->h; - return; - } - txi->invalid_area = *area; -} - - -void glSDL_SetLogicSize(SDL_Surface *surface, int w, int h) -{ - SDL_Rect r; - glSDL_TexInfo *txi; - if(!IS_GLSDL_SURFACE(surface)) - return; - - txi = glSDL_GetTexInfo(surface); - - txi->lw = w; - txi->lh = h; - - if((SDL_GetVideoSurface() != surface) && (fake_screen != surface)) - return; - - r.x = r.y = 0; - r.w = w; - r.h = h; - glSDL_SetClipRect(surface, &r); - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glTranslatef(0.0f, 0.0f, 0.0f); - - glDisable(GL_DEPTH_TEST); - glDisable(GL_CULL_FACE); - - gl_reset(); -} - - -/* Upload a single texture. */ -static int _UploadTexture(SDL_Surface *datasurf, glSDL_TexInfo *txi, int tex) -{ - int bpp = datasurf->format->BytesPerPixel; - - glGenTextures(1, (unsigned int *)&txi->texture[tex]); - glBindTexture(GL_TEXTURE_2D, txi->texture[tex]); - glPixelStorei(GL_UNPACK_ROW_LENGTH, datasurf->pitch / - datasurf->format->BytesPerPixel); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, 0, - datasurf->format->Amask ? GL_RGBA8 : GL_RGB8, - txi->texsize, txi->texsize, 0, - datasurf->format->Amask ? GL_RGBA : GL_RGB, - GL_UNSIGNED_BYTE, NULL); - DBG(_print_glerror(1)); - - switch(txi->tilemode) - { - case GLSDL_TM_SINGLE: - case GLSDL_TM_HORIZONTAL: - { - /* Image tiled horizontally, or not at all */ - int fromx = txi->tilew * tex * txi->tilespertex; - int toy = 0; - while(toy + txi->tileh <= txi->texsize) - { - int thistw; - thistw = datasurf->w - fromx; - if(thistw > txi->tilew) - thistw = txi->tilew; - else if(thistw <= 0) - break; - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, toy, - thistw, txi->tileh, - datasurf->format->Amask ? GL_RGBA : GL_RGB, - GL_UNSIGNED_BYTE, - (char *)datasurf->pixels + bpp * fromx); - DBG4(_print_glerror(2)); - fromx += txi->tilew; - toy += txi->tileh; - glFlush(); - } - break; - } - case GLSDL_TM_VERTICAL: - { - /* Image tiled vertically */ - int fromy = txi->tileh * tex * txi->tilespertex; - int tox = 0; - while(tox + txi->tilew <= txi->texsize) - { - int thisth; - thisth = datasurf->h - fromy; - if(thisth > txi->tileh) - thisth = txi->tileh; - else if(thisth <= 0) - break; - glTexSubImage2D(GL_TEXTURE_2D, 0, tox, 0, - txi->tilew, thisth, - datasurf->format->Amask ? GL_RGBA : GL_RGB, - GL_UNSIGNED_BYTE, - (char *)datasurf->pixels + datasurf->pitch * fromy); - DBG4(_print_glerror(3)); - fromy += txi->tileh; - tox += txi->tilew; - glFlush(); - } - break; - } - case GLSDL_TM_HUGE: - /* "Huge" image - tiled both ways */ - return -4; - break; - } - return 0; -} - - -int glSDL_UploadSurface(SDL_Surface *surface) -{ - SDL_Surface *datasurf = surface; - glSDL_TexInfo *txi; - int i; - - /* - * For now, we just assume that *every* texture needs - * conversion before uploading. - */ - - /* If there's no TexInfo, add one. */ - if(!IS_GLSDL_SURFACE(surface)) - glSDL_AddTexInfo(surface); - - txi = glSDL_GetTexInfo(surface); - - /* No partial updates implemented yet... */ - if(txi->invalid_area.w) - glSDL_UnloadSurface(surface); - else - { - int missing = 0; - if(txi->textures) - { - for(i = 0; i < txi->textures; ++i) - if(-1 == txi->texture[i]) - { - missing = 1; - break; - } - if(!missing) - return 0; /* They're already there! */ - } - } - - if(txi->texsize > maxtexsize) - { - fprintf(stderr, "glSDL: INTERNAL ERROR: Too large texture!\n"); - return -1; /* This surface wasn't tiled properly... */ - } - - /* - * Kludge: Convert if not of preferred RGB or RGBA format. - * - * Conversion should only be done when *really* needed. - * That is, it should rarely have to be done with OpenGL - * 1.2+. - * - * Besides, any surface that's been SDL_DisplayFormat()ed - * should already be in the best known OpenGL format - - * preferably one that makes DMA w/o conversion possible. - */ - if(_FormatIsOk(surface)) - datasurf = surface; - else - { - DBG(fprintf(stderr, "glSDL: WARNING: On-the-fly conversion performed!\n")); - if(surface->format->Amask) - datasurf = glSDL_DisplayFormatAlpha(surface); - else - datasurf = glSDL_DisplayFormat(surface); - if(!datasurf) - return -2; - } - - for(i = 0; i < txi->textures; ++i) - if(_UploadTexture(datasurf, txi, i) < 0) - return -3; - - if(datasurf != surface) - glSDL_FreeSurface(datasurf); - return 0; -} - - -static void _UnloadTexture(glSDL_TexInfo *txi) -{ - int i; - for(i = 0; i < txi->textures; ++i) - glDeleteTextures(1, (unsigned int *)&txi->texture[i]); - memset(&txi->invalid_area, 0, sizeof(txi->invalid_area)); -} - - -void glSDL_UnloadSurface(SDL_Surface *surface) -{ - if(!IS_GLSDL_SURFACE(surface)) - return; - - _UnloadTexture(glSDL_GetTexInfo(surface)); -} - - -SDL_Surface *glSDL_IMG_Load(const char *file) -{ - SDL_Surface *s; - s = IMG_Load(file); - if(s) - GLSDL_FIX_SURFACE(s); - return s; -} - -#endif /* HAVE_OPENGL */ diff --git a/glSDL.h b/glSDL.h deleted file mode 100644 index 5d5d649..0000000 --- a/glSDL.h +++ /dev/null @@ -1,325 +0,0 @@ -/*(LGPL) ------------------------------------------------------------- - glSDL 0.6 - SDL 2D API on top of OpenGL ------------------------------------------------------------- - * (c) David Olofson, 2001-2003 - * This code is released under the terms of the GNU LGPL. - */ - -#ifndef _GLSDL_H_ -#define _GLSDL_H_ - -/* - * If you don't use GNU autotools or similar, uncomment this to - * compile with OpenGL enabled: -#define HAVE_OPENGL - */ - -/* We're still using SDL datatypes here - we just add some stuff. */ -#include -#include - -#ifndef HAVE_OPENGL - -/* Fakes to make glSDL code compile with SDL. */ -#define SDL_GLSDL 0 -#define LOGIC_W(s) ( (s)->w ) -#define LOGIC_H(s) ( (s)->h ) -#define GLSDL_FIX_SURFACE(s) - -#else /* HAVE_OPENGL */ - -#include "begin_code.h" -#ifdef __cplusplus -extern "C" { -#endif - -#if (SDL_MAJOR_VERSION <= 1) && (SDL_MINOR_VERSION <= 2) && \ - (SDL_PATCHLEVEL < 5) -#warning glSDL: Using SDL version 1.2.5 or later is strongly recommended! -#endif - -/*---------------------------------------------------------- - SDL style API -----------------------------------------------------------*/ - -typedef enum glSDL_TileModes -{ - GLSDL_TM_SINGLE, - GLSDL_TM_HORIZONTAL, - GLSDL_TM_VERTICAL, - GLSDL_TM_HUGE -} glSDL_TileModes; - - -typedef struct glSDL_TexInfo -{ - /* Size of surface in logic screen pixels */ - int lw, lh; - - int textures; - int *texture; - int texsize; /* width/height of OpenGL texture */ - glSDL_TileModes tilemode; - int tilew, tileh; /* At least one must equal texsize! */ - int tilespertex; - SDL_Rect virt; /* Total size of assembled surface */ - - /* Area of surface to download when/after unlocking */ - SDL_Rect invalid_area; -} glSDL_TexInfo; - -#define GLSDL_FIX_SURFACE(s) (s)->unused1 = 0; -#define IS_GLSDL_SURFACE(s) ((s) && glSDL_GetTexInfo(s)) - -#define LOGIC_W(s) ( IS_GLSDL_SURFACE(s) ? TEXINFO(s)->lw : (s)->w ) -#define LOGIC_H(s) ( IS_GLSDL_SURFACE(s) ? TEXINFO(s)->lh : (s)->h ) - -#define SDL_GLSDL 0x00100000 /* Create an OpenGL 2D rendering context */ - - -/* - * Wraps SDL_SetVideoMode(), and adds support for the SDL_GLSDL flag. - * - * If 'flags' contains SDL_GLSDL, glSDL_SetVideoMode() sets up a "pure" - * OpenGL rendering context for use with the glSDL_ calls. - * - * SDL can be closed as usual (using SDL_ calls), but you should call - * glSDL_Quit() (kludge) to allow glSDL to clean up it's internal stuff. - */ -SDL_Surface *glSDL_SetVideoMode(int width, int height, int bpp, Uint32 flags); -void glSDL_Quit(void); - -void glSDL_QuitSubSystem(Uint32 flags); - -/* Replaces SDL_Quit() entirely, when using the override defines */ -void _glSDL_FullQuit(void); - -SDL_Surface *glSDL_GetVideoSurface(void); - -void glSDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects); -void glSDL_UpdateRect(SDL_Surface *screen, Sint32 x, Sint32 y, Uint32 w, Uint32 h); - -/* - * Works like SDL_Flip(), but may also perform enqueued blits. - * (That is, it's possible that the implementation renders - * *nothing* until glSDL_Flip() is called.) - */ -int glSDL_Flip(SDL_Surface *screen); - -void glSDL_FreeSurface(SDL_Surface *surface); - -int glSDL_LockSurface(SDL_Surface *surface); -void glSDL_UnlockSurface(SDL_Surface *surface); - -/* - * Like the respective SDL functions, although they ignore - * SDL_RLEACCEL, as it makes no sense in this context. - */ -int glSDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key); -int glSDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha); - -/* - * Sets up clipping for the screen, or a SDL_Surface. - * - * Note that this function takes both SDL_Surfaces and - * glSDL_Surfaces. - */ -SDL_bool glSDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect); - -int glSDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, - SDL_Surface *dst, SDL_Rect *dstrect); - -int glSDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color); - -/* - * Convert the given surface into a SDL_Surface (if it isn't - * one already), and makes sure that the underlying SDL_Surface - * is of a pixel format suitable for fast texture downloading. - * - * Note that you *only* have to use this function if you want - * fast pixel access to surfaces (ie "procedural textures"). - * Any surfaces that aren't converted will be downloaded - * automatically upon the first call to glSDL_BlitSurface(), - * but if conversion is required, it will be required for - * every glSDL_UnlockSurface() call. - * - * IMPORTANT: - * You *can* pass an SDL_Surface directly to this function, - * and it will try to deal with it nicely. However, this - * requires that a temporary SDL_Surface is created, and - * this surface is cached only until the texture memory is - * needed for new surfaces. - */ -SDL_Surface *glSDL_DisplayFormat(SDL_Surface *surface); -SDL_Surface *glSDL_DisplayFormatAlpha(SDL_Surface *surface); - -SDL_Surface *glSDL_ConvertSurface - (SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags); -SDL_Surface *glSDL_CreateRGBSurface - (Uint32 flags, int width, int height, int depth, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); -SDL_Surface *glSDL_CreateRGBSurfaceFrom(void *pixels, - int width, int height, int depth, int pitch, - Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask); -SDL_Surface *glSDL_LoadBMP(const char *file); -int glSDL_SaveBMP(SDL_Surface *surface, const char *file); - - - -/*---------------------------------------------------------- - glSDL specific API extensions -----------------------------------------------------------*/ - -/* - * Invalidate part of a texture. - * - * This function can be used either between calls to - * glSDL_LockSurface() and glSDL_UnlockSurface(), or before - * calling glSDL_DownloadSurface(). - * - * In either case, it causes only the specified area to be - * downloaded when unlocking the surface, or calling - * glSDL_UnlockSurface(), respectively. - * - * Note that if this function is not used, glSDL assumes that - * the entire surface has to be updated. (That is, it's safe - * to ignore this function - it's "just a performance hack.") - * - * Passing a rectangle with zero height or width cancels the - * downloading when/after unlocking the surface. Use if you - * just want to read the texture, but feel like being nice and - * obeying SDL_MUSTLOCK() - which is a good idea, as things - * may change... - * - * Passing NULL for the 'area' argument results in the entire - * surface being invalidated. - * - * NOTE: This function does NOT perform clipping! Weird or - * even Bad Things may happen if you specify areas - * that protrude outside the edges of the actual - * surface. - */ -void glSDL_Invalidate(SDL_Surface *surface, SDL_Rect *area); - -/* - * Set logic width and height of a surface. - * - * When used on the screen surface: - * Changes the OpenGL view coordinate system without - * changing the screen resolution. This is used to - * decouple the rendering coordinate system from the - * physical screen resolution, which is needed to - * achieve sub-pixel resolution without switching to - * float coords. - * - * When used on a SDL_Surface: - * Normally, surfaces are scaled so that one pixel on - * the surface corresponds to one pixel in the current - * logic screen resolution. This function makes it - * possible to change that relation by specifying the - * desired size of the rendered texture in the current - * logic screen resolution. - * - * BUG? WRT blitting *to* surfaces, this call affects - * the screen surface and other surfaces differently! - * As of now, coordinates are *always* treated as real - * pixels when blitting to normal surfaces, whereas - * they are scaled when blitting to the screen. - * - * Of course, this function can also be "abused" just to - * make rendering code independent of screen resolution, - * although that can potentially *lower* accuracy, if the - * real resolution is higher than the logic resolution. - */ -void glSDL_SetLogicSize(SDL_Surface *surface, int w, int h); - -/* - * Make sure that the texture of the specified surface is up - * to date in OpenGL texture memory. - * - * This can be used together with glSDL_UnloadSurface() to - * implement custom texture caching schemes. - * - * Returns 0 on success, or a negative value if something - * went wrong. - */ -int glSDL_UploadSurface(SDL_Surface *surface); - -/* - * Free the texture space used by the specified surface. - * - * Normally, glSDL should download textures when needed, and - * unload the oldest (in terms of use) surfaces, if it runs out - * of texture space. - */ -void glSDL_UnloadSurface(SDL_Surface *surface); - - -/* - * Get the clSDL_TexInfo struct associated with a surface. - */ -glSDL_TexInfo *glSDL_GetTexInfo(SDL_Surface *surface); - - - -#ifdef __cplusplus -} -#endif -#include "close_code.h" - -/* Some ugly "overriding"... */ -#ifndef _GLSDL_NO_REDEFINES_ -/* - * You *always* need to lock and unlock a glSDL surface in - * order to get glSDL to update the OpenGL texture! - */ -#undef SDL_MUSTLOCK -#define SDL_MUSTLOCK(surface) \ - (surface->offset || \ - ((surface->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_RLEACCEL)) != 0) || \ - IS_GLSDL_SURFACE(surface)) - -#define SDL_SetVideoMode glSDL_SetVideoMode -#define SDL_GetVideoSurface glSDL_GetVideoSurface -#define SDL_Quit _glSDL_FullQuit -#define SDL_QuitSubSystem glSDL_QuitSubSystem -#define SDL_UpdateRects glSDL_UpdateRects -#define SDL_UpdateRect glSDL_UpdateRect -#define SDL_Flip glSDL_Flip -#define SDL_FreeSurface glSDL_FreeSurface -#define SDL_LockSurface glSDL_LockSurface -#define SDL_UnlockSurface glSDL_UnlockSurface -#define SDL_SetColorKey glSDL_SetColorKey -#define SDL_SetAlpha glSDL_SetAlpha -#define SDL_SetClipRect glSDL_SetClipRect -#undef SDL_BlitSurface -#define SDL_BlitSurface glSDL_BlitSurface -#define SDL_FillRect glSDL_FillRect -#define SDL_DisplayFormat glSDL_DisplayFormat -#define SDL_DisplayFormatAlpha glSDL_DisplayFormatAlpha -#define SDL_ConvertSurface glSDL_ConvertSurface -#define SDL_CreateRGBSurface glSDL_CreateRGBSurface -#define SDL_CreateRGBSurfaceFrom glSDL_CreateRGBSurfaceFrom -#undef SDL_AllocSurface -#define SDL_AllocSurface glSDL_CreateRGBSurface -#undef SDL_LoadBMP -#define SDL_LoadBMP glSDL_LoadBMP -#undef SDL_SaveBMP -#define SDL_SaveBMP glSDL_SaveBMP -#define IMG_Load(x) glSDL_IMG_Load(x) -#endif - -/* Some extra overloading for common external lib calls... */ -#include -#ifdef __cplusplus -extern "C" { -#endif -SDL_Surface *glSDL_IMG_Load(const char *file); -#ifdef __cplusplus -} -#endif - -#endif /* HAVE_OPENGL */ - -#endif diff --git a/sofont.c b/sofont.c index 2281d2e..7c818df 100644 --- a/sofont.c +++ b/sofont.c @@ -1,6 +1,6 @@ #include #include "sofont.h" -#include "string.h" +#include struct _SOFONT { @@ -318,7 +318,7 @@ SoFont_load (SoFont * font, IIM_Surface * FontSurface) font->max_i = START_CHAR + i - 1; font->background = SoFontGetPixel (font->picture->surf, 0, font->height); - SDL_SetColorKey (font->picture->surf, SDL_SRCCOLORKEY, font->background); + //SDL_SetColorKey (font->picture->surf, SDL_SRCCOLORKEY, font->background); SoFont_CleanSurface (font); font->CharPos = (int *) malloc (i * sizeof (int)); @@ -385,7 +385,7 @@ void SoFont_Refresh(SoFont * font) { font->background = SoFontGetPixel (font->picture->surf, 0, font->height); - SDL_SetColorKey (font->picture->surf, SDL_SRCCOLORKEY, font->background); + //SDL_SetColorKey (font->picture->surf, SDL_SRCCOLORKEY, font->background); SoFont_CleanSurface (font); }