Some further optimizations to the SDL OpenGL port. I've reduced maximum

CPU usage from 14% to approx. 10%.  While that may not seem like much,
it's actually a 28% improvement.

The only way for it to get much better is to switch to paletted OpenGL
textures, but since they aren't supported in all versions of OpenGL,
I may not even bother.

For reference, the software SDL port uses a maximum of 5% CPU.  I don't
see the OpenGL port ever getting that low.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@216 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2003-11-22 20:13:11 +00:00
parent b4388d45c0
commit 7efab7f29c
3 changed files with 79 additions and 68 deletions

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGL.cxx,v 1.5 2003-11-18 15:04:17 stephena Exp $
// $Id: FrameBufferGL.cxx,v 1.6 2003-11-22 20:13:11 stephena Exp $
//============================================================================
#include <SDL.h>
@ -77,22 +77,16 @@ bool FrameBufferGL::createScreen()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::setupPalette(float shade)
{
// FIXME - OpenGL should be able to shade the texture itself
const uInt32* gamePalette = myMediaSource->palette();
for(uInt32 i = 0; i < 256; ++i)
{
Uint8 r, g, b, a;
Uint8 r, g, b;
r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade);
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
a = 0xff;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
myPalette[i] = (a << 24) | (b << 16) | (g << 8) | r;
#else
myPalette[i] = (r << 24) | (g << 16) | (b << 8) | a;
#endif
myPalette[i] = SDL_MapRGB(myTexture->format, r, g, b);
}
theRedrawEntireFrameIndicator = true;
@ -142,52 +136,84 @@ bool FrameBufferGL::init()
SDL_WM_SetCaption(name.str().c_str(), "stella");
// Set up the OpenGL attributes
int rgb_size[3];
int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
switch(bpp)
myDepth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
switch(myDepth)
{
case 8:
rgb_size[0] = 3;
rgb_size[1] = 3;
rgb_size[2] = 2;
myRGB[0] = 3;
myRGB[1] = 3;
myRGB[2] = 2;
myRGB[3] = 0;
break;
case 15:
case 16:
rgb_size[0] = 5;
rgb_size[1] = 5;
rgb_size[2] = 5;
myRGB[0] = 5;
myRGB[1] = 5;
myRGB[2] = 5;
myRGB[3] = 0;
break;
default:
rgb_size[0] = 8;
rgb_size[1] = 8;
rgb_size[2] = 8;
case 16:
myRGB[0] = 5;
myRGB[1] = 6;
myRGB[2] = 5;
myRGB[3] = 0;
break;
case 24:
myRGB[0] = 8;
myRGB[1] = 8;
myRGB[2] = 8;
myRGB[3] = 0;
break;
case 32:
myRGB[0] = 8;
myRGB[1] = 8;
myRGB[2] = 8;
myRGB[3] = 8;
break;
default: // This should never happen
break;
}
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rgb_size[0] );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgb_size[1] );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, rgb_size[2] );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bpp );
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, myRGB[0] );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, myRGB[1] );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, myRGB[2] );
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, myRGB[3] );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
// Create the screen
if(!createScreen())
return false;
// Now check to see what color components were actually created
SDL_GL_GetAttribute( SDL_GL_RED_SIZE, (int*)&myRGB[0] );
SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, (int*)&myRGB[1] );
SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, (int*)&myRGB[2] );
SDL_GL_GetAttribute( SDL_GL_ALPHA_SIZE, (int*)&myRGB[3] );
// Create the texture surface and texture fonts
createTextures();
// Set up the palette *after* we know the color components
// and the textures
setupPalette(1.0);
// Show some OpenGL info
if(myConsole->settings().getBool("showinfo"))
{
ostringstream colormode;
colormode << "Color : " << myDepth << " bit, " << myRGB[0] << "-"
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3];
cout << endl
<< "Vendor : " << glGetString(GL_VENDOR) << endl
<< "Renderer: " << glGetString(GL_RENDERER) << endl
<< "Version : " << glGetString(GL_VERSION) << endl;
<< "Version : " << glGetString(GL_VERSION) << endl
<< colormode.str() << endl;
}
// Create the texture surface and texture fonts
createTextures();
// Make sure that theUseFullScreenFlag sets up fullscreen mode correctly
theGrabMouseIndicator = myConsole->settings().getBool("grabmouse");
theHideCursorIndicator = myConsole->settings().getBool("hidecursor");
@ -209,8 +235,8 @@ bool FrameBufferGL::init()
// Set up global GL stuff
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_LINE_SMOOTH);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
@ -225,7 +251,7 @@ void FrameBufferGL::drawMediaSource()
uInt8* previousFrame = myMediaSource->previousFrameBuffer();
uInt32 width = myMediaSource->width();
uInt32 height = myMediaSource->height();
uInt32* buffer = (uInt32*) myTexture->pixels;
uInt16* buffer = (uInt16*) myTexture->pixels;
register uInt32 y;
for(y = 0; y < height; ++y )
@ -241,9 +267,9 @@ void FrameBufferGL::drawMediaSource()
if(v == previousFrame[bufofs] && !theRedrawEntireFrameIndicator)
continue;
// x << 1 is times 2 ( doubling width ) WIDTH_FACTOR
// x << 1 is times 2 ( doubling width )
const uInt32 pos = screenofsY + (x << 1);
buffer[pos] = buffer[pos+1] = myPalette[v];
buffer[pos] = buffer[pos+1] = (uInt16) myPalette[v];
}
}
@ -251,7 +277,7 @@ void FrameBufferGL::drawMediaSource()
// and antialiasing
glBindTexture(GL_TEXTURE_2D, myTextureID);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myTexture->w, myTexture->h,
GL_RGBA, GL_UNSIGNED_BYTE, myTexture->pixels);
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, myTexture->pixels);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glColor3f(0.0, 0.0, 0.0);
@ -282,13 +308,12 @@ void FrameBufferGL::postFrameUpdate()
void FrameBufferGL::drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{
// First draw the box in the background, alpha-blended
glEnable(GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glColor4f(0.0, 0.0, 0.0, 0.7);
glRecti(x, y, x+w, y+h);
// Now draw the outer edges
glDisable(GL_BLEND);
glColor3f(0.8, 0.8, 0.8);
glColor4f(0.8, 0.8, 0.8, 1.0);
glBegin(GL_LINE_LOOP);
glVertex2i(x, y ); // Top Left
glVertex2i(x+w, y ); // Top Right
@ -311,8 +336,6 @@ void FrameBufferGL::drawChar(uInt32 x, uInt32 y, uInt32 c)
return;
glBindTexture(GL_TEXTURE_2D, myFontTextureID[c]);
glEnable(GL_BLEND);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
glBegin(GL_QUADS);
glTexCoord2f(0, 0); glVertex2i(x, y );
glTexCoord2f(1, 0); glVertex2i(x+8, y );
@ -332,12 +355,8 @@ bool FrameBufferGL::createTextures()
myTexCoord[2] = (GLfloat) myWidth / w;
myTexCoord[3] = (GLfloat) myHeight / h;
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
#else
0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
#endif
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16,
0x0000F800, 0x000007E0, 0x0000001F, 0x00000000);
if(myTexture == NULL)
return false;
@ -365,7 +384,7 @@ bool FrameBufferGL::createTextures()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, param);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5,
myTexture->pixels);
// Now create the font textures. There are 256 fonts of 8x8 pixels.

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferGL.hxx,v 1.4 2003-11-17 17:43:39 stephena Exp $
// $Id: FrameBufferGL.hxx,v 1.5 2003-11-22 20:13:11 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_GL_HXX
@ -34,7 +34,7 @@ class MediaSource;
This class implements an SDL OpenGL framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferGL.hxx,v 1.4 2003-11-17 17:43:39 stephena Exp $
@version $Id: FrameBufferGL.hxx,v 1.5 2003-11-22 20:13:11 stephena Exp $
*/
class FrameBufferGL : public FrameBufferSDL
{
@ -135,6 +135,12 @@ class FrameBufferGL : public FrameBufferSDL
// The main texture buffer
SDL_Surface* myTexture;
// The depth of the texture buffer
uInt32 myDepth;
// The size of color components for OpenGL
uInt32 myRGB[4];
// The OpenGL main texture handle
GLuint myTextureID;

View File

@ -13,7 +13,7 @@
// See the file "license" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: FrameBufferSoft.cxx,v 1.1 2003-11-09 23:53:20 stephena Exp $
// $Id: FrameBufferSoft.cxx,v 1.2 2003-11-22 20:13:11 stephena Exp $
//============================================================================
#include <SDL.h>
@ -68,21 +68,7 @@ void FrameBufferSoft::setupPalette(float shade)
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
switch(myScreen->format->BitsPerPixel)
{
case 15:
myPalette[i] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
break;
case 16:
myPalette[i] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
break;
case 24:
case 32:
myPalette[i] = (r << 16) | (g << 8) | b;
break;
}
myPalette[i] = SDL_MapRGB(myScreen->format, r, g, b);
}
theRedrawEntireFrameIndicator = true;