Phosphor effect now working for software render in 16/32 bit color modes;

still TODO for 24 bit mode.

I've benchmarked the CPU usage in Linux under 16/32 bit modes, and they're
within 1% of those for z26.  Not bad for C++ vs. assembly code :)  I still
need to test in Windows, which (ironically enough) tends to be slower than
Linux in graphics performance.

Note that CPU usage ranges from 6% (Linux/1x/software/phosphor/16bit) to
85% (Linux/3x/software/phosphor/32bit).  Using OpenGL, the usage is always
12%, whatever the zoom/color depth/phosphor.  I just love OpenGL ...


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@955 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-01-12 16:23:36 +00:00
parent b4525b5ff7
commit 53d70797d8
3 changed files with 249 additions and 211 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.47 2006-01-11 20:28:06 stephena Exp $ // $Id: FrameBufferGL.cxx,v 1.48 2006-01-12 16:23:36 stephena Exp $
//============================================================================ //============================================================================
#ifdef DISPLAY_OPENGL #ifdef DISPLAY_OPENGL
@ -221,16 +221,16 @@ void FrameBufferGL::drawMediaSource()
uInt16* buffer = (uInt16*) myTexture->pixels; uInt16* buffer = (uInt16*) myTexture->pixels;
// TODO - is this fast enough? // TODO - is this fast enough?
register uInt32 x, y;
switch((int)myUsePhosphor) // use switch/case, since we'll eventually have filters switch((int)myUsePhosphor) // use switch/case, since we'll eventually have filters
{ {
case 0: case 0:
for(y = 0; y < height; ++y )
{ {
const uInt32 bufofsY = y * width; uInt32 bufofsY = 0;
const uInt32 screenofsY = y * myTexture->w; uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y )
for(x = 0; x < width; ++x ) {
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{ {
const uInt32 bufofs = bufofsY + x; const uInt32 bufofs = bufofsY + x;
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
@ -243,63 +243,42 @@ void FrameBufferGL::drawMediaSource()
// are drawn in postFrameUpdate() // are drawn in postFrameUpdate()
myDirtyFlag = true; myDirtyFlag = true;
// x << 1 is times 2 ( doubling width )
const uInt32 pos = screenofsY + (x << 1);
buffer[pos] = buffer[pos+1] = (uInt16) myPalette[v]; buffer[pos] = buffer[pos+1] = (uInt16) myPalette[v];
} }
pos += 2;
} }
bufofsY += width;
screenofsY += myTexture->w;
} }
/*
for(y = 0; y < height; ++y )
{
const uInt32 bufofsY = y * width;
const uInt32 screenofsY = y * myTexture->w;
for(x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
if(v != w || theRedrawTIAIndicator)
{
// If we ever get to this point, we know the current and previous
// buffers differ. In that case, make sure the changes are
// are drawn in postFrameUpdate()
myDirtyFlag = true;
// x << 1 is times 2 ( doubling width )
const uInt32 pos = screenofsY + (x << 1);
buffer[pos] = buffer[pos+1] = (uInt16) myPalette[v];
}
}
}
*/
break; break;
}
case 1: case 1:
{
// 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 theRedrawTIAIndicator
myDirtyFlag = true; myDirtyFlag = true;
for(y = 0; y < height; ++y )
{
const uInt32 bufofsY = y * width;
const uInt32 screenofsY = y * myTexture->w;
for(x = 0; x < width; ++x ) uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y )
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{ {
const uInt32 bufofs = bufofsY + x; const uInt32 bufofs = bufofsY + x;
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs]; uInt8 w = previousFrame[bufofs];
// x << 1 is times 2 ( doubling width ) buffer[pos++] = (uInt16) myAvgPalette[v][w];
const uInt32 pos = screenofsY + (x << 1); buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos] = buffer[pos+1] = (uInt16) myAvgPalette[v][w];
} }
bufofsY += width;
screenofsY += myTexture->w;
} }
break; break;
} }
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -495,11 +474,6 @@ void FrameBufferGL::enablePhosphor(bool enable)
{ {
myUsePhosphor = enable; myUsePhosphor = enable;
myPhosphorBlend = myOSystem->settings().getInt("ppblend"); myPhosphorBlend = myOSystem->settings().getInt("ppblend");
cerr << "phosphor effect: " << (myUsePhosphor ? "yes" : "no") << endl
<< "phosphor amount: " << myPhosphorBlend << endl << endl;
// FIXME - change rendering method
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

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.41 2006-01-11 20:28:06 stephena Exp $ // $Id: FrameBufferSoft.cxx,v 1.42 2006-01-12 16:23:36 stephena Exp $
//============================================================================ //============================================================================
#include <SDL.h> #include <SDL.h>
@ -117,7 +117,7 @@ void FrameBufferSoft::drawMediaSource()
uInt32 width = mediasrc.width(); uInt32 width = mediasrc.width();
uInt32 height = mediasrc.height(); uInt32 height = mediasrc.height();
switch(myRenderType) // use switch/case, since we'll eventually have filters switch((int)myRenderType) // use switch/case, since we'll eventually have filters
{ {
case kSoftZoom: case kSoftZoom:
{ {
@ -259,11 +259,10 @@ void FrameBufferSoft::drawMediaSource()
myRectList->add(&temp); myRectList->add(&temp);
SDL_FillRect(myScreen, &temp, myPalette[active.color]); SDL_FillRect(myScreen, &temp, myPalette[active.color]);
} }
break; // case 0 break; // case 0
} }
case kPhosphor2x_16: case kPhosphor_16:
{ {
// Since phosphor mode updates the whole screen, // Since phosphor mode updates the whole screen,
// we might as well use SDL_Flip (see postFrameUpdate) // we might as well use SDL_Flip (see postFrameUpdate)
@ -273,53 +272,114 @@ void FrameBufferSoft::drawMediaSource()
myRectList->add(&temp); myRectList->add(&temp);
uInt16* buffer = (uInt16*)myScreen->pixels; uInt16* buffer = (uInt16*)myScreen->pixels;
int pixel; uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y)
{
for(int i = 0; i < width>>2; ++i)
{
pixel = myAvgPalette[*currentFrame++][*previousFrame++];
*buffer++ = pixel; *buffer++ = pixel;
*buffer++ = pixel; *buffer++ = pixel;
pixel = myAvgPalette[*currentFrame++][*previousFrame++];
*buffer++ = pixel; *buffer++ = pixel;
*buffer++ = pixel; *buffer++ = pixel;
pixel = myAvgPalette[*currentFrame++][*previousFrame++];
*buffer++ = pixel; *buffer++ = pixel;
*buffer++ = pixel; *buffer++ = pixel;
pixel = myAvgPalette[*currentFrame++][*previousFrame++];
*buffer++ = pixel; *buffer++ = pixel;
*buffer++ = pixel; *buffer++ = pixel;
}
buffer+=myScreen->pitch/2;
}
/*
uInt32 bufofsY = 0;//y * width;
uInt32 screenofsY = 0;//y * myScreen->pitch/2;
for(uInt32 y = 0; y < height; ++y ) for(uInt32 y = 0; y < height; ++y )
{ {
for(uInt32 x = 0; x < width; ++x) uInt32 ystride = theZoomLevel;
while(ystride--)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{ {
const uInt32 bufofs = bufofsY + x; const uInt32 bufofs = bufofsY + x;
uInt32 xstride = theZoomLevel;
uInt8 v = currentFrame[bufofs]; uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs]; uInt8 w = previousFrame[bufofs];
// x << 1 is times 2 ( doubling width ) while(xstride--)
int pos = screenofsY + (x << 2); {
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
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 += myScreen->w;
}
bufofsY += width; bufofsY += width;
screenofsY += myScreen->pitch/2;
} }
*/ break; // kPhosphor_16
break; }
case kPhosphor_24:
{
// FIXME - implement 24 bit mode
#if 0
// 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 )
{
uInt32 ystride = theZoomLevel;
while(ystride--)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt32 xstride = theZoomLevel;
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
while(xstride--)
{
buffer[pos++] = (uInt16) myAvgPalette[v][w];
buffer[pos++] = (uInt16) myAvgPalette[v][w];
}
}
screenofsY += myScreen->w;
}
bufofsY += width;
}
#endif
break; // kPhosphor_24
}
case kPhosphor_32:
{
// 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);
uInt32* buffer = (uInt32*)myScreen->pixels;
uInt32 bufofsY = 0;
uInt32 screenofsY = 0;
for(uInt32 y = 0; y < height; ++y )
{
uInt32 ystride = theZoomLevel;
while(ystride--)
{
uInt32 pos = screenofsY;
for(uInt32 x = 0; x < width; ++x )
{
const uInt32 bufofs = bufofsY + x;
uInt32 xstride = theZoomLevel;
uInt8 v = currentFrame[bufofs];
uInt8 w = previousFrame[bufofs];
while(xstride--)
{
buffer[pos++] = (uInt32) myAvgPalette[v][w];
buffer[pos++] = (uInt32) myAvgPalette[v][w];
}
}
screenofsY += myScreen->w;
}
bufofsY += width;
}
break; // kPhosphor_32
} }
} }
} }
@ -557,12 +617,25 @@ void FrameBufferSoft::enablePhosphor(bool enable)
myPhosphorBlend = myOSystem->settings().getInt("ppblend"); myPhosphorBlend = myOSystem->settings().getInt("ppblend");
if(myUsePhosphor) if(myUsePhosphor)
myRenderType = kPhosphor2x_16; {
switch(myScreen->format->BitsPerPixel)
{
case 16:
myRenderType = kPhosphor_16;
break;
case 24:
myRenderType = kPhosphor_24;
break;
case 32:
myRenderType = kPhosphor_32;
break;
default:
myRenderType = kSoftZoom; // What else should we do here?
break;
}
}
else else
myRenderType = kSoftZoom; myRenderType = kSoftZoom;
cerr << "phosphor effect: " << (myUsePhosphor ? "yes" : "no") << endl
<< "phosphor amount: " << myPhosphorBlend << endl << endl;
} }

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.27 2006-01-11 20:28:06 stephena Exp $ // $Id: FrameBufferSoft.hxx,v 1.28 2006-01-12 16:23:36 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.27 2006-01-11 20:28:06 stephena Exp $ @version $Id: FrameBufferSoft.hxx,v 1.28 2006-01-12 16:23:36 stephena Exp $
*/ */
class FrameBufferSoft : public FrameBuffer class FrameBufferSoft : public FrameBuffer
{ {
@ -201,18 +201,9 @@ class FrameBufferSoft : public FrameBuffer
private: private:
enum RenderType { enum RenderType {
kSoftZoom, kSoftZoom,
kPhosphor1x_16, kPhosphor_16,
kPhosphor2x_16, kPhosphor_24,
kPhosphor3x_16, kPhosphor_32
kPhosphor4x_16,
kPhosphor1x_24,
kPhosphor2x_24,
kPhosphor3x_24,
kPhosphor4x_24,
kPhosphor1x_32,
kPhosphor2x_32,
kPhosphor3x_32,
kPhosphor4x_32,
}; };
RenderType myRenderType; RenderType myRenderType;
}; };