Moved from using SDL_FillRect to directly accessing the pixel data

when drawing characters in software mode.  The old code was calling
SDL_FillRect for every pixel in the character!  Preliminary testing
shows at least 2-3 times faster rendering, but I suspect it might
be higher for those systems where SDL_FillRect was slower than in
Linux.  SDL_FillRect isn't meant to be used for 1-pixel calls.
Incidentally, this is the reason why dirty-rect merging with
a lot of onscreen movement could be slow; it degenerated into calling
SDL_FillRect for every pixel.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1206 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2006-12-12 19:41:52 +00:00
parent af61380785
commit abcf56bd05
3 changed files with 86 additions and 17 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.cxx,v 1.64 2006-12-11 00:15:33 stephena Exp $ // $Id: FrameBufferSoft.cxx,v 1.65 2006-12-12 19:41:51 stephena Exp $
//============================================================================ //============================================================================
#include <SDL.h> #include <SDL.h>
@ -556,19 +556,16 @@ void FrameBufferSoft::scanline(uInt32 row, uInt8* data)
// Make sure no pixels are being modified // Make sure no pixels are being modified
SDL_LockSurface(myScreen); SDL_LockSurface(myScreen);
uInt32 bpp = myScreen->format->BytesPerPixel;
uInt8* start = (uInt8*) myScreen->pixels;
uInt32 yoffset = row * myScreen->pitch;
uInt32 pixel = 0; uInt32 pixel = 0;
uInt8 *p, r, g, b; uInt8 *p, r, g, b;
for(Int32 x = 0; x < myScreen->w; x++) for(Int32 x = 0; x < myScreen->w; x++)
{ {
p = (Uint8*) (start + // Start at top of RAM p = (Uint8*) ((uInt8*)myScreen->pixels + // Start at top of RAM
(yoffset) + // Go down 'row' lines (row * myScreen->pitch) + // Go down 'row' lines
(x * bpp)); // Go in 'x' pixels (x * myBytesPerPixel)); // Go in 'x' pixels
switch(bpp) switch(myBytesPerPixel)
{ {
case 1: case 1:
pixel = *p; pixel = *p;
@ -664,6 +661,75 @@ void FrameBufferSoft::drawChar(const GUI::Font* font, uInt8 chr,
chr -= desc.firstchar; chr -= desc.firstchar;
const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * h)); const uInt16* tmp = desc.bits + (desc.offset ? desc.offset[chr] : (chr * h));
#if 1
// Scale the origins to the current zoom
xorig *= myZoomLevel;
yorig *= myZoomLevel;
int screenofsY = 0;
switch(myBytesPerPixel)
{
case 2:
{
// Get buffer position where upper-left pixel of the character will be drawn
uInt16* buffer = (uInt16*) myScreen->pixels + yorig * myPitch + xorig;
for(int y = h; y; --y)
{
const uInt16 fontbuf = *tmp++;
int ystride = myZoomLevel;
while(ystride--)
{
uInt16 mask = 0x8000;
int pos = screenofsY;
for(int x = 0; x < w; x++, mask >>= 1)
{
int xstride = myZoomLevel;
if((fontbuf & mask) != 0)
while(xstride--)
buffer[pos++] = myDefPalette[color];
else
pos += xstride;
}
screenofsY += myPitch;
}
}
break;
}
case 3:
{
// TODO ...
break;
}
case 4:
{
// Get buffer position where upper-left pixel of the character will be drawn
uInt32* buffer = (uInt32*) myScreen->pixels + yorig * myPitch + xorig;
for(int y = h; y; --y)
{
const uInt16 fontbuf = *tmp++;
int ystride = myZoomLevel;
while(ystride--)
{
uInt16 mask = 0x8000;
int pos = screenofsY;
for(int x = 0; x < w; x++, mask >>= 1)
{
int xstride = myZoomLevel;
if((fontbuf & mask) != 0)
while(xstride--)
buffer[pos++] = myDefPalette[color];
else
pos += xstride;
}
screenofsY += myPitch;
}
}
break;
}
default:
break;
}
#else
SDL_Rect rect; SDL_Rect rect;
for(int y = 0; y < h; y++) for(int y = 0; y < h; y++)
{ {
@ -681,6 +747,7 @@ void FrameBufferSoft::drawChar(const GUI::Font* font, uInt8 chr,
} }
} }
} }
#endif
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -774,9 +841,10 @@ void FrameBufferSoft::stateChanged(EventHandler::State state)
// Make sure drawMediaSource() knows which renderer to use // Make sure drawMediaSource() knows which renderer to use
// Testing for dirty rects takes priority over phosphor mode, // Testing for dirty rects takes priority over phosphor mode,
// since phosphor mode only exists while emulating a ROM // since phosphor mode only exists while emulating a ROM
switch(myScreen->format->BitsPerPixel) myBytesPerPixel = myScreen->format->BytesPerPixel;
switch(myBytesPerPixel)
{ {
case 16: case 2: // 16-bit
myPitch = myScreen->pitch/2; myPitch = myScreen->pitch/2;
if(myUsePhosphor && emulation) if(myUsePhosphor && emulation)
myRenderType = kPhosphor_16; myRenderType = kPhosphor_16;
@ -785,7 +853,7 @@ void FrameBufferSoft::stateChanged(EventHandler::State state)
else else
myRenderType = kSoftZoom_16; myRenderType = kSoftZoom_16;
break; break;
case 24: case 3: // 24-bit
myPitch = myScreen->pitch; myPitch = myScreen->pitch;
if(myUsePhosphor && emulation) if(myUsePhosphor && emulation)
myRenderType = kPhosphor_24; myRenderType = kPhosphor_24;
@ -794,7 +862,7 @@ void FrameBufferSoft::stateChanged(EventHandler::State state)
else else
myRenderType = kSoftZoom_24; myRenderType = kSoftZoom_24;
break; break;
case 32: case 4: // 32-bit
myPitch = myScreen->pitch/4; myPitch = myScreen->pitch/4;
if(myUsePhosphor && emulation) if(myUsePhosphor && emulation)
myRenderType = kPhosphor_32; myRenderType = kPhosphor_32;

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.41 2006-12-11 00:15:33 stephena Exp $ // $Id: FrameBufferSoft.hxx,v 1.42 2006-12-12 19:41:52 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.41 2006-12-11 00:15:33 stephena Exp $ @version $Id: FrameBufferSoft.hxx,v 1.42 2006-12-12 19:41:52 stephena Exp $
*/ */
class FrameBufferSoft : public FrameBuffer class FrameBufferSoft : public FrameBuffer
{ {
@ -218,6 +218,7 @@ class FrameBufferSoft : public FrameBuffer
private: private:
int myZoomLevel; int myZoomLevel;
int myBytesPerPixel;
int myPitch; int myPitch;
enum RenderType { enum RenderType {

View File

@ -33,7 +33,7 @@
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>StellaOSX</string> <string>StellaOSX</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>StellaOSX 2.2</string> <string>StellaOSX 2.3</string>
<key>CFBundleHelpBookFolder</key> <key>CFBundleHelpBookFolder</key>
<string>docs</string> <string>docs</string>
<key>CFBundleHelpBookName</key> <key>CFBundleHelpBookName</key>
@ -45,13 +45,13 @@
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>StellaOSX 2.2</string> <string>StellaOSX 2.3</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>StLa</string> <string>StLa</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>StellaOSX 2.2</string> <string>StellaOSX 2.3</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>SDLMain.nib</string> <string>SDLMain.nib</string>
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>