From 252928f87a00e5f7b189258b2316789d3696cd36 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Tue, 15 Apr 2003 01:32:16 +0000 Subject: Add patch #721194 - SDL/GL: hotswap_gfx_mode (win32 and MacOS) svn-id: r7012 --- backends/sdl/fb2opengl.h | 336 +++++++++++++++++++++++++++-------------------- backends/sdl/sdl_gl.cpp | 85 +++++++++--- 2 files changed, 261 insertions(+), 160 deletions(-) (limited to 'backends') diff --git a/backends/sdl/fb2opengl.h b/backends/sdl/fb2opengl.h index 844486d612..87f83b6f64 100644 --- a/backends/sdl/fb2opengl.h +++ b/backends/sdl/fb2opengl.h @@ -19,7 +19,7 @@ */ // FrameBuffer renderer in an OpenGL texture -// Andre Souza +// Andre Souza #include #include @@ -43,32 +43,45 @@ class FB2GL { private: + SDL_Surface *screen; // Framebuffer for 8 bpp - unsigned char ogl_fb[256][256]; - unsigned char ogl_fbb[256][64]; + unsigned char palettedFrameBuffer1[256][256]; + unsigned char palettedFrameBuffer2[256][64]; // Framebuffer for RGBA - unsigned char ogl_fb1[256][256][4]; - unsigned char ogl_fb2[256][64][4]; + unsigned char RGBAFrameBuffer1[256][256][4]; + unsigned char RGBAFrameBuffer2[256][64][4]; // Framebuffer for the blit function (SDL Blitting) - unsigned char fb1[256 * 256 * 4]; // Enough room for RGBA - unsigned char fb2[64 * 256 * 4]; // Enough room for RGBA + unsigned char *blitFrameBuffer1; + unsigned char *blitFrameBuffer2; // Texture(s) - GLuint texture; - GLuint textureb; + GLuint texture1; + GLuint texture2; // Display list - GLuint dlist; + GLuint displayList; // Color Table (256 colors, RGB) - char ogl_ctable[256][3]; - char ogl_temp_ctable[256][3]; // Support for OpenGL 1.1 + char colorTable[256][3]; + char tempColorTable[256][3]; // Support for OpenGL 1.1 char flags; - void maketex(); - void makedlist(int xf, int yf); + void makeTextures(); + void makeDisplayList(int xf, int yf); + public: - SDL_Surface *screen; + FB2GL() { flags = 0; screen = NULL; + blitFrameBuffer1 = (unsigned char *)RGBAFrameBuffer1; + blitFrameBuffer2 = (unsigned char *)RGBAFrameBuffer2; } + + SDL_Surface *getScreen() { + return screen; + }; + + void setScreen(SDL_Surface *s) { + screen = s; + }; + int init(int width, int height, int xfix, int yfix, char _flags); void update(void *fb, int width, int height, int pitch, int xskip, int yskip); void palette(int index, int r, int g, int b); @@ -77,9 +90,9 @@ class FB2GL { void display(); }; -void FB2GL::maketex() { - glGenTextures(0,&texture); - glBindTexture(GL_TEXTURE_2D,texture); +void FB2GL::makeTextures() { + glGenTextures(0,&texture1); + glBindTexture(GL_TEXTURE_2D,texture1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); @@ -93,15 +106,15 @@ void FB2GL::maketex() { */ if (flags & FB2GL_RGBA) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, ogl_fb1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, RGBAFrameBuffer1); } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX, 256, 256, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ogl_fb); + glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX, 256, 256, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, palettedFrameBuffer1); } if (flags & FB2GL_320) { - glGenTextures(1, &textureb); - glBindTexture(GL_TEXTURE_2D, textureb); + glGenTextures(1, &texture2); + glBindTexture(GL_TEXTURE_2D, texture2); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); @@ -116,57 +129,68 @@ void FB2GL::maketex() { if (flags & FB2GL_RGBA) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 256, 0, GL_RGBA, - GL_UNSIGNED_BYTE, ogl_fb2); + GL_UNSIGNED_BYTE, RGBAFrameBuffer2); } else { glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX, 64, 256, 0, GL_COLOR_INDEX, - GL_UNSIGNED_BYTE, ogl_fbb); + GL_UNSIGNED_BYTE, palettedFrameBuffer2); } } } -void FB2GL::makedlist(int xf, int yf) { +void FB2GL::makeDisplayList(int xf, int yf) { double xfix = (double)xf / 128; // 128 = 256/2 (half texture => 0.0 to 1.0) double yfix = (double)yf / 128; // End of 256x256 (from -1.0 to 1.0) double texend = (double)96 / 160; // 160=320/2 (== 0.0), 256-160=96. - if (glIsList(dlist)) - glDeleteLists(dlist, 1); + if (glIsList(displayList)) + glDeleteLists(displayList, 1); - dlist=glGenLists(1); - glNewList(dlist, GL_COMPILE); + displayList = glGenLists(1); + glNewList(displayList, GL_COMPILE); glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, texture); + glBindTexture(GL_TEXTURE_2D, texture1); if (!(flags & FB2GL_320)) { // Normal 256x256 glBegin(GL_QUADS); - glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, -1.0 - yfix); // upper left - glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0); // lower left - glTexCoord2f(1.0, 0.0); glVertex2f(1.0 + xfix, 1.0); // lower right - glTexCoord2f(1.0, 1.0); glVertex2f(1.0 + xfix, -1.0 - yfix); // upper right - glEnd(); + // upper left + glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, -1.0 - yfix); + // lower left + glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0); + // lower right + glTexCoord2f(1.0, 0.0); glVertex2f(1.0 + xfix, 1.0); + // upper right + glTexCoord2f(1.0, 1.0); glVertex2f(1.0 + xfix, -1.0 - yfix); glEnd(); } else { // 320x256 // First, the 256x256 texture glBegin(GL_QUADS); - glTexCoord2f(0.0, 1.0); glVertex2f( -1.0, -1.0 - yfix); // upper left - glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0); // lower left - glTexCoord2f(1.0, 0.0); glVertex2f(texend + xfix, 1.0); // lower right - glTexCoord2f(1.0, 1.0); glVertex2f(texend + xfix, -1.0 - yfix); // upper right + // upper left + glTexCoord2f(0.0, 1.0); glVertex2f( -1.0, -1.0 - yfix); + // lower left + glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0); + // lower right + glTexCoord2f(1.0, 0.0); glVertex2f(texend + xfix, 1.0); + // upper right + glTexCoord2f(1.0, 1.0); glVertex2f(texend + xfix, -1.0 - yfix); glEnd(); // 64x256 - glBindTexture(GL_TEXTURE_2D, textureb); + glBindTexture(GL_TEXTURE_2D, texture2); glBegin(GL_QUADS); - glTexCoord2f(0.0, 1.0); glVertex2f(texend + xfix, -1.0 - yfix); // upper left - glTexCoord2f(0.0, 0.0); glVertex2f(texend + xfix, 1.0); // lower left - glTexCoord2f(1.0, 0.0); glVertex2f(1.0 + xfix, 1.0); // lower right - glTexCoord2f(1.0, 1.0); glVertex2f(1.0 + xfix, -1.0 - yfix); // upper right + // upper left + glTexCoord2f(0.0, 1.0); glVertex2f(texend + xfix, -1.0 - yfix); + // lower left + glTexCoord2f(0.0, 0.0); glVertex2f(texend + xfix, 1.0); + // lower right + glTexCoord2f(1.0, 0.0); glVertex2f(1.0 + xfix, 1.0); + // upper right + glTexCoord2f(1.0, 1.0); glVertex2f(1.0 + xfix, -1.0 - yfix); glEnd(); } @@ -188,14 +212,14 @@ int FB2GL::init(int width, int height, int xfix, int yfix, char _flags) { (flags & FB2GL_FS? SDL_FULLSCREEN: 0)); } - warning("Screen BitsPerPixel: %d\n",screen->format->BitsPerPixel); +// warning("Screen BitsPerPixel: %d\n",screen->format->BitsPerPixel); if (!screen) { - fprintf(stderr, "Couldn't start video res %dx%d\n", width, height); + warning("Couldn't start video res %dx%d\n", width, height); return 0; } - +/* if (!(flags & FB2GL_RGBA)) { // Check for Paletted Texture Extension strcpy(gl_ext, (char *)glGetString(GL_EXTENSIONS)); @@ -208,32 +232,28 @@ int FB2GL::init(int width, int height, int xfix, int yfix, char _flags) { return 0; } } - +*/ + if (width>0 && height>0) - maketex(); - makedlist(xfix, yfix); + makeTextures(); + makeDisplayList(xfix, yfix); -/* glEnable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - glAlphaFunc(GL_GREATER,0); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);*/ - return 1; } void FB2GL::display() { - glCallList(dlist); + glCallList(displayList); SDL_GL_SwapBuffers(); } void FB2GL::update(void *fb, int w, int h, int pitch, int xskip, int yskip) { - unsigned char *fb1=(unsigned char *)fb; - int x,y,scr_pitch,byte=0; + unsigned char *tempFrameBuffer = (unsigned char *)fb; + int x, y, scr_pitch, byte = 0; - if (flags & FB2GL_PITCH) scr_pitch=pitch; + if (flags & FB2GL_PITCH) scr_pitch = pitch; else { - scr_pitch=w*pitch; + scr_pitch = w * pitch; byte = pitch; // Bytes perl pixel (for RGBA mode) } @@ -241,54 +261,56 @@ void FB2GL::update(void *fb, int w, int h, int pitch, int xskip, int yskip) { if (flags & FB2GL_EXPAND) { // Expand the 8 bit fb into a RGB fb - for (y=yskip; ypitch/2; // 16 bit pointer access (not char *) - int tex1_w = 0, tex2_w = 0, tex2_x = 0; - + + // Width of the rectangle draw in texture1. (256 - rx) > 0 + unsigned int tex1_w = 0; + // Width of the rectangle draw in texture2. (xend - 256) > 0 + unsigned int tex2_w = 0; + // Rectangle's x coordinate in texture2. (rx - 256) > 0 + unsigned int tex2_x = 0; + for (i=0; i fb->w) continue; if (yend > fb->h) continue; - if (rx < 256) { // Begins before the end of the 1st texture - if (xend >= 256) { // Ends after the first texture - tex2_w = xend-256; // For the 2nd texture - tex1_w = rw - tex2_w; // For the 1st texture + if (rx < 256) { // Begins before the end of texture1 + if (xend >= 256) { // Ends after texture1 + tex2_w = xend - 256; //Rectangle width on texture2 + tex1_w = rw - tex2_w; // Width left for texture1 } - else tex1_w = rw; + else tex1_w = rw; // This rectangle is inside texture1 } else { - tex2_w = rw; - tex2_x = rx - 256; + tex2_w = rw; // This rectangle is inside texture2 + tex2_x = rx - 256; // Relative x coordinate on texture2 } + // Note: if (tex1_w == 0) then there is no rectangle to draw + // in texture1. The same is true for tex2_w. + for (y = ry; y < yend; y++) { for (x = rx; x < xend; x++) { if (x < 256 && tex1_w) { - int pos = (x-rx+(y-ry)*tex1_w)*4; // RGBA - SDL_GetRGB(((Uint16 *)fb->pixels)[x+y*(pitch)],fb->format, - &fb1[pos], - &fb1[pos+1], - &fb1[pos+2]); + int pos = (x-rx+(y-ry)*tex1_w)*4; // (x + (y*pitch)) * RGBAsize + SDL_GetRGB( + ((Uint16 *)fb->pixels)[x+y*(pitch)], + fb->format, + &blitFrameBuffer1[pos], + &blitFrameBuffer1[pos+1], + &blitFrameBuffer1[pos+2] + ); } else if (x >= 256 && tex2_w) { int rx2 = rx < 256? 256: rx; - int pos = (x-rx2+(y-ry)*tex2_w)*4; // RGBA - SDL_GetRGB(((Uint16 *)fb->pixels)[x+y*(pitch)],fb->format, - &fb2[pos], - &fb2[pos+1], - &fb2[pos+2]); + int pos = (x-rx2+(y-ry)*tex2_w)*4; // (x + (y*pitch)) * RGBAsize + SDL_GetRGB( + ((Uint16 *)fb->pixels)[x+y*(pitch)], + fb->format, + &blitFrameBuffer2[pos], + &blitFrameBuffer2[pos+1], + &blitFrameBuffer2[pos+2] + ); } } } if (tex1_w > 0) { // Update 256x256 texture - glBindTexture(GL_TEXTURE_2D,texture); + glBindTexture(GL_TEXTURE_2D, texture1); glFlush(); - glTexSubImage2D(GL_TEXTURE_2D,0,rx+xskip,ry+yskip,tex1_w,rh,GL_RGBA, - GL_UNSIGNED_BYTE,fb1); + glTexSubImage2D(GL_TEXTURE_2D, 0, + rx + xskip, + ry + yskip, + tex1_w, rh, GL_RGBA, + GL_UNSIGNED_BYTE, blitFrameBuffer1); } if (tex2_w > 0) { // What was left for this texture // Update 64x256 texture - glBindTexture(GL_TEXTURE_2D,textureb); + glBindTexture(GL_TEXTURE_2D, texture2); glFlush(); - glTexSubImage2D(GL_TEXTURE_2D,0,tex2_x+xskip,ry+yskip,tex2_w,rh,GL_RGBA, - GL_UNSIGNED_BYTE,fb2); + glTexSubImage2D(GL_TEXTURE_2D, 0, + tex2_x + xskip, + ry + yskip, + tex2_w, rh, GL_RGBA, + GL_UNSIGNED_BYTE,blitFrameBuffer2); } } } void FB2GL::palette(int i, int r, int g, int b) { if (flags & FB2GL_EXPAND) { - ogl_temp_ctable[i][0]=r; - ogl_temp_ctable[i][1]=g; - ogl_temp_ctable[i][2]=b; + tempColorTable[i][0] = r; + tempColorTable[i][1] = g; + tempColorTable[i][2] = b; } else { // Paletted texture - ogl_ctable[i][0]=r; - ogl_ctable[i][1]=g; - ogl_ctable[i][2]=b; + colorTable[i][0] = r; + colorTable[i][1] = g; + colorTable[i][2] = b; } } -void FB2GL::setPalette(int f, int n) { +void FB2GL::setPalette(int first, int n) { char temp[256][3]; int i; if (flags & FB2GL_EXPAND) { - for (i=f; ipixels); + SDL_FreeSurface(old_tmpscreen); + + // Finally, blit everything to the screen + update_screen(); +} + void OSystem_SDL_OpenGL::update_screen() { // If the shake position changed, fill the dirty area with blackness if (_currentShakePos != _newShakePos) { @@ -228,11 +267,15 @@ void OSystem_SDL_OpenGL::update_screen() { fb2gl.blit16(_tmpscreen, _num_dirty_rects, _dirty_rect_list, 0, _currentShakePos+_glScreenStart); - tmpBlackRect.h = 256 - _screenHeight - _glScreenStart - _currentShakePos; - - SDL_FillRect(tmpSurface, &tmpBlackRect, 0); - fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0,_screenHeight - + _glScreenStart+_currentShakePos); + int _glBottomOfGameScreen = _screenHeight + _glScreenStart + _currentShakePos; + // Bottom black border height + tmpBlackRect.h = _glBottomOfTexture - _glBottomOfGameScreen; + + if (!(_full_screen) && (tmpBlackRect.h > 0)) { + SDL_FillRect(tmpSurface, &tmpBlackRect, 0); + fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0, + _glBottomOfGameScreen); + } fb2gl.display(); } @@ -246,8 +289,18 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) { if (param == PROP_TOGGLE_FULLSCREEN) { _full_screen ^= true; +#ifdef MACOSX + // On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse, + // it still always returns -1. So we simply don't call it at all and + // use hotswap_gfx_mode() directly to switch to fullscreen mode. + hotswap_gfx_mode(); +#else + if (!SDL_WM_ToggleFullScreen(fb2gl.getScreen())) { + // if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode + hotswap_gfx_mode(); + } +#endif - SDL_WM_ToggleFullScreen(fb2gl.screen); return 1; } else if (param == PROP_SET_GFX_MODE) { @@ -268,14 +321,14 @@ uint32 OSystem_SDL_OpenGL::property(int param, Property *value) { } } break; - case 1: // Don't fit the whole screen - fb2gl.init(0, 0, 0, 15, gl_flags); + case 1: // Don't use the whole screen + fb2gl.init(0, 0, 0, 15, _glFlags); _glScreenStart = 20; SDL_FillRect(tmpSurface, &tmpBlackRect, 0); fb2gl.blit16(tmpSurface, 1, &tmpBlackRect, 0, 0); break; - case 2: // Fit the whole screen - fb2gl.init(0, 0, 0, 70, gl_flags); + case 2: // Use the whole screen + fb2gl.init(0, 0, 0, 70, _glFlags); _glScreenStart = 0; break; default: // Zooming -- cgit v1.2.3