First pass at optimizing the FrameBufferGP2X rendering code. Since the

hardware in this device is a known quantity and is using a hardware surface,
perhaps we can take advantage of that.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1177 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-12-04 19:43:26 +00:00
parent c973c3d968
commit 0bf5e843bc
2 changed files with 62 additions and 37 deletions

View File

@ -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: FrameBufferGP2X.cxx,v 1.3 2006-12-03 17:57:54 stephena Exp $ // $Id: FrameBufferGP2X.cxx,v 1.4 2006-12-04 19:43:26 stephena Exp $
//============================================================================ //============================================================================
#include <SDL.h> #include <SDL.h>
@ -26,9 +26,14 @@
#include "RectList.hxx" #include "RectList.hxx"
#include "FrameBufferGP2X.hxx" #include "FrameBufferGP2X.hxx"
// Comment out entire line to test new rendering code
#define DIRTY_RECTS 1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferGP2X::FrameBufferGP2X(OSystem* osystem) FrameBufferGP2X::FrameBufferGP2X(OSystem* osystem)
: FrameBuffer(osystem), : FrameBuffer(osystem),
myDirtyFlag(true),
myRectList(NULL), myRectList(NULL),
myOverlayRectList(NULL) myOverlayRectList(NULL)
{ {
@ -97,6 +102,7 @@ bool FrameBufferGP2X::createScreen()
myRectList->start(); myRectList->start();
myOverlayRectList->start(); myOverlayRectList->start();
myDirtyFlag = true;
return true; return true;
} }
@ -107,13 +113,17 @@ void FrameBufferGP2X::drawMediaSource()
uInt8* currentFrame = mediasrc.currentFrameBuffer(); uInt8* currentFrame = mediasrc.currentFrameBuffer();
uInt8* previousFrame = mediasrc.previousFrameBuffer(); uInt8* previousFrame = mediasrc.previousFrameBuffer();
uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height();
uInt16* buffer = (uInt16*) myScreen->pixels;
uInt16 screenMultiple = 1; // remove this, and everything that refers to it uInt16 screenMultiple = 1; // remove this, and everything that refers to it
uInt32 width = mediasrc.width(); uInt32 bufofsY = 0;
uInt32 height = mediasrc.height(); uInt32 screenofsY = 0;
if(!myUsePhosphor) if(!myUsePhosphor)
{ {
#ifdef DIRTY_RECTS
struct Rectangle struct Rectangle
{ {
uInt8 color; uInt8 color;
@ -249,42 +259,51 @@ void FrameBufferGP2X::drawMediaSource()
myRectList->add(&temp); myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]); SDL_FillRect(myScreen, &temp, myDefPalette[active.color]);
} }
#else
for(uInt32 y = 0; y < height; ++y )
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
{
// If we ever get to this point, we know the current and previous
// buffers differ. In that case, make sure the changes are
// are drawn in postFrameUpdate()
myDirtyFlag = true;
buffer[pos] = buffer[pos+1] = (uInt16) myDefPalette[v];
}
pos += 2;
}
bufofsY += width;
screenofsY += myBaseTexture->w;
}
#endif
} }
else else
{ {
// Since phosphor mode updates the whole screen, // Phosphor mode always implies a dirty update,
// we might as well use SDL_Flip (see postFrameUpdate) // so we don't care about theRedrawTIAIndicator
myUseDirtyRects = false; myDirtyFlag = true;
SDL_Rect temp;
temp.x = temp.y = temp.w = temp.h = 0;
myRectList->add(&temp);
uInt16* buffer = (uInt16*)myScreen->pixels;
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y ) for(uInt32 y = 0; y < height; ++y )
{ {
uInt32 ystride = 1; // optimize this away uInt32 pos = screenofsY;
while(ystride--) for(uInt32 x = 0; x < width; ++x )
{ {
uInt32 pos = screenofsY; const uInt32 bufofs = bufofsY + x;
for(uInt32 x = 0; x < width; ++x ) uInt8 v = currentFrame[bufofs];
{ uInt8 w = previousFrame[bufofs];
const uInt32 bufofs = bufofsY + x;
uInt32 xstride = 1; // optimize this away
uInt8 v = currentFrame[bufofs]; buffer[pos++] = (uInt16) myAvgPalette[v][w];
uInt8 w = previousFrame[bufofs]; buffer[pos++] = (uInt16) myAvgPalette[v][w];
while(xstride--)
{
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
}
}
screenofsY += myPitch;
} }
bufofsY += width; bufofsY += width;
screenofsY += myPitch;
} }
} }
} }
@ -305,8 +324,12 @@ void FrameBufferGP2X::preFrameUpdate()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::postFrameUpdate() void FrameBufferGP2X::postFrameUpdate()
{ {
SDL_Flip(myScreen); if(myDirtyFlag)
myRectList->start(); {
SDL_Flip(myScreen);
myRectList->start();
myDirtyFlag = false;
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -454,6 +477,10 @@ void FrameBufferGP2X::translateCoords(Int32* x, Int32* y)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h) void FrameBufferGP2X::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
{ {
// We may entirely remove the RectList, since it might be faster to just
// flip the screen (since it's a hardware buffer)
myDirtyFlag = true;
// Add a dirty rect to the overlay rectangle list // Add a dirty rect to the overlay rectangle list
// They will actually be added to the main rectlist in preFrameUpdate() // They will actually be added to the main rectlist in preFrameUpdate()
// TODO - intelligent merging of rectangles, to avoid overlap // TODO - intelligent merging of rectangles, to avoid overlap
@ -464,9 +491,6 @@ void FrameBufferGP2X::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
temp.h = h; temp.h = h;
myOverlayRectList->add(&temp); myOverlayRectList->add(&temp);
// cerr << "addDirtyRect(): "
// << "x=" << temp.x << ", y=" << temp.y << ", w=" << temp.w << ", h=" << temp.h << endl;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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: FrameBufferGP2X.hxx,v 1.3 2006-12-03 17:57:54 stephena Exp $ // $Id: FrameBufferGP2X.hxx,v 1.4 2006-12-04 19:43:26 stephena Exp $
//============================================================================ //============================================================================
#ifndef FRAMEBUFFER_GP2X_HXX #ifndef FRAMEBUFFER_GP2X_HXX
@ -33,7 +33,7 @@ class RectList;
This class implements an SDL hardware framebuffer for the GP2X device. This class implements an SDL hardware framebuffer for the GP2X device.
@author Stephen Anthony @author Stephen Anthony
@version $Id: FrameBufferGP2X.hxx,v 1.3 2006-12-03 17:57:54 stephena Exp $ @version $Id: FrameBufferGP2X.hxx,v 1.4 2006-12-04 19:43:26 stephena Exp $
*/ */
class FrameBufferGP2X : public FrameBuffer class FrameBufferGP2X : public FrameBuffer
{ {
@ -212,6 +212,7 @@ class FrameBufferGP2X : public FrameBuffer
virtual void showCursor(bool show); virtual void showCursor(bool show);
private: private:
bool myDirtyFlag;
int myPitch; int myPitch;
// Used in the dirty update of the SDL surface // Used in the dirty update of the SDL surface