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
// 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>
@ -26,9 +26,14 @@
#include "RectList.hxx"
#include "FrameBufferGP2X.hxx"
// Comment out entire line to test new rendering code
#define DIRTY_RECTS 1
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBufferGP2X::FrameBufferGP2X(OSystem* osystem)
: FrameBuffer(osystem),
myDirtyFlag(true),
myRectList(NULL),
myOverlayRectList(NULL)
{
@ -97,6 +102,7 @@ bool FrameBufferGP2X::createScreen()
myRectList->start();
myOverlayRectList->start();
myDirtyFlag = true;
return true;
}
@ -107,13 +113,17 @@ void FrameBufferGP2X::drawMediaSource()
uInt8* currentFrame = mediasrc.currentFrameBuffer();
uInt8* previousFrame = mediasrc.previousFrameBuffer();
uInt16 screenMultiple = 1; // remove this, and everything that refers to it
uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height();
uInt16* buffer = (uInt16*) myScreen->pixels;
uInt16 screenMultiple = 1; // remove this, and everything that refers to it
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
if(!myUsePhosphor)
{
#ifdef DIRTY_RECTS
struct Rectangle
{
uInt8 color;
@ -249,42 +259,51 @@ void FrameBufferGP2X::drawMediaSource()
myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]);
}
}
else
{
// Since phosphor mode updates the whole screen,
// we might as well use SDL_Flip (see postFrameUpdate)
myUseDirtyRects = false;
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;
#else
for(uInt32 y = 0; y < height; ++y )
{
uInt32 ystride = 1; // optimize this away
while(ystride--)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt32 xstride = 1; // optimize this away
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
while(xstride--)
if(v != w || theRedrawTIAIndicator)
{
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
// 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];
}
}
screenofsY += myPitch;
pos += 2;
}
bufofsY += width;
screenofsY += myBaseTexture->w;
}
#endif
}
else
{
// Phosphor mode always implies a dirty update,
// so we don't care about theRedrawTIAIndicator
myDirtyFlag = true;
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];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
}
bufofsY += width;
screenofsY += myPitch;
}
}
}
@ -305,8 +324,12 @@ void FrameBufferGP2X::preFrameUpdate()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGP2X::postFrameUpdate()
{
if(myDirtyFlag)
{
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)
{
// 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
// They will actually be added to the main rectlist in preFrameUpdate()
// 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;
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
// 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
@ -33,7 +33,7 @@ class RectList;
This class implements an SDL hardware framebuffer for the GP2X device.
@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
{
@ -212,6 +212,7 @@ class FrameBufferGP2X : public FrameBuffer
virtual void showCursor(bool show);
private:
bool myDirtyFlag;
int myPitch;
// Used in the dirty update of the SDL surface