Backtracked a little on the new software surfaces rendering code. The

surfaces are still separate and blitted separately, but the actual
screen updates are now done all at once, at the end of the frame (as in
the previous code).  This makes things a little faster, and eliminates
an annoying flicker because of SDL_UpdateRect being called at different
times.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1547 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2008-08-04 11:56:12 +00:00
parent 60da49f3ef
commit 54b5b79414
5 changed files with 75 additions and 57 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.104 2008-06-19 12:01:30 stephena Exp $
// $Id: FrameBufferGL.cxx,v 1.105 2008-08-04 11:56:11 stephena Exp $
//============================================================================
#ifdef DISPLAY_OPENGL
@ -385,7 +385,7 @@ void FrameBufferGL::drawMediaSource()
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
if(v != w || myRedrawEntireFrame)
{
// If we ever get to this point, we know the current and previous
// buffers differ. In that case, make sure the changes are
@ -403,7 +403,7 @@ void FrameBufferGL::drawMediaSource()
else
{
// Phosphor mode always implies a dirty update,
// so we don't care about theRedrawTIAIndicator
// so we don't care about myRedrawEntireFrame
myDirtyFlag = true;
uInt32 bufofsY = 0;
@ -462,7 +462,7 @@ void FrameBufferGL::enablePhosphor(bool enable, int blend)
myUsePhosphor = enable;
myPhosphorBlend = blend;
theRedrawTIAIndicator = true;
myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -488,7 +488,7 @@ void FrameBufferGL::toggleFilter()
p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter);
// The filtering has changed, so redraw the entire screen
theRedrawTIAIndicator = true;
myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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.81 2008-07-04 14:27:17 stephena Exp $
// $Id: FrameBufferSoft.cxx,v 1.82 2008-08-04 11:56:11 stephena Exp $
//============================================================================
#include <sstream>
@ -35,6 +35,8 @@
FrameBufferSoft::FrameBufferSoft(OSystem* osystem)
: FrameBuffer(osystem),
myRenderType(kSoftZoom_16),
myTiaDirty(false),
myInUIMode(false),
myRectList(NULL)
{
}
@ -131,8 +133,6 @@ void FrameBufferSoft::drawMediaSource()
uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height();
bool tiaChanged = false;
switch(myRenderType)
{
case kSoftZoom_16:
@ -155,14 +155,14 @@ void FrameBufferSoft::drawMediaSource()
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
if(v != w || myRedrawEntireFrame)
{
while(xstride--)
{
buffer[pos++] = (uInt16) myDefPalette[v];
buffer[pos++] = (uInt16) myDefPalette[v];
}
tiaChanged = true;
myTiaDirty = true;
}
else
pos += xstride + xstride;
@ -195,7 +195,7 @@ void FrameBufferSoft::drawMediaSource()
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
if(v != w || myRedrawEntireFrame)
{
uInt32 pixel = myDefPalette[v];
uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift;
@ -207,7 +207,7 @@ void FrameBufferSoft::drawMediaSource()
buffer[pos++] = r; buffer[pos++] = g; buffer[pos++] = b;
buffer[pos++] = r; buffer[pos++] = g; buffer[pos++] = b;
}
tiaChanged = true;
myTiaDirty = true;
}
else // try to eliminate multply whereever possible
pos += xstride + xstride + xstride + xstride + xstride + xstride;
@ -240,14 +240,14 @@ void FrameBufferSoft::drawMediaSource()
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
if(v != w || myRedrawEntireFrame)
{
while(xstride--)
{
buffer[pos++] = (uInt32) myDefPalette[v];
buffer[pos++] = (uInt32) myDefPalette[v];
}
tiaChanged = true;
myTiaDirty = true;
}
else
pos += xstride + xstride;
@ -291,7 +291,7 @@ void FrameBufferSoft::drawMediaSource()
bufofsY += width;
}
SDL_UnlockSurface(myScreen);
tiaChanged = true;
myTiaDirty = true;
break; // kPhosphor_16
}
@ -330,7 +330,7 @@ void FrameBufferSoft::drawMediaSource()
bufofsY += width;
}
SDL_UnlockSurface(myScreen);
tiaChanged = true;
myTiaDirty = true;
break; // kPhosphor_24
}
@ -365,16 +365,25 @@ void FrameBufferSoft::drawMediaSource()
bufofsY += width;
}
SDL_UnlockSurface(myScreen);
tiaChanged = true;
myTiaDirty = true;
break; // kPhosphor_32
}
}
}
if(tiaChanged)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::postFrameUpdate()
{
if(myTiaDirty && !myInUIMode)
{
SDL_Flip(myScreen);
tiaChanged = false;
myTiaDirty = false;
}
else if(myRectList->numRects() > 0)
{
SDL_UpdateRects(myScreen, myRectList->numRects(), myRectList->rects());
}
myRectList->start();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -392,6 +401,9 @@ void FrameBufferSoft::stateChanged(EventHandler::State state)
if(!myScreen)
return;
myInUIMode = (state == EventHandler::S_LAUNCHER ||
state == EventHandler::S_DEBUGGER);
// Make sure drawMediaSource() knows which renderer to use
switch(myBytesPerPixel)
{
@ -683,6 +695,10 @@ void FBSurfaceSoft::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
}
else
{
SDL_Rect temp;
temp.x = myXOrig; temp.y = myYOrig; temp.w = myWidth; temp.h = myHeight;
myFB.myRectList->add(&temp);
// Indicate that at least one dirty rect has been added
// This is an optimization for the update() method
mySurfaceIsDirty = true;
@ -751,15 +767,7 @@ void FBSurfaceSoft::update()
{
// Since this method is called each frame, we only blit the surfaces when
// absolutely necessary
if(myIsBaseSurface)
{
if(myFB.myRectList->numRects() > 0)
{
SDL_UpdateRects(mySurface, myFB.myRectList->numRects(), myFB.myRectList->rects());
myFB.myRectList->start();
}
}
else if(mySurfaceIsDirty /* && !myIsBaseSurface */)
if(mySurfaceIsDirty /* && !myIsBaseSurface */)
{
SDL_Rect srcrect;
srcrect.x = 0;
@ -772,17 +780,8 @@ void FBSurfaceSoft::update()
dstrect.y = myYOrig;
dstrect.w = myWidth;
dstrect.h = myHeight;
/*
cerr << "blit sub-surface:" << endl
<< " src x = " << dstrect.x << endl
<< " src y = " << dstrect.y << endl
<< " dst w = " << dstrect.w << endl
<< " dst h = " << dstrect.h << endl
<< endl;
*/
SDL_BlitSurface(mySurface, &srcrect, myFB.myScreen, &dstrect);
SDL_UpdateRect(myFB.myScreen, myXOrig, myYOrig, myWidth, myHeight);
SDL_BlitSurface(mySurface, &srcrect, myFB.myScreen, &dstrect);
mySurfaceIsDirty = false;
}
}

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.hxx,v 1.53 2008-08-01 12:15:57 stephena Exp $
// $Id: FrameBufferSoft.hxx,v 1.54 2008-08-04 11:56:11 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_SOFT_HXX
@ -33,7 +33,7 @@ class RectList;
This class implements an SDL software framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.53 2008-08-01 12:15:57 stephena Exp $
@version $Id: FrameBufferSoft.hxx,v 1.54 2008-08-04 11:56:11 stephena Exp $
*/
class FrameBufferSoft : public FrameBuffer
{
@ -127,6 +127,11 @@ class FrameBufferSoft : public FrameBuffer
*/
void drawMediaSource();
/**
This method is called after any drawing is done (per-frame).
*/
void postFrameUpdate();
/**
This method is called to provide information about the FrameBuffer.
*/
@ -154,6 +159,12 @@ class FrameBufferSoft : public FrameBuffer
};
RenderType myRenderType;
// Indicates if the TIA image has been modified
bool myTiaDirty;
// Indicates if we're in a purely UI mode
bool myInUIMode;
// Used in the dirty update of rectangles in non-TIA modes
RectList* myRectList;
};
@ -162,7 +173,7 @@ class FrameBufferSoft : public FrameBuffer
A surface suitable for software rendering mode.
@author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.53 2008-08-01 12:15:57 stephena Exp $
@version $Id: FrameBufferSoft.hxx,v 1.54 2008-08-04 11:56:11 stephena Exp $
*/
class FBSurfaceSoft : public FBSurface
{

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: FrameBuffer.cxx,v 1.138 2008-08-01 12:15:59 stephena Exp $
// $Id: FrameBuffer.cxx,v 1.139 2008-08-04 11:56:12 stephena Exp $
//============================================================================
#include <algorithm>
@ -42,7 +42,7 @@
FrameBuffer::FrameBuffer(OSystem* osystem)
: myOSystem(osystem),
myScreen(0),
theRedrawTIAIndicator(true),
myRedrawEntireFrame(true),
myUsePhosphor(false),
myPhosphorBlend(77),
myInitializedCount(0),
@ -168,7 +168,7 @@ void FrameBuffer::update()
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
myStatsMsg.surface->drawString(&myOSystem->consoleFont(), msg, 0, 0,
myStatsMsg.w, myStatsMsg.color, kTextAlignLeft);
myStatsMsg.surface->addDirtyRect(0, 0, 0, 0);
myStatsMsg.surface->addDirtyRect(0, 0, 0, 0); // force a full draw
myStatsMsg.surface->setPos(myImageRect.x() + 3, myImageRect.y() + 3);
myStatsMsg.surface->update();
}
@ -178,7 +178,7 @@ void FrameBuffer::update()
case EventHandler::S_PAUSE:
{
// Only update the screen if it's been invalidated
if(theRedrawTIAIndicator)
if(myRedrawEntireFrame)
drawMediaSource();
// Show a pause message every 5 seconds
@ -193,7 +193,7 @@ void FrameBuffer::update()
case EventHandler::S_MENU:
{
// Only update the screen if it's been invalidated
if(theRedrawTIAIndicator)
if(myRedrawEntireFrame)
drawMediaSource();
myOSystem->menu().draw();
@ -203,7 +203,7 @@ void FrameBuffer::update()
case EventHandler::S_CMDMENU:
{
// Only update the screen if it's been invalidated
if(theRedrawTIAIndicator)
if(myRedrawEntireFrame)
drawMediaSource();
myOSystem->commandMenu().draw();
@ -233,8 +233,11 @@ void FrameBuffer::update()
if(myMsg.counter > 0)
drawMessage();
// Do any post-frame stuff
postFrameUpdate();
// The frame doesn't need to be completely redrawn anymore
theRedrawTIAIndicator = false;
myRedrawEntireFrame = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -244,7 +247,7 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
// Erase old messages on the screen
if(myMsg.counter > 0)
{
theRedrawTIAIndicator = true;
myRedrawEntireFrame = true;
myOSystem->eventHandler().refreshDisplay();
}
@ -359,7 +362,7 @@ inline void FrameBuffer::drawMessage()
myOSystem->eventHandler().refreshDisplay(true);
else
{
myMsg.surface->addDirtyRect(0, 0, 0, 0);
myMsg.surface->addDirtyRect(0, 0, 0, 0); // force a full draw
myMsg.surface->update();
}
}
@ -367,7 +370,7 @@ inline void FrameBuffer::drawMessage()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::refresh()
{
theRedrawTIAIndicator = true;
myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -405,7 +408,7 @@ void FrameBuffer::setTIAPalette(const uInt32* palette)
}
}
theRedrawTIAIndicator = true;
myRedrawEntireFrame = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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: FrameBuffer.hxx,v 1.103 2008-08-01 12:16:00 stephena Exp $
// $Id: FrameBuffer.hxx,v 1.104 2008-08-04 11:56:12 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_HXX
@ -90,7 +90,7 @@ enum {
turn drawn here as well.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.103 2008-08-01 12:16:00 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.104 2008-08-04 11:56:12 stephena Exp $
*/
class FrameBuffer
{
@ -354,6 +354,11 @@ class FrameBuffer
*/
virtual void drawMediaSource() = 0;
/**
This method is called after any drawing is done (per-frame).
*/
virtual void postFrameUpdate() = 0;
/**
This method is called to provide information about the FrameBuffer.
*/
@ -369,8 +374,8 @@ class FrameBuffer
// SDL initialization flags
uInt32 mySDLFlags;
// Indicates if the TIA area should be redrawn
bool theRedrawTIAIndicator;
// Indicates if the entire frame need to redrawn
bool myRedrawEntireFrame;
// Use phosphor effect (aka no flicker on 30Hz screens)
bool myUsePhosphor;
@ -511,7 +516,7 @@ class FrameBuffer
FrameBuffer type.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.103 2008-08-01 12:16:00 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.104 2008-08-04 11:56:12 stephena Exp $
*/
// Text alignment modes for drawString()
enum TextAlignment {