mirror of https://github.com/stella-emu/stella.git
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:
parent
b4388d45c0
commit
7efab7f29c
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// 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>
|
#include <SDL.h>
|
||||||
|
@ -77,22 +77,16 @@ bool FrameBufferGL::createScreen()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferGL::setupPalette(float shade)
|
void FrameBufferGL::setupPalette(float shade)
|
||||||
{
|
{
|
||||||
// FIXME - OpenGL should be able to shade the texture itself
|
|
||||||
const uInt32* gamePalette = myMediaSource->palette();
|
const uInt32* gamePalette = myMediaSource->palette();
|
||||||
for(uInt32 i = 0; i < 256; ++i)
|
for(uInt32 i = 0; i < 256; ++i)
|
||||||
{
|
{
|
||||||
Uint8 r, g, b, a;
|
Uint8 r, g, b;
|
||||||
|
|
||||||
r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade);
|
r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade);
|
||||||
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
|
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
|
||||||
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
|
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
|
||||||
a = 0xff;
|
|
||||||
|
|
||||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
myPalette[i] = SDL_MapRGB(myTexture->format, r, g, b);
|
||||||
myPalette[i] = (a << 24) | (b << 16) | (g << 8) | r;
|
|
||||||
#else
|
|
||||||
myPalette[i] = (r << 24) | (g << 16) | (b << 8) | a;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
theRedrawEntireFrameIndicator = true;
|
theRedrawEntireFrameIndicator = true;
|
||||||
|
@ -142,52 +136,84 @@ bool FrameBufferGL::init()
|
||||||
SDL_WM_SetCaption(name.str().c_str(), "stella");
|
SDL_WM_SetCaption(name.str().c_str(), "stella");
|
||||||
|
|
||||||
// Set up the OpenGL attributes
|
// Set up the OpenGL attributes
|
||||||
int rgb_size[3];
|
myDepth = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
|
||||||
int bpp = SDL_GetVideoInfo()->vfmt->BitsPerPixel;
|
switch(myDepth)
|
||||||
switch(bpp)
|
|
||||||
{
|
{
|
||||||
case 8:
|
case 8:
|
||||||
rgb_size[0] = 3;
|
myRGB[0] = 3;
|
||||||
rgb_size[1] = 3;
|
myRGB[1] = 3;
|
||||||
rgb_size[2] = 2;
|
myRGB[2] = 2;
|
||||||
|
myRGB[3] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 15:
|
case 15:
|
||||||
case 16:
|
myRGB[0] = 5;
|
||||||
rgb_size[0] = 5;
|
myRGB[1] = 5;
|
||||||
rgb_size[1] = 5;
|
myRGB[2] = 5;
|
||||||
rgb_size[2] = 5;
|
myRGB[3] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case 16:
|
||||||
rgb_size[0] = 8;
|
myRGB[0] = 5;
|
||||||
rgb_size[1] = 8;
|
myRGB[1] = 6;
|
||||||
rgb_size[2] = 8;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rgb_size[0] );
|
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, myRGB[0] );
|
||||||
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgb_size[1] );
|
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, myRGB[1] );
|
||||||
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, rgb_size[2] );
|
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, myRGB[2] );
|
||||||
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, bpp );
|
SDL_GL_SetAttribute( SDL_GL_ALPHA_SIZE, myRGB[3] );
|
||||||
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
|
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
|
||||||
|
|
||||||
// Create the screen
|
// Create the screen
|
||||||
if(!createScreen())
|
if(!createScreen())
|
||||||
return false;
|
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);
|
setupPalette(1.0);
|
||||||
|
|
||||||
// Show some OpenGL info
|
// Show some OpenGL info
|
||||||
if(myConsole->settings().getBool("showinfo"))
|
if(myConsole->settings().getBool("showinfo"))
|
||||||
{
|
{
|
||||||
|
ostringstream colormode;
|
||||||
|
colormode << "Color : " << myDepth << " bit, " << myRGB[0] << "-"
|
||||||
|
<< myRGB[1] << "-" << myRGB[2] << "-" << myRGB[3];
|
||||||
|
|
||||||
cout << endl
|
cout << endl
|
||||||
<< "Vendor : " << glGetString(GL_VENDOR) << endl
|
<< "Vendor : " << glGetString(GL_VENDOR) << endl
|
||||||
<< "Renderer: " << glGetString(GL_RENDERER) << 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
|
// Make sure that theUseFullScreenFlag sets up fullscreen mode correctly
|
||||||
theGrabMouseIndicator = myConsole->settings().getBool("grabmouse");
|
theGrabMouseIndicator = myConsole->settings().getBool("grabmouse");
|
||||||
theHideCursorIndicator = myConsole->settings().getBool("hidecursor");
|
theHideCursorIndicator = myConsole->settings().getBool("hidecursor");
|
||||||
|
@ -209,8 +235,8 @@ bool FrameBufferGL::init()
|
||||||
// Set up global GL stuff
|
// Set up global GL stuff
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glEnable(GL_LINE_SMOOTH);
|
|
||||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
@ -223,9 +249,9 @@ void FrameBufferGL::drawMediaSource()
|
||||||
// Copy the mediasource framebuffer to the RGB texture
|
// Copy the mediasource framebuffer to the RGB texture
|
||||||
uInt8* currentFrame = myMediaSource->currentFrameBuffer();
|
uInt8* currentFrame = myMediaSource->currentFrameBuffer();
|
||||||
uInt8* previousFrame = myMediaSource->previousFrameBuffer();
|
uInt8* previousFrame = myMediaSource->previousFrameBuffer();
|
||||||
uInt32 width = myMediaSource->width();
|
uInt32 width = myMediaSource->width();
|
||||||
uInt32 height = myMediaSource->height();
|
uInt32 height = myMediaSource->height();
|
||||||
uInt32* buffer = (uInt32*) myTexture->pixels;
|
uInt16* buffer = (uInt16*) myTexture->pixels;
|
||||||
|
|
||||||
register uInt32 y;
|
register uInt32 y;
|
||||||
for(y = 0; y < height; ++y )
|
for(y = 0; y < height; ++y )
|
||||||
|
@ -241,9 +267,9 @@ void FrameBufferGL::drawMediaSource()
|
||||||
if(v == previousFrame[bufofs] && !theRedrawEntireFrameIndicator)
|
if(v == previousFrame[bufofs] && !theRedrawEntireFrameIndicator)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// x << 1 is times 2 ( doubling width ) WIDTH_FACTOR
|
// x << 1 is times 2 ( doubling width )
|
||||||
const uInt32 pos = screenofsY + (x << 1);
|
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
|
// and antialiasing
|
||||||
glBindTexture(GL_TEXTURE_2D, myTextureID);
|
glBindTexture(GL_TEXTURE_2D, myTextureID);
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, myTexture->w, myTexture->h,
|
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);
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
|
||||||
glColor3f(0.0, 0.0, 0.0);
|
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)
|
void FrameBufferGL::drawBoundedBox(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
|
||||||
{
|
{
|
||||||
// First draw the box in the background, alpha-blended
|
// 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);
|
glColor4f(0.0, 0.0, 0.0, 0.7);
|
||||||
glRecti(x, y, x+w, y+h);
|
glRecti(x, y, x+w, y+h);
|
||||||
|
|
||||||
// Now draw the outer edges
|
// Now draw the outer edges
|
||||||
glDisable(GL_BLEND);
|
glColor4f(0.8, 0.8, 0.8, 1.0);
|
||||||
glColor3f(0.8, 0.8, 0.8);
|
|
||||||
glBegin(GL_LINE_LOOP);
|
glBegin(GL_LINE_LOOP);
|
||||||
glVertex2i(x, y ); // Top Left
|
glVertex2i(x, y ); // Top Left
|
||||||
glVertex2i(x+w, y ); // Top Right
|
glVertex2i(x+w, y ); // Top Right
|
||||||
|
@ -311,8 +336,6 @@ void FrameBufferGL::drawChar(uInt32 x, uInt32 y, uInt32 c)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, myFontTextureID[c]);
|
glBindTexture(GL_TEXTURE_2D, myFontTextureID[c]);
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND);
|
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(0, 0); glVertex2i(x, y );
|
glTexCoord2f(0, 0); glVertex2i(x, y );
|
||||||
glTexCoord2f(1, 0); glVertex2i(x+8, y );
|
glTexCoord2f(1, 0); glVertex2i(x+8, y );
|
||||||
|
@ -332,12 +355,8 @@ bool FrameBufferGL::createTextures()
|
||||||
myTexCoord[2] = (GLfloat) myWidth / w;
|
myTexCoord[2] = (GLfloat) myWidth / w;
|
||||||
myTexCoord[3] = (GLfloat) myHeight / h;
|
myTexCoord[3] = (GLfloat) myHeight / h;
|
||||||
|
|
||||||
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
|
myTexture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16,
|
||||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
0x0000F800, 0x000007E0, 0x0000001F, 0x00000000);
|
||||||
0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
|
|
||||||
#else
|
|
||||||
0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(myTexture == NULL)
|
if(myTexture == NULL)
|
||||||
return false;
|
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_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, param);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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);
|
myTexture->pixels);
|
||||||
|
|
||||||
// Now create the font textures. There are 256 fonts of 8x8 pixels.
|
// Now create the font textures. There are 256 fonts of 8x8 pixels.
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// 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
|
#ifndef FRAMEBUFFER_GL_HXX
|
||||||
|
@ -34,7 +34,7 @@ class MediaSource;
|
||||||
This class implements an SDL OpenGL framebuffer.
|
This class implements an SDL OpenGL framebuffer.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@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
|
class FrameBufferGL : public FrameBufferSDL
|
||||||
{
|
{
|
||||||
|
@ -135,6 +135,12 @@ class FrameBufferGL : public FrameBufferSDL
|
||||||
// The main texture buffer
|
// The main texture buffer
|
||||||
SDL_Surface* myTexture;
|
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
|
// The OpenGL main texture handle
|
||||||
GLuint myTextureID;
|
GLuint myTextureID;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// See the file "license" for information on usage and redistribution of
|
// See the file "license" for information on usage and redistribution of
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// 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>
|
#include <SDL.h>
|
||||||
|
@ -68,21 +68,7 @@ void FrameBufferSoft::setupPalette(float shade)
|
||||||
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
|
g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade);
|
||||||
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
|
b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade);
|
||||||
|
|
||||||
switch(myScreen->format->BitsPerPixel)
|
myPalette[i] = SDL_MapRGB(myScreen->format, r, g, b);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
theRedrawEntireFrameIndicator = true;
|
theRedrawEntireFrameIndicator = true;
|
||||||
|
|
Loading…
Reference in New Issue