]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/sdlemu_opengl.c
Expended OpenGL rendering with 16, 24 and 32 bit texture types.
[virtualjaguar] / src / sdlemu_opengl.c
index 6b92f1858fa3024442311bb96966cf13d9c135c9..41f92a77f3cad8becb77b746f2dd6c07e764a46f 100644 (file)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+/*
+    Version 1.0.001 - 4-10-2004
+    
+    - Added support for 16, 24 and 32 bit textures * new *;
+    - Added support for 16, 24 and 32 bit texture rendering *new*;
+
+*/
 
 #include "sdlemu_opengl.h"
 
@@ -23,6 +31,7 @@ static SDL_Surface *texture      = 0;
 static GLuint       texid        = 0;
 static GLfloat      texcoord[4];
 static unsigned int glFilter;
+static unsigned int texturebpp  = 0; // 16, 24 or 32 bpp
 
 static inline int power_of_two(int input)
 {
@@ -34,15 +43,24 @@ static inline int power_of_two(int input)
        return value;
 }
 
-void sdlemu_init_opengl(SDL_Surface * src, int texturetype, float size, int filter)
+void sdlemu_init_opengl(SDL_Surface * src, int texturetype, float size, int filter, int src_bpp)
 {
        int w, h;
-
+       Uint32 rmask, gmask, bmask, amask;
+
+       // We allow the developer to set its own texture bpp. But if the value is NULL or
+       // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
+       if ( (src_bpp != NULL) && ( (src_bpp == 16) || (src_bpp == 24) || (src_bpp == 32) ) )
+       texturebpp = src_bpp;
+    else
+       texturebpp = src->format->BitsPerPixel;
+       
        printf("\nOpenGL driver information :\n");
        printf("\n");
-       printf("Vendor:            %s\n", glGetString(GL_VENDOR));
-       printf("Renderer:          %s\n", glGetString(GL_RENDERER));
-       printf("Version:           %s\n", glGetString(GL_VERSION));
+       printf("Vendor:             %s\n", glGetString(GL_VENDOR));
+       printf("Renderer:           %s\n", glGetString(GL_RENDERER));
+       printf("Version:            %s\n", glGetString(GL_VERSION));
+       printf("OpenGL Texture BPP: %d\n", texturebpp);
        printf("OpenGL drawmethod: ");
 
        switch (texturetype)
@@ -59,22 +77,95 @@ void sdlemu_init_opengl(SDL_Surface * src, int texturetype, float size, int filt
 
        // Texture width/height should be power of 2
        // So, find the largest power of two that will contain both the width and height
-       w = power_of_two(src->w);
-       h = power_of_two(src->h);
+       // w = power_of_two(src->w);
+       // h = power_of_two(src->h);
+       w = 512;
+       h = 512;
+
+       switch ( texturebpp )
+       {
+    case 16:
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+       
+//         rmask = 0xff000000;
+//         gmask = 0x00ff0000;
+//         bmask = 0x0000ff00;
+//         amask = 0x00000000;
+
+        rmask = 0x0000;
+               gmask = 0x0000;
+               bmask = 0x0000;
+               amask = 0x0000;
+
+       #else
+
+//         rmask = 0x000000ff;
+//         gmask = 0x0000ff00;
+//         bmask = 0x00ff0000;
+//         amask = 0x00000000;
+
+      rmask = 0x0000;
+      gmask = 0x0000;
+      bmask = 0x0000;
+      amask = 0x0000;
+
+    #endif
+        
+        break;
+    case 24:
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+           rmask = 0x00ff0000;
+               gmask = 0x0000ff00;
+               bmask = 0x000000ff;
+               amask = 0x00000000;
+       #else
+           rmask = 0x000000ff;
+           gmask = 0x0000ff00;
+           bmask = 0x00ff0000;
+           amask = 0x00000000;
+    #endif
+       break;
+    case 32: 
+    default:
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+           rmask = 0xff000000;
+               gmask = 0x00ff0000;
+               bmask = 0x0000ff00;
+               amask = 0x000000ff;
+       #else
+           rmask = 0x000000ff;
+           gmask = 0x0000ff00;
+           bmask = 0x00ff0000;
+           amask = 0xff000000;
+    #endif
+        break;
+    }    
 
        // create texture surface
-       texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
-       #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
+       texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
+/*     
+    #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
                0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
        #else
                0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
        #endif
+*/
 
        // setup 2D gl environment
-       glPushAttrib(GL_ENABLE_BIT);
-       glDisable(GL_DEPTH_TEST);
+       //glPushAttrib(GL_ENABLE_BIT);
+       //glDisable(GL_DEPTH_TEST);
+       //glDisable(GL_CULL_FACE);
+       //glEnable(GL_TEXTURE_2D);
+
+       glDisable(GL_FOG);
+       glDisable(GL_LIGHTING);
        glDisable(GL_CULL_FACE);
+       glDisable(GL_DEPTH_TEST);
+       glDisable(GL_BLEND);
+       glDisable(GL_NORMALIZE);
+       glDisable(GL_ALPHA_TEST);
        glEnable(GL_TEXTURE_2D);
+       glBlendFunc (GL_SRC_ALPHA, GL_ONE);
 
        glViewport(0, 0, src->w * size, src->h * size);
 
@@ -109,20 +200,62 @@ void sdlemu_init_opengl(SDL_Surface * src, int texturetype, float size, int filt
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     }
+    
+    switch ( texturebpp )
+    {
+    case 16:
+           glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+        break;
+    case 24:
+           glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+        break;
+    case 32:
+    default:
+           glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        break;        
+    }    
 
-       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
 }
 
 void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
 {
+       //SDL_Rect rect = { 0, 0, src->w, src->h };
 
        // convert color-indexed surface to RGB texture
+       //SDL_BlitSurface(src, &rect, texture, &rect);
+       //glFlush();
+       
        SDL_BlitSurface(src, NULL, texture, NULL);
 
+//     printf("Rmask - src : %d\n", src->format->Rmask);
+//     printf("Gmask - src : %d\n", src->format->Gmask);
+//     printf("Bmask - src : %d\n", src->format->Bmask);
+//     printf("Amask - src : %d\n", src->format->Amask);
+
+//     printf("Rmask - texture : %d\n", texture->format->Rmask);
+//     printf("Gmask - texture : %d\n", texture->format->Gmask);
+//     printf("Bmask - texture : %d\n", texture->format->Bmask);
+//     printf("Amask - texture : %d\n", texture->format->Amask);
+
        // Texturemap complete texture to surface so we have free scaling 
-       // and antialiasing 
-       glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
-               GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
+       // and antialiasing
+    switch ( texturebpp )
+    {
+    case 16:
+        // GL_UNSIGNED_SHORT_5_6_5
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
+                       GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->pixels);
+        break;
+    case 24:
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
+                       GL_RGB, GL_UNSIGNED_BYTE, texture->pixels);
+        break;
+    case 32:
+    default:
+        glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
+                       GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
+        break;
+    }     
        
        switch (texturetype)
        {
@@ -146,8 +279,11 @@ void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
                                glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w, dst->h, 0);
                glEnd();
        }
