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 // 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.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 #ifdef DISPLAY_OPENGL
@ -385,7 +385,7 @@ void FrameBufferGL::drawMediaSource()
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[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 // If we ever get to this point, we know the current and previous
// buffers differ. In that case, make sure the changes are // buffers differ. In that case, make sure the changes are
@ -403,7 +403,7 @@ void FrameBufferGL::drawMediaSource()
else else
{ {
// Phosphor mode always implies a dirty update, // Phosphor mode always implies a dirty update,
// so we don't care about theRedrawTIAIndicator // so we don't care about myRedrawEntireFrame
myDirtyFlag = true; myDirtyFlag = true;
uInt32 bufofsY = 0; uInt32 bufofsY = 0;
@ -462,7 +462,7 @@ void FrameBufferGL::enablePhosphor(bool enable, int blend)
myUsePhosphor = enable; myUsePhosphor = enable;
myPhosphorBlend = blend; myPhosphorBlend = blend;
theRedrawTIAIndicator = true; myRedrawEntireFrame = true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -488,7 +488,7 @@ void FrameBufferGL::toggleFilter()
p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter); p_glTexParameteri(myBuffer.target, GL_TEXTURE_MIN_FILTER, myBuffer.filter);
// The filtering has changed, so redraw the entire screen // 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 // 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.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> #include <sstream>
@ -35,6 +35,8 @@
FrameBufferSoft::FrameBufferSoft(OSystem* osystem) FrameBufferSoft::FrameBufferSoft(OSystem* osystem)
: FrameBuffer(osystem), : FrameBuffer(osystem),
myRenderType(kSoftZoom_16), myRenderType(kSoftZoom_16),
myTiaDirty(false),
myInUIMode(false),
myRectList(NULL) myRectList(NULL)
{ {
} }
@ -131,8 +133,6 @@ void FrameBufferSoft::drawMediaSource()
uInt32 width = mediasrc.width(); uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height(); uInt32 height = mediasrc.height();
bool tiaChanged = false;
switch(myRenderType) switch(myRenderType)
{ {
case kSoftZoom_16: case kSoftZoom_16:
@ -155,14 +155,14 @@ void FrameBufferSoft::drawMediaSource()
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs]; uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator) if(v != w || myRedrawEntireFrame)
{ {
while(xstride--) while(xstride--)
{ {
buffer[pos++] = (uInt16) myDefPalette[v]; buffer[pos++] = (uInt16) myDefPalette[v];
buffer[pos++] = (uInt16) myDefPalette[v]; buffer[pos++] = (uInt16) myDefPalette[v];
} }
tiaChanged = true; myTiaDirty = true;
} }
else else
pos += xstride + xstride; pos += xstride + xstride;
@ -195,7 +195,7 @@ void FrameBufferSoft::drawMediaSource()
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs]; uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator) if(v != w || myRedrawEntireFrame)
{ {
uInt32 pixel = myDefPalette[v]; uInt32 pixel = myDefPalette[v];
uInt8 r = (pixel & myFormat->Rmask) >> myFormat->Rshift; 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;
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 else // try to eliminate multply whereever possible
pos += xstride + xstride + xstride + xstride + xstride + xstride; pos += xstride + xstride + xstride + xstride + xstride + xstride;
@ -240,14 +240,14 @@ void FrameBufferSoft::drawMediaSource()
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs]; uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator) if(v != w || myRedrawEntireFrame)
{ {
while(xstride--) while(xstride--)
{ {
buffer[pos++] = (uInt32) myDefPalette[v]; buffer[pos++] = (uInt32) myDefPalette[v];
buffer[pos++] = (uInt32) myDefPalette[v]; buffer[pos++] = (uInt32) myDefPalette[v];
} }
tiaChanged = true; myTiaDirty = true;
} }
else else
pos += xstride + xstride; pos += xstride + xstride;
@ -291,7 +291,7 @@ void FrameBufferSoft::drawMediaSource()
bufofsY += width; bufofsY += width;
} }
SDL_UnlockSurface(myScreen); SDL_UnlockSurface(myScreen);
tiaChanged = true; myTiaDirty = true;
break; // kPhosphor_16 break; // kPhosphor_16
} }
@ -330,7 +330,7 @@ void FrameBufferSoft::drawMediaSource()
bufofsY += width; bufofsY += width;
} }
SDL_UnlockSurface(myScreen); SDL_UnlockSurface(myScreen);
tiaChanged = true; myTiaDirty = true;
break; // kPhosphor_24 break; // kPhosphor_24
} }
@ -365,16 +365,25 @@ void FrameBufferSoft::drawMediaSource()
bufofsY += width; bufofsY += width;
} }
SDL_UnlockSurface(myScreen); SDL_UnlockSurface(myScreen);
tiaChanged = true; myTiaDirty = true;
break; // kPhosphor_32 break; // kPhosphor_32
} }
} }
}
if(tiaChanged) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferSoft::postFrameUpdate()
{
if(myTiaDirty && !myInUIMode)
{ {
SDL_Flip(myScreen); 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) if(!myScreen)
return; return;
myInUIMode = (state == EventHandler::S_LAUNCHER ||
state == EventHandler::S_DEBUGGER);
// Make sure drawMediaSource() knows which renderer to use // Make sure drawMediaSource() knows which renderer to use
switch(myBytesPerPixel) switch(myBytesPerPixel)
{ {
@ -683,6 +695,10 @@ void FBSurfaceSoft::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
} }
else 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 // Indicate that at least one dirty rect has been added
// This is an optimization for the update() method // This is an optimization for the update() method
mySurfaceIsDirty = true; mySurfaceIsDirty = true;
@ -751,15 +767,7 @@ void FBSurfaceSoft::update()
{ {
// Since this method is called each frame, we only blit the surfaces when // Since this method is called each frame, we only blit the surfaces when
// absolutely necessary // absolutely necessary
if(myIsBaseSurface) if(mySurfaceIsDirty /* && !myIsBaseSurface */)
{
if(myFB.myRectList->numRects() > 0)
{
SDL_UpdateRects(mySurface, myFB.myRectList->numRects(), myFB.myRectList->rects());
myFB.myRectList->start();
}
}
else if(mySurfaceIsDirty /* && !myIsBaseSurface */)
{ {
SDL_Rect srcrect; SDL_Rect srcrect;
srcrect.x = 0; srcrect.x = 0;
@ -772,17 +780,8 @@ void FBSurfaceSoft::update()
dstrect.y = myYOrig; dstrect.y = myYOrig;
dstrect.w = myWidth; dstrect.w = myWidth;
dstrect.h = myHeight; 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; mySurfaceIsDirty = false;
} }
} }

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: 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 #ifndef FRAMEBUFFER_SOFT_HXX
@ -33,7 +33,7 @@ class RectList;
This class implements an SDL software framebuffer. This class implements an SDL software framebuffer.
@author Stephen Anthony @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 class FrameBufferSoft : public FrameBuffer
{ {
@ -127,6 +127,11 @@ class FrameBufferSoft : public FrameBuffer
*/ */
void drawMediaSource(); 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. This method is called to provide information about the FrameBuffer.
*/ */
@ -154,6 +159,12 @@ class FrameBufferSoft : public FrameBuffer
}; };
RenderType myRenderType; 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 // Used in the dirty update of rectangles in non-TIA modes
RectList* myRectList; RectList* myRectList;
}; };
@ -162,7 +173,7 @@ class FrameBufferSoft : public FrameBuffer
A surface suitable for software rendering mode. A surface suitable for software rendering mode.
@author Stephen Anthony @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 class FBSurfaceSoft : public FBSurface
{ {

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: 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> #include <algorithm>
@ -42,7 +42,7 @@
FrameBuffer::FrameBuffer(OSystem* osystem) FrameBuffer::FrameBuffer(OSystem* osystem)
: myOSystem(osystem), : myOSystem(osystem),
myScreen(0), myScreen(0),
theRedrawTIAIndicator(true), myRedrawEntireFrame(true),
myUsePhosphor(false), myUsePhosphor(false),
myPhosphorBlend(77), myPhosphorBlend(77),
myInitializedCount(0), myInitializedCount(0),
@ -168,7 +168,7 @@ void FrameBuffer::update()
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor); myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
myStatsMsg.surface->drawString(&myOSystem->consoleFont(), msg, 0, 0, myStatsMsg.surface->drawString(&myOSystem->consoleFont(), msg, 0, 0,
myStatsMsg.w, myStatsMsg.color, kTextAlignLeft); 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->setPos(myImageRect.x() + 3, myImageRect.y() + 3);
myStatsMsg.surface->update(); myStatsMsg.surface->update();
} }
@ -178,7 +178,7 @@ void FrameBuffer::update()
case EventHandler::S_PAUSE: case EventHandler::S_PAUSE:
{ {
// Only update the screen if it's been invalidated // Only update the screen if it's been invalidated
if(theRedrawTIAIndicator) if(myRedrawEntireFrame)
drawMediaSource(); drawMediaSource();
// Show a pause message every 5 seconds // Show a pause message every 5 seconds
@ -193,7 +193,7 @@ void FrameBuffer::update()
case EventHandler::S_MENU: case EventHandler::S_MENU:
{ {
// Only update the screen if it's been invalidated // Only update the screen if it's been invalidated
if(theRedrawTIAIndicator) if(myRedrawEntireFrame)
drawMediaSource(); drawMediaSource();
myOSystem->menu().draw(); myOSystem->menu().draw();
@ -203,7 +203,7 @@ void FrameBuffer::update()
case EventHandler::S_CMDMENU: case EventHandler::S_CMDMENU:
{ {
// Only update the screen if it's been invalidated // Only update the screen if it's been invalidated
if(theRedrawTIAIndicator) if(myRedrawEntireFrame)
drawMediaSource(); drawMediaSource();
myOSystem->commandMenu().draw(); myOSystem->commandMenu().draw();
@ -233,8 +233,11 @@ void FrameBuffer::update()
if(myMsg.counter > 0) if(myMsg.counter > 0)
drawMessage(); drawMessage();
// Do any post-frame stuff
postFrameUpdate();
// The frame doesn't need to be completely redrawn anymore // 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 // Erase old messages on the screen
if(myMsg.counter > 0) if(myMsg.counter > 0)
{ {
theRedrawTIAIndicator = true; myRedrawEntireFrame = true;
myOSystem->eventHandler().refreshDisplay(); myOSystem->eventHandler().refreshDisplay();
} }
@ -359,7 +362,7 @@ inline void FrameBuffer::drawMessage()
myOSystem->eventHandler().refreshDisplay(true); myOSystem->eventHandler().refreshDisplay(true);
else else
{ {
myMsg.surface->addDirtyRect(0, 0, 0, 0); myMsg.surface->addDirtyRect(0, 0, 0, 0); // force a full draw
myMsg.surface->update(); myMsg.surface->update();
} }
} }
@ -367,7 +370,7 @@ inline void FrameBuffer::drawMessage()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::refresh() 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 // 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: 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 #ifndef FRAMEBUFFER_HXX
@ -90,7 +90,7 @@ enum {
turn drawn here as well. turn drawn here as well.
@author Stephen Anthony @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 class FrameBuffer
{ {
@ -354,6 +354,11 @@ class FrameBuffer
*/ */
virtual void drawMediaSource() = 0; 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. This method is called to provide information about the FrameBuffer.
*/ */
@ -369,8 +374,8 @@ class FrameBuffer
// SDL initialization flags // SDL initialization flags
uInt32 mySDLFlags; uInt32 mySDLFlags;
// Indicates if the TIA area should be redrawn // Indicates if the entire frame need to redrawn
bool theRedrawTIAIndicator; bool myRedrawEntireFrame;
// Use phosphor effect (aka no flicker on 30Hz screens) // Use phosphor effect (aka no flicker on 30Hz screens)
bool myUsePhosphor; bool myUsePhosphor;
@ -511,7 +516,7 @@ class FrameBuffer
FrameBuffer type. FrameBuffer type.
@author Stephen Anthony @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() // Text alignment modes for drawString()
enum TextAlignment { enum TextAlignment {