OK, second pass at FrameBufferGP2X class.

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1168 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-12-03 01:13:45 +00:00
parent 8ef6d7032e
commit f48ea59ca6
4 changed files with 157 additions and 163 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: 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 #ifndef FRAMEBUFFER_SOFT_HXX
@ -35,7 +35,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.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 class FrameBufferSoft : public FrameBuffer
{ {
@ -185,7 +185,7 @@ class FrameBufferSoft : public FrameBuffer
@param x X coordinate to translate @param x X coordinate to translate
@param y Y 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 This method adds a dirty rectangle

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.102 2006-12-02 23:25:54 stephena Exp $ // $Id: FrameBuffer.cxx,v 1.103 2006-12-03 01:13:45 stephena Exp $
//============================================================================ //============================================================================
#include <sstream> #include <sstream>
@ -64,35 +64,35 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height,
myFrameRate = myOSystem->frameRate(); myFrameRate = myOSystem->frameRate();
// Now (re)initialize the SDL video system // Now (re)initialize the SDL video system
// These things only have to be done one per FrameBuffer creation
if(!isAlreadyInitialized) if(!isAlreadyInitialized)
{ {
Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER; Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER;
if(SDL_Init(initflags) < 0) if(SDL_Init(initflags) < 0)
return; 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 // Erase old contents
cls(); 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 // Set the available scalers for this framebuffer, based on current eventhandler
// state and the maximum size of a window for the current desktop // state and the maximum size of a window for the current desktop
setAvailableScalers(); setAvailableScalers();
@ -106,14 +106,14 @@ void FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height,
// And refresh the display // And refresh the display
myOSystem->eventHandler().refreshDisplay(); 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 // Enable unicode so we can see translated key events
// (lowercase vs. uppercase characters) // (lowercase vs. uppercase characters)
SDL_EnableUNICODE(1); 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 // Erase any messages from a previous run
myMessage.counter = 0; myMessage.counter = 0;

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: 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 <SDL.h> #include <SDL.h>
@ -93,6 +93,7 @@ bool FrameBufferGP2X::createScreen()
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl; cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
return false; return false;
} }
myPitch = myScreen->pitch/2;
// Erase old rects, since they've probably been scaled for // Erase old rects, since they've probably been scaled for
// a different sized screen // a different sized screen
@ -114,115 +115,94 @@ void FrameBufferGP2X::drawMediaSource()
uInt32 width = mediasrc.width(); uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height(); 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; // Has something changed in this set of four pixels?
uInt16 x, y, width, height; if((*current != *previous) || theRedrawTIAIndicator)
} 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? uInt8* c = (uInt8*)current;
if((*current != *previous) || theRedrawTIAIndicator) uInt8* p = (uInt8*)previous;
{
uInt8* c = (uInt8*)current;
uInt8* p = (uInt8*)previous;
// Look at each of the bytes that make up the uInt32 // Look at each of the bytes that make up the uInt32
for(uInt16 i = 0; i < 4; ++i, ++c, ++p) 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 // Can we extend a rectangle or do we have to create a new one?
if((*c != *p) || theRedrawTIAIndicator) 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? currentRectangles[currentCount - 1].width += 1;
if((currentCount != 0) && }
(currentRectangles[currentCount - 1].color == *c) && else
((currentRectangles[currentCount - 1].x + {
currentRectangles[currentCount - 1].width) == (x + i))) currentRectangles[currentCount].x = x + i;
{ currentRectangles[currentCount].y = y;
currentRectangles[currentCount - 1].width += 1; currentRectangles[currentCount].width = 1;
} currentRectangles[currentCount].height = 1;
else currentRectangles[currentCount].color = *c;
{ currentCount++;
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 // Merge the active and current rectangles flushing any that are of no use
uInt16 activeIndex = 0; 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]; current.y = active.y;
Rectangle& active = activeRectangles[activeIndex]; current.height = active.height + 1;
++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;
}
} }
// Is it impossible for this active rectangle to be merged?
// Flush any remaining active rectangles else if(current.x >= active.x)
for(uInt16 s = activeIndex; s < activeCount; ++s)
{ {
Rectangle& active = activeRectangles[s]; // Flush the active rectangle
SDL_Rect temp; SDL_Rect temp;
temp.x = active.x * screenMultiple << 1; temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple; temp.y = active.y * screenMultiple;
temp.w = active.width * screenMultiple << 1; temp.w = active.width * screenMultiple << 1;
@ -230,23 +210,15 @@ void FrameBufferGP2X::drawMediaSource()
myRectList->add(&temp); myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]); 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 // Flush any remaining active rectangles
for(uInt16 t = 0; t < activeCount; ++t) for(uInt16 s = activeIndex; s < activeCount; ++s)
{ {
Rectangle& active = activeRectangles[t]; Rectangle& active = activeRectangles[s];
SDL_Rect temp; SDL_Rect temp;
temp.x = active.x * screenMultiple << 1; temp.x = active.x * screenMultiple << 1;
temp.y = active.y * screenMultiple; temp.y = active.y * screenMultiple;
@ -256,44 +228,66 @@ void FrameBufferGP2X::drawMediaSource()
myRectList->add(&temp); myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myDefPalette[active.color]); 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, Rectangle& active = activeRectangles[t];
// we might as well use SDL_Flip (see postFrameUpdate)
myUseDirtyRects = false;
SDL_Rect temp; 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); 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; uInt16* buffer = (uInt16*)myScreen->pixels;
uInt32 bufofsY = 0; uInt32 bufofsY = 0;
uInt32 screenofsY = 0; uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y ) for(uInt32 y = 0; y < height; ++y )
{
uInt32 ystride = 1; // optimize this away
while(ystride--)
{ {
uInt32 ystride = 1; // optimize this away uInt32 pos = screenofsY;
while(ystride--) for(uInt32 x = 0; x < width; ++x )
{ {
uInt32 pos = screenofsY; const uInt32 bufofs = bufofsY + x;
for(uInt32 x = 0; x < width; ++x ) uInt32 xstride = 1; // optimize this away
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
while(xstride--)
{ {
const uInt32 bufofs = bufofsY + x; buffer[pos++] = (uInt16) myAvgPalette[v][w];
uInt32 xstride = 1; // optimize this away buffer[pos++] = (uInt16) myAvgPalette[v][w];
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
while(xstride--)
{
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
}
} }
screenofsY += myPitch;
} }
bufofsY += width; screenofsY += myPitch;
} }
bufofsY += width;
} }
} }
} }

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: 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 #ifndef FRAMEBUFFER_GP2X_HXX
@ -35,7 +35,7 @@ class RectList;
This class implements an SDL hardware framebuffer. This class implements an SDL hardware framebuffer.
@author Stephen Anthony @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 class FrameBufferGP2X : public FrameBuffer
{ {
@ -185,7 +185,7 @@ class FrameBufferGP2X : public FrameBuffer
@param x X coordinate to translate @param x X coordinate to translate
@param y Y 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 This method adds a dirty rectangle