From f48ea59ca6b490d7df8b9df801fbecbb1e1cef26 Mon Sep 17 00:00:00 2001 From: stephena Date: Sun, 3 Dec 2006 01:13:45 +0000 Subject: [PATCH] OK, second pass at FrameBufferGP2X class. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1168 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- stella/src/common/FrameBufferSoft.hxx | 6 +- stella/src/emucore/FrameBuffer.cxx | 46 ++--- stella/src/gp2x/FrameBufferGP2X.cxx | 262 +++++++++++++------------- stella/src/gp2x/FrameBufferGP2X.hxx | 6 +- 4 files changed, 157 insertions(+), 163 deletions(-) diff --git a/stella/src/common/FrameBufferSoft.hxx b/stella/src/common/FrameBufferSoft.hxx index b93989740..53f890264 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.36 2006-11-04 19:38:24 stephena Exp $ +// $Id: FrameBufferSoft.hxx,v 1.37 2006-12-03 01:13:44 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_SOFT_HXX @@ -35,7 +35,7 @@ class RectList; This class implements an SDL software framebuffer. @author Stephen Anthony - @version $Id: FrameBufferSoft.hxx,v 1.36 2006-11-04 19:38:24 stephena Exp $ + @version $Id: FrameBufferSoft.hxx,v 1.37 2006-12-03 01:13:44 stephena Exp $ */ class FrameBufferSoft : public FrameBuffer { @@ -185,7 +185,7 @@ class FrameBufferSoft : public FrameBuffer @param x X coordinate to translate @param y Y coordinate to translate */ - inline virtual void translateCoords(Int32* x, Int32* y); + virtual void translateCoords(Int32* x, Int32* y); /** This method adds a dirty rectangle diff --git a/stella/src/emucore/FrameBuffer.cxx b/stella/src/emucore/FrameBuffer.cxx index a852584ec..b9c8f1e90 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.102 2006-12-02 23:25:54 stephena Exp $ +// $Id: FrameBuffer.cxx,v 1.103 2006-12-03 01:13:45 stephena Exp $ //============================================================================ #include @@ -64,35 +64,35 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height, myFrameRate = myOSystem->frameRate(); // Now (re)initialize the SDL video system + // These things only have to be done one per FrameBuffer creation if(!isAlreadyInitialized) { Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER; if(SDL_Init(initflags) < 0) return; + + // Set window title and icon + setWindowTitle(title); + setWindowIcon(); + + // Query the desktop size + // This is really the job of SDL + int dwidth = 0, dheight = 0; + myOSystem->getScreenDimensions(dwidth, dheight); + myDesktopDim.w = dwidth; myDesktopDim.h = dheight; + + // Set fullscreen flag + mySDLFlags = myOSystem->settings().getBool("fullscreen") ? SDL_FULLSCREEN : 0; + + // Get the aspect ratio for the display if it's been enabled + theAspectRatio = 1.0; + if(useAspect) setAspectRatio(); } - setWindowIcon(); // Erase old contents cls(); - // Query the desktop size - // This is really the job of SDL - int dwidth = 0, dheight = 0; - myOSystem->getScreenDimensions(dwidth, dheight); - myDesktopDim.w = dwidth; myDesktopDim.h = dheight; - - // Set fullscreen flag - mySDLFlags = myOSystem->settings().getBool("fullscreen") ? SDL_FULLSCREEN : 0; - - // Set window title - setWindowTitle(title); - - // Get the aspect ratio for the display if it's been enabled - theAspectRatio = 1.0; - if(useAspect) - setAspectRatio(); - // Set the available scalers for this framebuffer, based on current eventhandler // state and the maximum size of a window for the current desktop setAvailableScalers(); @@ -106,14 +106,14 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height, // And refresh the display myOSystem->eventHandler().refreshDisplay(); - // Set palette for GUI - for(int i = 0; i < kNumColors-256; i++) - myDefPalette[i+256] = mapRGB(ourGUIColors[i][0], ourGUIColors[i][1], ourGUIColors[i][2]); - // Enable unicode so we can see translated key events // (lowercase vs. uppercase characters) SDL_EnableUNICODE(1); + // Set palette for GUI + for(int i = 0; i < kNumColors-256; i++) + myDefPalette[i+256] = mapRGB(ourGUIColors[i][0], ourGUIColors[i][1], ourGUIColors[i][2]); + // Erase any messages from a previous run myMessage.counter = 0; diff --git a/stella/src/gp2x/FrameBufferGP2X.cxx b/stella/src/gp2x/FrameBufferGP2X.cxx index ea1b4335e..2ae90d187 100644 --- a/stella/src/gp2x/FrameBufferGP2X.cxx +++ b/stella/src/gp2x/FrameBufferGP2X.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: FrameBufferGP2X.cxx,v 1.1 2006-12-02 23:25:54 stephena Exp $ +// $Id: FrameBufferGP2X.cxx,v 1.2 2006-12-03 01:13:45 stephena Exp $ //============================================================================ #include @@ -93,6 +93,7 @@ bool FrameBufferGP2X::createScreen() cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl; return false; } + myPitch = myScreen->pitch/2; // Erase old rects, since they've probably been scaled for // a different sized screen @@ -114,115 +115,94 @@ void FrameBufferGP2X::drawMediaSource() uInt32 width = mediasrc.width(); uInt32 height = mediasrc.height(); -// switch((int)myRenderType) // use switch/case, since we'll eventually have filters -// { - if(!myUsePhosphor) + if(!myUsePhosphor) + { + struct Rectangle { - struct Rectangle + uInt8 color; + uInt16 x, y, width, height; + } rectangles[2][160]; + + // This array represents the rectangles that need displaying + // on the current scanline we're processing + Rectangle* currentRectangles = rectangles[0]; + + // This array represents the rectangles that are still active + // from the previous scanlines we have processed + Rectangle* activeRectangles = rectangles[1]; + + // Indicates the number of active rectangles + uInt16 activeCount = 0; + + // This update procedure requires theWidth to be a multiple of four. + // This is validated when the properties are loaded. + for(uInt16 y = 0; y < height; ++y) + { + // Indicates the number of current rectangles + uInt16 currentCount = 0; + + // Look at four pixels at a time to see if anything has changed + uInt32* current = (uInt32*)(currentFrame); + uInt32* previous = (uInt32*)(previousFrame); + + for(uInt16 x = 0; x < width; x += 4, ++current, ++previous) { - uInt8 color; - uInt16 x, y, width, height; - } rectangles[2][160]; - - // This array represents the rectangles that need displaying - // on the current scanline we're processing - Rectangle* currentRectangles = rectangles[0]; - - // This array represents the rectangles that are still active - // from the previous scanlines we have processed - Rectangle* activeRectangles = rectangles[1]; - - // Indicates the number of active rectangles - uInt16 activeCount = 0; - - // This update procedure requires theWidth to be a multiple of four. - // This is validated when the properties are loaded. - for(uInt16 y = 0; y < height; ++y) - { - // Indicates the number of current rectangles - uInt16 currentCount = 0; - - // Look at four pixels at a time to see if anything has changed - uInt32* current = (uInt32*)(currentFrame); - uInt32* previous = (uInt32*)(previousFrame); - - for(uInt16 x = 0; x < width; x += 4, ++current, ++previous) + // Has something changed in this set of four pixels? + if((*current != *previous) || theRedrawTIAIndicator) { - // Has something changed in this set of four pixels? - if((*current != *previous) || theRedrawTIAIndicator) - { - uInt8* c = (uInt8*)current; - uInt8* p = (uInt8*)previous; + uInt8* c = (uInt8*)current; + uInt8* p = (uInt8*)previous; - // Look at each of the bytes that make up the uInt32 - for(uInt16 i = 0; i < 4; ++i, ++c, ++p) + // Look at each of the bytes that make up the uInt32 + for(uInt16 i = 0; i < 4; ++i, ++c, ++p) + { + // See if this pixel has changed + if((*c != *p) || theRedrawTIAIndicator) { - // See if this pixel has changed - if((*c != *p) || theRedrawTIAIndicator) + // Can we extend a rectangle or do we have to create a new one? + if((currentCount != 0) && + (currentRectangles[currentCount - 1].color == *c) && + ((currentRectangles[currentCount - 1].x + + currentRectangles[currentCount - 1].width) == (x + i))) { - // Can we extend a rectangle or do we have to create a new one? - if((currentCount != 0) && - (currentRectangles[currentCount - 1].color == *c) && - ((currentRectangles[currentCount - 1].x + - currentRectangles[currentCount - 1].width) == (x + i))) - { - currentRectangles[currentCount - 1].width += 1; - } - else - { - currentRectangles[currentCount].x = x + i; - currentRectangles[currentCount].y = y; - currentRectangles[currentCount].width = 1; - currentRectangles[currentCount].height = 1; - currentRectangles[currentCount].color = *c; - currentCount++; - } + currentRectangles[currentCount - 1].width += 1; + } + else + { + currentRectangles[currentCount].x = x + i; + currentRectangles[currentCount].y = y; + currentRectangles[currentCount].width = 1; + currentRectangles[currentCount].height = 1; + currentRectangles[currentCount].color = *c; + currentCount++; } } } } + } - // Merge the active and current rectangles flushing any that are of no use - uInt16 activeIndex = 0; + // Merge the active and current rectangles flushing any that are of no use + uInt16 activeIndex = 0; - for(uInt16 t = 0; (t < currentCount) && (activeIndex < activeCount); ++t) + for(uInt16 t = 0; (t < currentCount) && (activeIndex < activeCount); ++t) + { + Rectangle& current = currentRectangles[t]; + Rectangle& active = activeRectangles[activeIndex]; + + // Can we merge the current rectangle with an active one? + if((current.x == active.x) && (current.width == active.width) && + (current.color == active.color)) { - Rectangle& current = currentRectangles[t]; - Rectangle& active = activeRectangles[activeIndex]; - - // Can we merge the current rectangle with an active one? - if((current.x == active.x) && (current.width == active.width) && - (current.color == active.color)) - { - current.y = active.y; - current.height = active.height + 1; - - ++activeIndex; - } - // Is it impossible for this active rectangle to be merged? - else if(current.x >= active.x) - { - // Flush the active rectangle - SDL_Rect temp; - - temp.x = active.x * screenMultiple << 1; - temp.y = active.y * screenMultiple; - temp.w = active.width * screenMultiple << 1; - temp.h = active.height * screenMultiple; - - myRectList->add(&temp); - SDL_FillRect(myScreen, &temp, myDefPalette[active.color]); - - ++activeIndex; - } + current.y = active.y; + current.height = active.height + 1; + ++activeIndex; } - - // Flush any remaining active rectangles - for(uInt16 s = activeIndex; s < activeCount; ++s) + // Is it impossible for this active rectangle to be merged? + else if(current.x >= active.x) { - Rectangle& active = activeRectangles[s]; - + // Flush the active rectangle SDL_Rect temp; + temp.x = active.x * screenMultiple << 1; temp.y = active.y * screenMultiple; temp.w = active.width * screenMultiple << 1; @@ -230,23 +210,15 @@ void FrameBufferGP2X::drawMediaSource() myRectList->add(&temp); SDL_FillRect(myScreen, &temp, myDefPalette[active.color]); + + ++activeIndex; } - - // We can now make the current rectangles into the active rectangles - Rectangle* tmp = currentRectangles; - currentRectangles = activeRectangles; - activeRectangles = tmp; - activeCount = currentCount; - - currentFrame += width; - previousFrame += width; } - // Flush any rectangles that are still active - for(uInt16 t = 0; t < activeCount; ++t) + // Flush any remaining active rectangles + for(uInt16 s = activeIndex; s < activeCount; ++s) { - Rectangle& active = activeRectangles[t]; - + Rectangle& active = activeRectangles[s]; SDL_Rect temp; temp.x = active.x * screenMultiple << 1; temp.y = active.y * screenMultiple; @@ -256,44 +228,66 @@ void FrameBufferGP2X::drawMediaSource() myRectList->add(&temp); SDL_FillRect(myScreen, &temp, myDefPalette[active.color]); } + + // We can now make the current rectangles into the active rectangles + Rectangle* tmp = currentRectangles; + currentRectangles = activeRectangles; + activeRectangles = tmp; + activeCount = currentCount; + + currentFrame += width; + previousFrame += width; } -else -// case kPhosphor_16: + + // Flush any rectangles that are still active + for(uInt16 t = 0; t < activeCount; ++t) { - // Since phosphor mode updates the whole screen, - // we might as well use SDL_Flip (see postFrameUpdate) - myUseDirtyRects = false; + Rectangle& active = activeRectangles[t]; SDL_Rect temp; - temp.x = temp.y = temp.w = temp.h = 0; + temp.x = active.x * screenMultiple << 1; + temp.y = active.y * screenMultiple; + temp.w = active.width * screenMultiple << 1; + temp.h = active.height * screenMultiple; + 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; - for(uInt32 y = 0; y < height; ++y ) + uInt16* buffer = (uInt16*)myScreen->pixels; + uInt32 bufofsY = 0; + uInt32 screenofsY = 0; + for(uInt32 y = 0; y < height; ++y ) + { + uInt32 ystride = 1; // optimize this away + while(ystride--) { - uInt32 ystride = 1; // optimize this away - while(ystride--) + uInt32 pos = screenofsY; + for(uInt32 x = 0; x < width; ++x ) { - 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--) { - const uInt32 bufofs = bufofsY + x; - uInt32 xstride = 1; // optimize this away - - uInt8 v = currentFrame[bufofs]; - uInt8 w = previousFrame[bufofs]; - - while(xstride--) - { - buffer[pos++] = (uInt16) myAvgPalette[v][w]; - buffer[pos++] = (uInt16) myAvgPalette[v][w]; - } + buffer[pos++] = (uInt16) myAvgPalette[v][w]; + buffer[pos++] = (uInt16) myAvgPalette[v][w]; } - screenofsY += myPitch; } - bufofsY += width; + screenofsY += myPitch; } + bufofsY += width; } } } diff --git a/stella/src/gp2x/FrameBufferGP2X.hxx b/stella/src/gp2x/FrameBufferGP2X.hxx index 832cdf90c..afb5e3f52 100644 --- a/stella/src/gp2x/FrameBufferGP2X.hxx +++ b/stella/src/gp2x/FrameBufferGP2X.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: FrameBufferGP2X.hxx,v 1.1 2006-12-02 23:25:55 stephena Exp $ +// $Id: FrameBufferGP2X.hxx,v 1.2 2006-12-03 01:13:45 stephena Exp $ //============================================================================ #ifndef FRAMEBUFFER_GP2X_HXX @@ -35,7 +35,7 @@ class RectList; This class implements an SDL hardware framebuffer. @author Stephen Anthony - @version $Id: FrameBufferGP2X.hxx,v 1.1 2006-12-02 23:25:55 stephena Exp $ + @version $Id: FrameBufferGP2X.hxx,v 1.2 2006-12-03 01:13:45 stephena Exp $ */ class FrameBufferGP2X : public FrameBuffer { @@ -185,7 +185,7 @@ class FrameBufferGP2X : public FrameBuffer @param x X coordinate to translate @param y Y coordinate to translate */ - inline virtual void translateCoords(Int32* x, Int32* y); + virtual void translateCoords(Int32* x, Int32* y); /** This method adds a dirty rectangle