X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FOpenGL_Windows.cpp;h=6d684ba1d2cbe4e413aebc9264cf924459d2d065;hb=cd043e3f9e26c2b3406b40a354c2840941e9db7f;hp=a0ace20b7ac291148281b2d202ae3841fc8c20bb;hpb=24004d6ab1e68faaf85ece11b566449997da5013;p=lugaru.git diff --git a/Source/OpenGL_Windows.cpp b/Source/OpenGL_Windows.cpp index a0ace20..6d684ba 100644 --- a/Source/OpenGL_Windows.cpp +++ b/Source/OpenGL_Windows.cpp @@ -3,47 +3,30 @@ Copyright (C) 2003, 2010 - Wolfire Games This file is part of Lugaru. -Lugaru is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -as published by the Free Software Foundation; either version 2 -of the License, or (at your option) any later version. +Lugaru is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. -This program is distributed in the hope that it will be useful, +Lugaru is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -See the GNU General Public License for more details. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +along with Lugaru. If not, see . */ #ifdef WIN32 -#define UINT8 WIN32API_UINT8 -#define UINT16 WIN32API_UINT16 -#define boolean WIN32API_boolean #include -#undef UINT8 -#undef UINT16 -#undef boolean #endif - - #include "Game.h" -extern "C" { -#include "zlib.h" -#include "png.h" -#ifdef WIN32 -#define INT32 INT32_jpeg -#include "jpeglib.h" -#undef INT32 -#else -#include "jpeglib.h" -#endif -} + +#include +#include +#include using namespace Game; @@ -80,6 +63,7 @@ extern float slomofreq; #include #include #include +#include #include "gamegl.h" #include "MacCompatibility.h" #include "Settings.h" @@ -89,18 +73,11 @@ extern float slomofreq; #include "win-res/resource.h" #endif +extern SDL_Window *sdlwindow; + using namespace std; -SDL_Rect **resolutions = NULL; -static SDL_Rect rect_1024_768 = { 0, 0, 1024, 768 }; -static SDL_Rect rect_800_600 = { 0, 0, 800, 600 }; -static SDL_Rect rect_640_480 = { 0, 0, 640, 480 }; -static SDL_Rect *hardcoded_resolutions[] = { - &rect_1024_768, - &rect_800_600, - &rect_640_480, - NULL -}; +set> resolutions; Boolean SetUp (); void DoUpdate (); @@ -114,6 +91,7 @@ void CleanUp (void); #pragma warning(disable: 4273) #endif +#ifndef __MINGW32__ // FIXME: Temporary workaround for GL-8 #define GL_FUNC(ret,fn,params,call,rt) \ extern "C" { \ static ret (GLAPIENTRY *p##fn) params = NULL; \ @@ -121,6 +99,7 @@ void CleanUp (void); } #include "glstubs.h" #undef GL_FUNC +#endif // __MINGW32__ #ifdef _MSC_VER #pragma warning(pop) @@ -139,17 +118,21 @@ static bool lookup_glsym(const char *funcname, void **func) static bool lookup_all_glsyms(void) { bool retval = true; +#ifndef __MINGW32__ // FIXME: Temporary workaround for GL-8 #define GL_FUNC(ret,fn,params,call,rt) \ if (!lookup_glsym(#fn, (void **) &p##fn)) retval = false; #include "glstubs.h" #undef GL_FUNC +#endif // __MINGW32__ return retval; } +#ifndef __MINGW32__ // FIXME: Temporary workaround for GL-8 static void GLAPIENTRY glDeleteTextures_doNothing(GLsizei n, const GLuint *textures) { // no-op. } +#endif // __MINGW32__ #ifdef MessageBox #undef MessageBox @@ -163,10 +146,8 @@ int kContextHeight; Boolean gDone = false; -#ifndef __MINGW32__ static int _argc = 0; static char **_argv = NULL; -#endif bool cmdline(const char *cmd) { @@ -194,7 +175,7 @@ void initGL() glDisable( GL_ALPHA_TEST); glDisable( GL_BLEND); glDisable( GL_DEPTH_TEST); - // glDisable( GL_DITHER); + //glDisable( GL_DITHER); glDisable( GL_FOG); glDisable( GL_LIGHTING); glDisable( GL_LOGIC_OP); @@ -215,13 +196,13 @@ void initGL() glClearDepth( 1.0f); glDepthFunc( GL_LEQUAL); glDepthMask( GL_TRUE); - // glDepthRange( FRONT_CLIP, BACK_CLIP); + //glDepthRange( FRONT_CLIP, BACK_CLIP); glEnable( GL_DEPTH_TEST); glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glCullFace( GL_FRONT); glEnable( GL_CULL_FACE); glEnable( GL_LIGHTING); -// glEnable( GL_LIGHT_MODEL_AMBIENT); + //glEnable( GL_LIGHT_MODEL_AMBIENT); glEnable( GL_DITHER); glEnable( GL_COLOR_MATERIAL); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -236,47 +217,49 @@ void initGL() } } -static void toggleFullscreen() +void toggleFullscreen() { - if (!SDL_WM_ToggleFullScreen(SDL_GetVideoSurface())) { - SDL_Surface* screen = SDL_GetVideoSurface(); - Uint32 flags = screen->flags; - screen = SDL_SetVideoMode(0, 0, 0, flags ^ SDL_FULLSCREEN); - if (!screen) - screen = SDL_SetVideoMode(0, 0, 0, flags); - if (!screen) - exit(1); - //reload opengl state - initGL(); - Texture::reloadAll(); - if (text) - text->BuildFont(); - if (firstload) { - screentexture = 0; - LoadScreenTexture(); - } - screentexture2 = 0; + fullscreen = !fullscreen; + Uint32 flags = SDL_GetWindowFlags(sdlwindow); + if (flags & SDL_WINDOW_FULLSCREEN) { + flags &= ~SDL_WINDOW_FULLSCREEN; + } else { + flags |= SDL_WINDOW_FULLSCREEN; } + SDL_SetWindowFullscreen(sdlwindow, flags); } -static void sdlEventProc(const SDL_Event &e) +static SDL_bool sdlEventProc(const SDL_Event &e) { switch (e.type) { - case SDL_MOUSEMOTION: - deltah += e.motion.xrel; - deltav += e.motion.yrel; + case SDL_QUIT: + return SDL_FALSE; + + case SDL_WINDOWEVENT: + if (e.window.event == SDL_WINDOWEVENT_CLOSE) { + return SDL_FALSE; + } break; - case SDL_KEYDOWN: - if ((e.key.keysym.sym == SDLK_g) && - (e.key.keysym.mod & KMOD_CTRL) && - !(SDL_GetVideoSurface()->flags & SDL_FULLSCREEN) ) { - SDL_WM_GrabInput( ((SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON) ? SDL_GRAB_OFF : SDL_GRAB_ON) ); - } else if ( (e.key.keysym.sym == SDLK_RETURN) && (e.key.keysym.mod & KMOD_ALT) ) { - toggleFullscreen(); - } + case SDL_MOUSEMOTION: + deltah += e.motion.xrel; + deltav += e.motion.yrel; + break; + + case SDL_KEYDOWN: + if ((e.key.keysym.scancode == SDL_SCANCODE_G) && + (e.key.keysym.mod & KMOD_CTRL)) { + SDL_bool mode = SDL_TRUE; + if ((SDL_GetWindowFlags(sdlwindow) & SDL_WINDOW_FULLSCREEN) == 0) + mode = (SDL_GetWindowGrab(sdlwindow) ? SDL_FALSE : SDL_TRUE); + SDL_SetWindowGrab(sdlwindow, mode); + SDL_SetRelativeMouseMode(mode); + } else if ( (e.key.keysym.scancode == SDL_SCANCODE_RETURN) && (e.key.keysym.mod & KMOD_ALT) ) { + toggleFullscreen(); + } break; } + return SDL_TRUE; } @@ -287,8 +270,6 @@ static Point gMidPoint; Boolean SetUp () { - char string[10]; - LOGFUNC; osx = 0; @@ -296,7 +277,6 @@ Boolean SetUp () texdetail = 4; slomospeed = 0.25; slomofreq = 8012; - numplayers = 1; DefaultSettings(); @@ -319,84 +299,97 @@ Boolean SetUp () return false; } - SDL_Rect **res = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_OPENGL); - if ( (res == NULL) || (res == ((SDL_Rect **) - 1)) || (res[0] == NULL) || (res[0]->w < 640) || (res[0]->h < 480) ) - res = hardcoded_resolutions; - - // reverse list (it was sorted biggest to smallest by SDL)... - int count; - for (count = 0; res[count]; count++) { - if ((res[count]->w < 640) || (res[count]->h < 480)) - break; // sane lower limit. + for (int displayIdx = 0; displayIdx < SDL_GetNumVideoDisplays(); ++displayIdx) { + for (int i = 0; i < SDL_GetNumDisplayModes(displayIdx); ++i) { + SDL_DisplayMode mode; + if (SDL_GetDisplayMode(displayIdx, i, &mode) == -1) + continue; + if ((mode.w < 640) || (mode.h < 480)) + continue; // sane lower limit. + pair resolution(mode.w, mode.h); + resolutions.insert(resolution); + } } - static SDL_Rect *resolutions_block = NULL; - resolutions_block = (SDL_Rect*) realloc(resolutions_block, sizeof (SDL_Rect) * count); - resolutions = (SDL_Rect**) realloc(resolutions, sizeof (SDL_Rect *) * (count + 1)); - if ((resolutions_block == NULL) || (resolutions == NULL)) { + if (resolutions.empty()) { + const std::string error = "No suitable video resolutions found."; + cerr << error << endl; + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Lugaru init failed!", error.c_str(), NULL); SDL_Quit(); - fprintf(stderr, "Out of memory!\n"); return false; } - resolutions[count--] = NULL; - for (int i = 0; count >= 0; i++, count--) { - memcpy(&resolutions_block[count], res[i], sizeof (SDL_Rect)); - resolutions[count] = &resolutions_block[count]; - } - if (cmdline("showresolutions")) { - printf("Resolutions we think are okay:\n"); - for (int i = 0; resolutions[i]; i++) - printf(" %d x %d\n", (int) resolutions[i]->w, (int) resolutions[i]->h); + printf("Available resolutions:\n"); + for (auto resolution = resolutions.begin(); resolution != resolutions.end(); resolution++) { + printf(" %d x %d\n", (int) resolution->first, (int) resolution->second); + } } - Uint32 sdlflags = SDL_OPENGL; - - if (!cmdline("windowed")) - sdlflags |= SDL_FULLSCREEN; - - SDL_WM_SetCaption("Lugaru", "Lugaru"); - - SDL_ShowCursor(0); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 1); -#if SDL_VERSION_ATLEAST(1, 2, 10) - SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, vblsync); -#endif - if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) { - fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + Uint32 sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; + if ((fullscreen || cmdline("fullscreen")) && !cmdline("windowed")) { + fullscreen = 1; + sdlflags |= SDL_WINDOW_FULLSCREEN; + } + if (!cmdline("nomousegrab")) + sdlflags |= SDL_WINDOW_INPUT_GRABBED; + + sdlwindow = SDL_CreateWindow("Lugaru", SDL_WINDOWPOS_CENTERED_DISPLAY(0), SDL_WINDOWPOS_CENTERED_DISPLAY(0), + kContextWidth, kContextHeight, sdlflags); + + if (!sdlwindow) { + fprintf(stderr, "SDL_CreateWindow() failed: %s\n", SDL_GetError()); fprintf(stderr, "forcing 640x480...\n"); kContextWidth = 640; kContextHeight = 480; - if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) { - fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + sdlwindow = SDL_CreateWindow("Lugaru", SDL_WINDOWPOS_CENTERED_DISPLAY(0), SDL_WINDOWPOS_CENTERED_DISPLAY(0), + kContextWidth, kContextHeight, sdlflags); + if (!sdlwindow) { + fprintf(stderr, "SDL_CreateWindow() failed: %s\n", SDL_GetError()); fprintf(stderr, "forcing 640x480 windowed mode...\n"); - sdlflags &= ~SDL_FULLSCREEN; - if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL) { - fprintf(stderr, "SDL_SetVideoMode() failed: %s\n", SDL_GetError()); + sdlflags &= ~SDL_WINDOW_FULLSCREEN; + sdlwindow = SDL_CreateWindow("Lugaru", SDL_WINDOWPOS_CENTERED_DISPLAY(0), SDL_WINDOWPOS_CENTERED_DISPLAY(0), + kContextWidth, kContextHeight, sdlflags); + + if (!sdlwindow) { + fprintf(stderr, "SDL_CreateWindow() failed: %s\n", SDL_GetError()); return false; } } } - int dblbuf = 0; - if ((SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &dblbuf) == -1) || (!dblbuf)) { - fprintf(stderr, "Failed to get double buffered GL context!\n"); + SDL_GLContext glctx = SDL_GL_CreateContext(sdlwindow); + if (!glctx) { + fprintf(stderr, "SDL_GL_CreateContext() failed: %s\n", SDL_GetError()); SDL_Quit(); return false; } + SDL_GL_MakeCurrent(sdlwindow, glctx); + if (!lookup_all_glsyms()) { + fprintf(stderr, "Missing required OpenGL functions.\n"); SDL_Quit(); return false; } - if (!cmdline("nomousegrab")) - SDL_WM_GrabInput(SDL_GRAB_ON); + int dblbuf = 0; + if ((SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &dblbuf) == -1) || (!dblbuf)) + { + fprintf(stderr, "Failed to get a double-buffered context.\n"); + SDL_Quit(); + return false; + } + if (SDL_GL_SetSwapInterval(-1) == -1) // try swap_tear first. + SDL_GL_SetSwapInterval(1); + + SDL_ShowCursor(0); + if (!cmdline("nomousegrab")) + SDL_SetRelativeMouseMode(SDL_TRUE); initGL(); @@ -411,6 +404,12 @@ Boolean SetUp () newscreenwidth = screenwidth; newscreenheight = screenheight; + /* If saved resolution is not in the list, add it to the list (so that it’s selectable in the options) */ + pair startresolution(width,height); + if (resolutions.find(startresolution) == resolutions.end()) { + resolutions.insert(startresolution); + } + InitGame(); return true; @@ -446,26 +445,29 @@ void DoFrameRate (int update) AbsoluteTime currTime = UpTime (); double deltaTime = (float) AbsoluteDeltaToDuration (currTime, frametime); - if (0 > deltaTime) // if negative microseconds + if (0 > deltaTime) // if negative microseconds deltaTime /= -1000000.0; - else // else milliseconds + else // else milliseconds deltaTime /= 1000.0; multiplier = deltaTime; - if (multiplier < .001) multiplier = .001; - if (multiplier > 10) multiplier = 10; - if (update) frametime = currTime; // reset for next time interval + if (multiplier < .001) + multiplier = .001; + if (multiplier > 10) + multiplier = 10; + if (update) + frametime = currTime; // reset for next time interval deltaTime = (float) AbsoluteDeltaToDuration (currTime, time); - if (0 > deltaTime) // if negative microseconds + if (0 > deltaTime) // if negative microseconds deltaTime /= -1000000.0; - else // else milliseconds + else // else milliseconds deltaTime /= 1000.0; frames++; - if (0.001 <= deltaTime) { // has update interval passed + if (0.001 <= deltaTime) { // has update interval passed if (update) { - time = currTime; // reset for next time interval + time = currTime; // reset for next time interval frames = 0; } } @@ -479,20 +481,26 @@ void DoUpdate () static float oldmult; DoFrameRate(1); - if (multiplier > .6)multiplier = .6; + if (multiplier > .6) + multiplier = .6; fps = 1 / multiplier; count = multiplier * sps; - if (count < 2)count = 2; + if (count < 2) + count = 2; realmultiplier = multiplier; multiplier *= gamespeed; - if (difficulty == 1)multiplier *= .9; - if (difficulty == 0)multiplier *= .8; - - if (loading == 4)multiplier *= .00001; - if (slomo && !mainmenu)multiplier *= slomospeed; + if (difficulty == 1) + multiplier *= .9; + if (difficulty == 0) + multiplier *= .8; + + if (loading == 4) + multiplier *= .00001; + if (slomo && !mainmenu) + multiplier *= slomospeed; oldmult = multiplier; multiplier /= (float)count; @@ -507,38 +515,38 @@ void DoUpdate () TickOnceAfter(); /* - Debug code to test how many channels were active on average per frame - static long frames = 0; - - static AbsoluteTime start = {0,0}; - AbsoluteTime currTime = UpTime (); - static int num_channels = 0; - - num_channels += OPENAL_GetChannelsPlaying(); - double deltaTime = (float) AbsoluteDeltaToDuration (currTime, start); - - if (0 > deltaTime) // if negative microseconds - deltaTime /= -1000000.0; - else // else milliseconds - deltaTime /= 1000.0; - - ++frames; - - if (deltaTime >= 1) - { - start = currTime; - float avg_channels = (float)num_channels / (float)frames; - - ofstream opstream("log.txt",ios::app); - opstream << "Average frame count: "; - opstream << frames; - opstream << " frames - "; - opstream << avg_channels; - opstream << " per frame.\n"; - opstream.close(); - - frames = 0; - num_channels = 0; - } + static long frames = 0; + + static AbsoluteTime start = {0,0}; + AbsoluteTime currTime = UpTime (); + static int num_channels = 0; + + num_channels += OPENAL_GetChannelsPlaying(); + double deltaTime = (float) AbsoluteDeltaToDuration (currTime, start); + + if (0 > deltaTime) // if negative microseconds + deltaTime /= -1000000.0; + else // else milliseconds + deltaTime /= 1000.0; + + ++frames; + + if (deltaTime >= 1) + { + start = currTime; + float avg_channels = (float)num_channels / (float)frames; + + ofstream opstream("log.txt",ios::app); + opstream << "Average frame count: "; + opstream << frames; + opstream << " frames - "; + opstream << avg_channels; + opstream << " per frame.\n"; + opstream.close(); + + frames = 0; + num_channels = 0; + } */ if ( stereomode == stereoNone ) { DrawGLScene(stereoCenter); @@ -556,12 +564,14 @@ void CleanUp (void) LOGFUNC; SDL_Quit(); +#ifndef __MINGW32__ // FIXME: Temporary workaround for GL-8 #define GL_FUNC(ret,fn,params,call,rt) p##fn = NULL; #include "glstubs.h" #undef GL_FUNC // cheat here...static destructors are calling glDeleteTexture() after // the context is destroyed and libGL unloaded by SDL_Quit(). pglDeleteTextures = glDeleteTextures_doNothing; +#endif // __MINGW32__ } @@ -569,7 +579,7 @@ void CleanUp (void) static bool IsFocused() { - return ((SDL_GetAppState() & SDL_APPINPUTFOCUS) != 0); + return ((SDL_GetWindowFlags(sdlwindow) & SDL_WINDOW_INPUT_FOCUS) != 0); } @@ -629,7 +639,6 @@ char *calcBaseDir(const char *argv0) char *retval; char *envr; - const char *ptr = strrchr((char *)argv0, '/'); if (strchr(argv0, '/')) { retval = strdup(argv0); if (retval) @@ -638,9 +647,11 @@ char *calcBaseDir(const char *argv0) } envr = getenv("PATH"); - if (!envr) return NULL; + if (!envr) + return NULL; envr = strdup(envr); - if (!envr) return NULL; + if (!envr) + return NULL; retval = findBinaryInPath(argv0, envr); free(envr); return(retval); @@ -671,10 +682,8 @@ static inline void chdirToAppPath(const char *argv0) int main(int argc, char **argv) { -#ifndef __MINGW32__ _argc = argc; _argv = argv; -#endif // !!! FIXME: we could use a Win32 API for this. --ryan. #ifndef WIN32 @@ -707,11 +716,10 @@ int main(int argc, char **argv) if (!waiting) { // message pump while ( SDL_PollEvent( &e ) ) { - if ( e.type == SDL_QUIT ) { + if (!sdlEventProc(e)) { gDone = true; break; } - sdlEventProc(e); } } @@ -725,12 +733,7 @@ int main(int argc, char **argv) } // game is not in focus, give CPU time to other apps by waiting for messages instead of 'peeking' - SDL_ActiveEvent evt; - SDL_WaitEvent((SDL_Event*)&evt); - if (evt.type == SDL_ACTIVEEVENT && evt.gain == 1) - gameFocused = true; - else if (evt.type == SDL_QUIT) - gDone = true; + SDL_WaitEvent(0); } } @@ -792,8 +795,8 @@ static bool load_image(const char *file_name, TGAImageRec &tex) struct my_error_mgr { - struct jpeg_error_mgr pub; /* "public" fields */ - jmp_buf setjmp_buffer; /* for return to caller */ + struct jpeg_error_mgr pub; /* "public" fields */ + jmp_buf setjmp_buffer; /* for return to caller */ }; typedef struct my_error_mgr * my_error_ptr; @@ -809,8 +812,8 @@ static bool load_jpg(const char *file_name, TGAImageRec &tex) { struct jpeg_decompress_struct cinfo; struct my_error_mgr jerr; - JSAMPROW buffer[1]; /* Output row buffer */ - int row_stride; /* physical row width in output buffer */ + JSAMPROW buffer[1]; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ FILE *infile = fopen(file_name, "rb"); if (infile == NULL) @@ -860,7 +863,6 @@ static bool load_png(const char *file_name, TGAImageRec &tex) png_infop info_ptr = NULL; png_uint_32 width, height; int bit_depth, color_type, interlace_type; - png_byte **rows = NULL; bool retval = false; png_byte **row_pointers = NULL; FILE *fp = fopen(file_name, "rb"); @@ -906,7 +908,7 @@ static bool load_png(const char *file_name, TGAImageRec &tex) png_byte *dst = tex.data; for (int i = height - 1; i >= 0; i--) { png_byte *src = row_pointers[i]; - for (int j = 0; j < width; j++) { + for (unsigned j = 0; j < width; j++) { dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2];