From 54b5b79414f1aac12d9ab3bc56c520673179b633 Mon Sep 17 00:00:00 2001 From: stephena Date: Mon, 4 Aug 2008 11:56:12 +0000 Subject: [PATCH] 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 --- stella/src/common/FrameBufferGL.cxx | 10 ++--- stella/src/common/FrameBufferSoft.cxx | 65 +++++++++++++-------------- stella/src/common/FrameBufferSoft.hxx | 17 +++++-- stella/src/emucore/FrameBuffer.cxx | 25 ++++++----- stella/src/emucore/FrameBuffer.hxx | 15 ++++--- 5 files changed, 75 insertions(+), 57 deletions(-) diff --git a/stella/src/common/FrameBufferGL.cxx b/stella/src/common/FrameBufferGL.cxx index 54023d96a..c771a7038 100644 --- a/stella/src/common/FrameBufferGL.cxx +++ b/stella/src/common/FrameBufferGL.cxx @@ -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; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/common/FrameBufferSoft.cxx b/stella/src/common/FrameBufferSoft.cxx index 874c3dd71..572f43a47 100644 --- a/stella/src/common/FrameBufferSoft.cxx +++ b/stella/src/common/FrameBufferSoft.cxx @@ -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 @@ -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; } } diff --git a/stella/src/common/FrameBufferSoft.hxx b/stella/src/common/FrameBufferSoft.hxx index 05ab91177..87b85a279 100644 --- a/stella/src/common/FrameBufferSoft.hxx +++ b/stella/src/common/FrameBufferSoft.hxx @@ -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 { diff --git a/stella/src/emucore/FrameBuffer.cxx b/stella/src/emucore/FrameBuffer.cxx index 7358af6b1..715d43023 100644 --- a/stella/src/emucore/FrameBuffer.cxx +++ b/stella/src/emucore/FrameBuffer.cxx @@ -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 @@ -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; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/FrameBuffer.hxx b/stella/src/emucore/FrameBuffer.hxx index e33f1b53d..ba3a9307b 100644 --- a/stella/src/emucore/FrameBuffer.hxx +++ b/stella/src/emucore/FrameBuffer.hxx @@ -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 {