]> git.jsancho.org Git - lugaru.git/blobdiff - Source/OpenGL_Windows.cpp
Dynamically load the GL.
[lugaru.git] / Source / OpenGL_Windows.cpp
index 8ce1a4ce34e88a150d2c357054a4601a096d30e6..15073ce19546940855d9e54b1a598907c24bcdaf 100644 (file)
@@ -25,6 +25,8 @@
     static bool load_image(const char * fname, TGAImageRec & tex);
     static bool load_png(const char * fname, TGAImageRec & tex);
     static bool load_jpg(const char * fname, TGAImageRec & tex);
+    static bool save_image(const char * fname);
+    static bool save_png(const char * fname);
 #endif
 
 // ADDED GWC
@@ -132,6 +134,43 @@ typedef struct tagPOINT {
 #endif
 
 #if USE_SDL
+#define GL_FUNC(ret,fn,params,call,rt) \
+    extern "C" { \
+        static ret GLAPIENTRY (*p##fn) params = NULL; \
+        ret GLAPIENTRY fn params { rt p##fn call; } \
+    }
+#include "glstubs.h"
+#undef GL_FUNC
+
+static bool lookup_glsym(const char *funcname, void **func, const char *libname)
+{
+    *func = SDL_GL_GetProcAddress(funcname);
+    if (*func == NULL)
+    {
+        fprintf(stderr, "Failed to find OpenGL symbol \"%s\" in \"%s\"\n",
+                 funcname, libname);
+        return false;
+    }
+    return true;
+}
+
+static bool lookup_all_glsyms(const char *libname)
+{
+    bool retval = true;
+    #define GL_FUNC(ret,fn,params,call,rt) \
+        if (!lookup_glsym(#fn, (void **) &p##fn, libname)) retval = false;
+    #include "glstubs.h"
+    #undef GL_FUNC
+    return retval;
+}
+
+static void GLAPIENTRY glDeleteTextures_doNothing(GLsizei n, const GLuint *textures)
+{
+    // no-op.
+}
+
+
+
 void sdlGetCursorPos(POINT *pt)
 {
     int x, y;
@@ -796,9 +835,20 @@ Boolean SetUp (Game & game)
             fprintf(stderr, "SDL_Init() failed: %s\n", SDL_GetError());
             return false;
         }
+
+        const char *libname = "libGL.so.1";  // !!! FIXME: Linux specific!
+        if (SDL_GL_LoadLibrary(libname) == -1)
+        {
+            fprintf(stderr, "SDL_GL_LoadLibrary(\"%s\") failed: %s\n",
+                    libname, SDL_GetError());
+            return false;
+        }
+
+        if (!lookup_all_glsyms(libname))
+            return false;
     }
 
-    Uint32 sdlflags = SDL_OPENGL;
+    Uint32 sdlflags = SDL_OPENGL;  // !!! FIXME: SDL_FULLSCREEN?
     SDL_WM_SetCaption("Lugaru", "lugaru");
     SDL_ShowCursor(0);
     if (SDL_SetVideoMode(kContextWidth, kContextHeight, 0, sdlflags) == NULL)
@@ -807,6 +857,8 @@ Boolean SetUp (Game & game)
         return false;
     }
 
+
+
 #elif (defined WIN32)
        //------------------------------------------------------------------
        // create window
@@ -1181,6 +1233,12 @@ void CleanUp (void)
 
 #if USE_SDL
     SDL_Quit();
+    #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;
 
 #elif (defined WIN32)
        if (hRC)
@@ -1252,7 +1310,8 @@ int main (void)
                        //ofstream os("log.txt");
                        //os.close();
 
-                       SetUp (game);
+                       if (!SetUp (game))
+                return 42;
 
                        while (!gDone&&!game.quit&&(!game.tryquit||!game.registered))
                        {
@@ -2204,7 +2263,7 @@ int main (void)
 
                free(f);
         #else
-        STUBBED("Non-DevIL screenshot");
+        save_image(fname);
         #endif
        }
 
@@ -2246,7 +2305,7 @@ static bool load_jpg(const char *file_name, TGAImageRec &tex)
     struct my_error_mgr jerr;
     JSAMPROW buffer[1];                /* Output row buffer */
     int row_stride;            /* physical row width in output buffer */
-    FILE *infile = fopen(file_name, "rb")
+    FILE *infile = fopen(file_name, "rb");
 
     if (infile == NULL)
         return false;
@@ -2286,6 +2345,7 @@ static bool load_jpg(const char *file_name, TGAImageRec &tex)
     return true;
 }
 
+
 /* stolen from public domain example.c code in libpng distribution. */
 static bool load_png(const char *file_name, TGAImageRec &tex)
 {
@@ -2370,53 +2430,95 @@ static bool load_png(const char *file_name, TGAImageRec &tex)
     retval = true;
 
 png_done:
-   png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
-   fclose(fp);
-   return (retval);
+    png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
+    if (fp)
+        fclose(fp);
+    return (retval);
+}
+
+
+static bool save_image(const char *file_name)
+{
+    char *ptr = strrchr(file_name, '.');
+    if (ptr)
+    {
+        if (stricmp(ptr+1, "png") == 0)
+            return save_png(file_name);
+    }
+
+    STUBBED("Unsupported image type");
+    return false;
 }
 
-#if 0
-void save_png(char *file_name /* , ... other image information ... */)
+
+static bool save_png(const char *file_name)
 {
-   FILE *fp;
-   png_structp png_ptr;
-   png_infop info_ptr;
-
-   /* open the file */
-   fp = fopen(file_name, "wb");
-   if (fp == NULL)
-      return (ERROR);
-
-   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
-   if (png_ptr == NULL)
-   {
-      fclose(fp);
-      return (ERROR);
-   }
-
-   info_ptr = png_create_info_struct(png_ptr);
-   if (info_ptr == NULL)
-   {
-      fclose(fp);
-      png_destroy_write_struct(&png_ptr,  png_infopp_NULL);
-      return (ERROR);
-   }
-
-   if (setjmp(png_jmpbuf(png_ptr)))
-   {
-      /* If we get here, we had a problem reading the file */
-      fclose(fp);
-      png_destroy_write_struct(&png_ptr, &info_ptr);
-      return (ERROR);
-   }
-
-   png_init_io(png_ptr, fp);
-   png_write_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
-   png_destroy_write_struct(&png_ptr, &info_ptr);
-   fclose(fp);
-   return (OK);
+    FILE *fp = NULL;
+    png_structp png_ptr = NULL;
+    png_infop info_ptr = NULL;
+    bool retval = false;
+
+    fp = fopen(file_name, "wb");
+    if (fp == NULL)
+        return false;
+
+    png_bytep *row_pointers = new png_bytep[kContextHeight];
+    png_bytep screenshot = new png_byte[kContextWidth * kContextHeight * 3];
+    if ((!screenshot) || (!row_pointers))
+        goto save_png_done;
+
+    glGetError();
+    glReadPixels(0, 0, kContextWidth, kContextHeight,
+                 GL_RGB, GL_UNSIGNED_BYTE, screenshot);
+    if (glGetError() != GL_NO_ERROR)
+        goto save_png_done;
+
+    for (int i = 0; i < kContextHeight; i++)
+        row_pointers[i] = screenshot + ((kContextWidth * ((kContextHeight-1) - i)) * 3);
+
+    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    if (png_ptr == NULL)
+        goto save_png_done;
+
+    info_ptr = png_create_info_struct(png_ptr);
+    if (info_ptr == NULL)
+        goto save_png_done;
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+        goto save_png_done;
+
+    png_init_io(png_ptr, fp);
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+        goto save_png_done;
+
+    png_set_IHDR(png_ptr, info_ptr, kContextWidth, kContextHeight,
+                 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+                 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+    png_write_info(png_ptr, info_ptr);
+
+    if (setjmp(png_jmpbuf(png_ptr)))
+        goto save_png_done;
+
+       png_write_image(png_ptr, row_pointers);
+
+       if (setjmp(png_jmpbuf(png_ptr)))
+        goto save_png_done;
+
+    png_write_end(png_ptr, NULL);
+    retval = true;
+
+save_png_done:
+    png_destroy_write_struct(&png_ptr, &info_ptr);
+    delete[] screenshot;
+    delete[] row_pointers;
+    if (fp)
+        fclose(fp);
+    if (!retval)
+        unlink(ConvertFileName(file_name));
+    return retval;
 }
-#endif
 
 #endif