-
+       
+//  glFlush();
        SDL_GL_SwapBuffers();    
+//     glFinish();
+
 }
 
 void sdlemu_close_opengl(void)
@@ -163,30 +299,121 @@ void sdlemu_close_opengl(void)
 // but, at the moment, it doesn't...
 // Now it does...!
 //
-void sdlemu_resize_texture(SDL_Surface * src, SDL_Surface * dst, int filter)
+void sdlemu_resize_texture(SDL_Surface * src, SDL_Surface * dst, int filter, int src_bpp)
 {
        // Texture width/height should be power of 2
        // So, find the largest power of two that will contain both the width and height
-       int w = power_of_two(src->w), h = power_of_two(src->h);
-
+       //int w = power_of_two(src->w), h = power_of_two(src->h);
+       int w = 512, h = 512;
+       Uint32 rmask, gmask, bmask, amask;
+       
+       // We allow the developer to set its own texture bpp. But if the value is NULL or
+       // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
+       if ( (src_bpp != NULL) && ( (src_bpp == 16) || (src_bpp == 24) || (src_bpp == 32) ) )
+       texturebpp = src_bpp;
+    else
+       texturebpp = src->format->BitsPerPixel;
+       
        // Delete old texture (if allocated)
        if (texture)
                SDL_FreeSurface(texture);
 
        // create texture surface
-//NOTE: Seems the byte order here *is* important! (Perhaps only for 32 BPP?)
-       texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
+       //NOTE: Seems the byte order here *is* important! (Perhaps only for 32 BPP?)
+       //
+       // NOTE : Nope! Not any more. We can now producte textures based upon 16, 24 or 32 bpp.
+       switch ( texturebpp )
+       {
+    case 16:
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+
+//         rmask = 0xff000000;
+//             gmask = 0x00ff0000;
+//             bmask = 0x0000ff00;
+//             amask = 0x00000000;
+
+        rmask = 0x0000;
+               gmask = 0x0000;
+               bmask = 0x0000;
+               amask = 0x0000;
+               
+       #else
+
+//         rmask = 0x000000ff;
+//         gmask = 0x0000ff00;
+//         bmask = 0x00ff0000;
+//         amask = 0x00000000;
+
+        rmask = 0x0000;
+               gmask = 0x0000;
+               bmask = 0x0000;
+               amask = 0x0000;
+
+    #endif
+        break;
+    case 24:
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+           rmask = 0x00ff0000;
+               gmask = 0x0000ff00;
+               bmask = 0x000000ff;
+               amask = 0x00000000;
+       #else
+           rmask = 0x000000ff;
+           gmask = 0x0000ff00;
+           bmask = 0x00ff0000;
+           amask = 0x00000000;
+    #endif
+       break;
+    case 32: 
+    default:
+    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
+           rmask = 0xff000000;
+               gmask = 0x00ff0000;
+               bmask = 0x0000ff00;
+               amask = 0x000000ff;
+       #else
+           rmask = 0x000000ff;
+           gmask = 0x0000ff00;
+           bmask = 0x00ff0000;
+           amask = 0xff000000;
+    #endif
+        break;
+    }    
+
+       // create texture surface
+       texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
+/*     
+    #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
+               0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
+       #else
+               0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
+       #endif
+*/
+       
+/* 
+    texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
        #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
                0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
        #else
                0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
        #endif
-
+*/
        // setup 2D gl environment
-       glPushAttrib(GL_ENABLE_BIT);
-       glDisable(GL_DEPTH_TEST);
+       //glPushAttrib(GL_ENABLE_BIT);
+       //glDisable(GL_DEPTH_TEST);
+       //glDisable(GL_CULL_FACE);
+       //glEnable(GL_TEXTURE_2D);
+
+       glDisable(GL_FOG);
+       glDisable(GL_LIGHTING);
        glDisable(GL_CULL_FACE);
+       glDisable(GL_DEPTH_TEST);
+       glDisable(GL_BLEND);
+       glDisable(GL_NORMALIZE);
+       glDisable(GL_ALPHA_TEST);
        glEnable(GL_TEXTURE_2D);
+       glBlendFunc (GL_SRC_ALPHA, GL_ONE);
 
        glViewport(0, 0, dst->w, dst->h);
 
@@ -222,5 +449,19 @@ void sdlemu_resize_texture(SDL_Surface * src, SDL_Surface * dst, int filter)
           glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     }
 
-       glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
+    switch ( texturebpp )
+    {
+    case 16:
+           glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+        break;
+    case 24:
+           glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+        break;
+    case 32:
+    default:
+           glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        break;        
+    }    
+
+       //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
 }