From 413aeb099b2982e60bc095a7e404fd2fefff4d7f Mon Sep 17 00:00:00 2001 From: Neils Wagenaar Date: Wed, 6 Oct 2004 14:20:31 +0000 Subject: [PATCH] Expended OpenGL rendering with 16, 24 and 32 bit texture types. --- src/sdlemu_opengl.c | 291 ++++++++++++++++++++++++++++++++++++++++---- src/video.cpp | 22 ++-- 2 files changed, 280 insertions(+), 33 deletions(-) diff --git a/src/sdlemu_opengl.c b/src/sdlemu_opengl.c index 6b92f18..41f92a7 100644 --- a/src/sdlemu_opengl.c +++ b/src/sdlemu_opengl.c @@ -16,6 +16,14 @@ * 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); } diff --git a/src/video.cpp b/src/video.cpp index bfc3097..4d3ffea 100644 --- a/src/video.cpp +++ b/src/video.cpp @@ -34,8 +34,12 @@ bool InitVideo(void) if (vjs.useOpenGL) { - mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL; - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + +// mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL; + mainSurfaceFlags = SDL_OPENGL; + } else { @@ -71,6 +75,7 @@ bool InitVideo(void) // Create the primary SDL display (16 BPP, 5/5/5 RGB format) surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, (vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL), +// 16, 63488, 2016, 31, 0); 16, 0x7C00, 0x03E0, 0x001F, 0); if (surface == NULL) @@ -82,7 +87,7 @@ bool InitVideo(void) if (vjs.useOpenGL) //Should make another setting here, for either linear or nearest (instead of just picking one) //And we have! ;-) - sdlemu_init_opengl(surface, 1/*method*/, 2/*size*/, vjs.glFilter/*texture type (linear, nearest)*/); + sdlemu_init_opengl(surface, 1/*method*/, 2/*size*/, vjs.glFilter/*texture type (linear, nearest)*/, NULL); // Initialize Joystick support under SDL if (vjs.useJoystick) @@ -161,8 +166,9 @@ void ResizeScreen(uint32 width, uint32 height) char window_title[256]; SDL_FreeSurface(surface); - surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 16, - 0x7C00, 0x03E0, 0x001F, 0); + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, +// 16, 63488, 2016, 31, 0); + 16, 0x7C00, 0x03E0, 0x001F, 0); if (surface == NULL) { @@ -178,7 +184,7 @@ void ResizeScreen(uint32 width, uint32 height) //Err, we should only do this *if* we changed from PAL to NTSC or vice versa... !!! FIX !!! mainSurface = SDL_SetVideoMode(VIRTUAL_SCREEN_WIDTH * 2, height * 2, 16, mainSurfaceFlags); // This seems to work well for resizing (i.e., changes in the pixel width)... - sdlemu_resize_texture(surface, mainSurface, vjs.glFilter); + sdlemu_resize_texture(surface, mainSurface, vjs.glFilter, NULL); } else { @@ -209,8 +215,8 @@ uint32 GetSDLScreenPitch(void) void ToggleFullscreen(void) { //NOTE: This does *NOT* work with OpenGL rendering! !!! FIX !!! - if (vjs.useOpenGL) - return; // Until we can fix it... +// if (vjs.useOpenGL) +// return; // Until we can fix it... vjs.fullscreen = !vjs.fullscreen; mainSurfaceFlags &= ~SDL_FULLSCREEN; -- 2.37.2