GRAPHICS: Keep destination buffer in SourceScaler instead of SDL backend.

This commit is contained in:
Johannes Schickel 2012-09-24 04:49:34 +02:00 committed by Filippos Karapetis
parent 5420a7f6bd
commit 8825c9e3b4
6 changed files with 75 additions and 117 deletions

View File

@ -123,7 +123,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
_originalBitsPerPixel(0),
#endif
_screen(0), _tmpscreen(0), _destbuffer(0),
_screen(0), _tmpscreen(0),
_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
_useOldSrc(false),
@ -731,17 +731,6 @@ void SurfaceSdlGraphicsManager::setGraphicsModeIntern() {
_scalerPlugin->enableSource(true);
_scalerPlugin->setSource((byte *)_tmpscreen->pixels, _tmpscreen->pitch,
_videoMode.screenWidth, _videoMode.screenHeight, _maxExtraPixels);
if (!_destbuffer) {
_destbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth * _videoMode.scaleFactor,
_videoMode.screenHeight * _videoMode.scaleFactor,
16,
_hwScreen->format->Rmask,
_hwScreen->format->Gmask,
_hwScreen->format->Bmask,
_hwScreen->format->Amask);
if (_destbuffer == NULL)
error("allocating _destbuffer failed");
}
}
}
@ -1029,17 +1018,6 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
// Create surface containing previous frame's data to pass to scaler
_scalerPlugin->setSource((byte *)_tmpscreen->pixels, _tmpscreen->pitch,
_videoMode.screenWidth, _videoMode.screenHeight, _maxExtraPixels);
// Create surface containing the raw output from the scaler
_destbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth * _videoMode.scaleFactor,
_videoMode.screenHeight * _videoMode.scaleFactor,
16,
_hwScreen->format->Rmask,
_hwScreen->format->Gmask,
_hwScreen->format->Bmask,
_hwScreen->format->Amask);
if (_destbuffer == NULL)
error("allocating _destbuffer failed");
}
_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,
@ -1088,11 +1066,6 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
_tmpscreen = NULL;
}
if (_destbuffer) {
SDL_FreeSurface(_destbuffer);
_destbuffer = NULL;
}
if (_tmpscreen2) {
SDL_FreeSurface(_tmpscreen2);
_tmpscreen2 = NULL;
@ -1144,10 +1117,6 @@ bool SurfaceSdlGraphicsManager::hotswapGFXMode() {
SDL_FreeSurface(_tmpscreen);
_tmpscreen = NULL;
}
if (_destbuffer) {
SDL_FreeSurface(_destbuffer);
_destbuffer = NULL;
}
if (_tmpscreen2) {
SDL_FreeSurface(_tmpscreen2);
_tmpscreen2 = NULL;
@ -1300,9 +1269,6 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
SDL_LockSurface(srcSurf);
SDL_LockSurface(_hwScreen);
if (_useOldSrc && !_overlayVisible) {
SDL_LockSurface(_destbuffer);
}
srcPitch = srcSurf->pitch;
dstPitch = _hwScreen->pitch;
@ -1334,14 +1300,8 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
if (_videoMode.aspectRatioCorrection && !_overlayVisible)
dst_y = real2Aspect(dst_y);
if (_useOldSrc && !_overlayVisible) {
// scale into _destbuffer instead of _hwScreen to avoid AR problems
_scalerPlugin->scale((byte *)srcSurf->pixels + (r->x + _maxExtraPixels) * 2 + (r->y + _maxExtraPixels) * srcPitch, srcPitch,
(byte *)_destbuffer->pixels + dst_x * 2 + orig_dst_y * scale1 * _destbuffer->pitch, _destbuffer->pitch, r->w, dst_h, r->x, r->y);
} else {
_scalerPlugin->scale((byte *)srcSurf->pixels + (r->x + _maxExtraPixels) * 2 + (r->y + _maxExtraPixels) * srcPitch, srcPitch,
(byte *)_hwScreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h, r->x, r->y);
}
_scalerPlugin->scale((byte *)srcSurf->pixels + (r->x + _maxExtraPixels) * 2 + (r->y + _maxExtraPixels) * srcPitch, srcPitch,
(byte *)_hwScreen->pixels + dst_x * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h, r->x, r->y);
}
r->x = dst_x;
@ -1349,22 +1309,6 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
r->w = dst_w * scale1;
r->h = dst_h * scale1;
#ifdef USE_SCALERS
if (_useOldSrc && !_overlayVisible) {
// Copy _destbuffer back into _hwScreen to be AR corrected
int y = orig_dst_y * scale1;
int h = r->h;
int w = r->w;
byte *dest = (byte *)_hwScreen->pixels + dst_x * 2 + dst_y * dstPitch;
byte *src = (byte *)_destbuffer->pixels + dst_x * 2 + y * _destbuffer->pitch;
while (h--) {
memcpy(dest, src, w*2);
dest += dstPitch;
src += _destbuffer->pitch;
}
}
#endif
#ifdef USE_ASPECT
if (_videoMode.aspectRatioCorrection && orig_dst_y < height && !_overlayVisible) {
if (_useOldSrc)
@ -1377,10 +1321,6 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
SDL_UnlockSurface(srcSurf);
SDL_UnlockSurface(_hwScreen);
if (_useOldSrc && !_overlayVisible) {
SDL_UnlockSurface(_destbuffer);
}
// Readjust the dirty rect list in case we are doing a full update.
// This is necessary if shaking is active.
if (_forceRedraw) {
@ -1839,16 +1779,9 @@ void SurfaceSdlGraphicsManager::clearOverlay() {
SDL_LockSurface(_tmpscreen);
SDL_LockSurface(_overlayscreen);
// The plugin won't write anything if _useOldSrc
if (_useOldSrc)
_scalerPlugin->enableSource(false);
_scalerPlugin->scale((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, _tmpscreen->pitch,
(byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight, 0, 0);
if (_useOldSrc)
_scalerPlugin->enableSource(true);
#ifdef USE_ASPECT
if (_videoMode.aspectRatioCorrection)
stretch200To240((uint8 *)_overlayscreen->pixels, _overlayscreen->pitch,

View File

@ -217,8 +217,6 @@ protected:
/** Temporary screen (for scalers) */
SDL_Surface *_tmpscreen;
/** Previous frame's raw scaled screen (for scalers) */
SDL_Surface *_destbuffer;
/** Temporary screen (for scalers) */
SDL_Surface *_tmpscreen2;

View File

@ -3258,26 +3258,25 @@ int checkUnchangedPixels(const Pixel *old_src_ptr, const Pixel *pixels, int w) {
/* Draw unchanged pixel grid, 3x */
/* old_dptr starts in top left of grid, dptr in center */
template<typename Pixel>
void draw_unchanged_grid_3x(Pixel *dptr, int dstPitch,
Pixel *old_dptr, int old_dst_inc) {
Pixel *sp;
void drawUnchangedGrid3x(byte *dptr, int dstPitch,
const byte *old_dptr, int old_dst_inc) {
const Pixel *sp;
Pixel *dp;
uint8 *dptr8 = (uint8 *) dptr;
sp = old_dptr;
dp = (Pixel *)(dptr8 - dstPitch) - 1;
sp = (const Pixel *)old_dptr;
dp = (Pixel *)(dptr - dstPitch) - 1;
*dp++ = *sp++;
*dp++ = *sp++;
*dp = *sp;
sp = old_dptr + old_dst_inc;
dp = dptr - 1;
sp = (const Pixel *)(old_dptr + old_dst_inc);
dp = (Pixel *)dptr - 1;
*dp++ = *sp++;
*dp++ = *sp++;
*dp = *sp;
sp = old_dptr + old_dst_inc + old_dst_inc;
dp = (Pixel *)(dptr8 + dstPitch) - 1;
sp = (const Pixel *)(old_dptr + old_dst_inc + old_dst_inc);
dp = (Pixel *)(dptr + dstPitch) - 1;
*dp++ = *sp++;
*dp++ = *sp++;
*dp = *sp;
@ -3287,19 +3286,18 @@ void draw_unchanged_grid_3x(Pixel *dptr, int dstPitch,
/* Draw unchanged pixel grid, 2x */
template<typename Pixel>
void draw_unchanged_grid_2x(Pixel *dptr, int dstPitch,
Pixel *old_dptr, int old_dst_inc) {
Pixel *sp;
void drawUnchangedGrid2x(byte *dptr, int dstPitch,
const byte *old_dptr, int old_dst_inc) {
const Pixel *sp;
Pixel *dp;
uint8 *dptr8 = (uint8 *) dptr;
sp = old_dptr;
dp = dptr;
sp = (const Pixel *)old_dptr;
dp = (Pixel *)dptr;
*dp++ = *sp++;
*dp = *sp;
sp = old_dptr + old_dst_inc;
dp = (Pixel *)(dptr8 + dstPitch);
sp = (const Pixel *)(old_dptr + old_dst_inc);
dp = (Pixel *)(dptr + dstPitch);
*dp++ = *sp++;
*dp = *sp;
}
@ -3310,12 +3308,14 @@ void EdgePlugin::antiAliasPass3x(const uint8 *src, uint8 *dst,
int w, int h, int w_new, int h_new,
int srcPitch, int dstPitch,
bool haveOldSrc,
const uint8* oldSrc, int oldPitch) {
const uint8* oldSrc, int oldPitch,
const uint8 *buffer, int bufferPitch) {
int x, y;
const uint8 *sptr8 = src;
uint8 *dptr8 = dst + dstPitch + sizeof(Pixel);
const Pixel *sptr16;
const Pixel *oldSptr;
const Pixel *oldDptr;
Pixel *dptr16;
int16 *bplane;
int8 sim[8];
@ -3323,13 +3323,15 @@ void EdgePlugin::antiAliasPass3x(const uint8 *src, uint8 *dst,
int32 angle;
int16 *diffs;
int dstPitch3 = dstPitch * 3;
int bufferPitch3 = bufferPitch * 3;
for (y = 0; y < h; y++, sptr8 += srcPitch, dptr8 += dstPitch3, oldSrc += oldPitch) {
for (y = 0; y < h; y++, sptr8 += srcPitch, dptr8 += dstPitch3, oldSrc += oldPitch, buffer += bufferPitch3) {
for (x = 0,
sptr16 = (const Pixel *) sptr8,
oldSptr = (const Pixel *) oldSrc,
oldDptr = (const Pixel *) buffer,
dptr16 = (Pixel *) dptr8;
x < w; x++, sptr16++, dptr16 += 3, oldSptr++) {
x < w; x++, sptr16++, dptr16 += 3, oldDptr += 3, oldSptr++) {
const Pixel *sptr2, *addr3;
Pixel pixels[9];
char edge_type;
@ -3349,8 +3351,7 @@ void EdgePlugin::antiAliasPass3x(const uint8 *src, uint8 *dst,
x > 0 && x < w - 1 && y > 0 && y < h - 1 &&
#endif
checkUnchangedPixels(oldSptr, pixels, oldPitch / sizeof(Pixel))) {
//draw_unchanged_grid_3x(dptr16, dstPitch, old_dptr16,
// old_dst_inc);
drawUnchangedGrid3x<Pixel>((byte *)dptr16, dstPitch, (const byte *)oldDptr, bufferPitch);
#if DEBUG_REFRESH_RANDOM_XOR
*(dptr16 + 1) = 0;
@ -3390,12 +3391,14 @@ void EdgePlugin::antiAliasPass2x(const uint8 *src, uint8 *dst,
int srcPitch, int dstPitch,
int interpolate_2x,
bool haveOldSrc,
const uint8 *oldSrc, int oldSrcPitch) {
const uint8 *oldSrc, int oldSrcPitch,
const uint8 *buffer, int bufferPitch) {
int x, y;
const uint8 *sptr8 = src;
uint8 *dptr8 = dst;
const Pixel *sptr16;
const Pixel *oldSptr;
const Pixel *oldDptr;
Pixel *dptr16;
int16 *bplane;
int8 sim[8];
@ -3403,13 +3406,15 @@ void EdgePlugin::antiAliasPass2x(const uint8 *src, uint8 *dst,
int32 angle;
int16 *diffs;
int dstPitch2 = dstPitch << 1;
int bufferPitch2 = bufferPitch * 2;
for (y = 0; y < h; y++, sptr8 += srcPitch, dptr8 += dstPitch2, oldSrc += oldSrcPitch) {
for (y = 0; y < h; y++, sptr8 += srcPitch, dptr8 += dstPitch2, oldSrc += oldSrcPitch, buffer += bufferPitch2) {
for (x = 0,
sptr16 = (const Pixel *) sptr8,
dptr16 = (Pixel *) dptr8,
oldSptr = (const Pixel *) oldSrc;
x < w; x++, sptr16++, dptr16 += 2, oldSptr++) {
oldSptr = (const Pixel *) oldSrc,
oldDptr = (const Pixel *) buffer;
x < w; x++, sptr16++, dptr16 += 2, oldDptr += 2, oldSptr++) {
const Pixel *sptr2, *addr3;
Pixel pixels[9];
char edge_type;
@ -3429,8 +3434,7 @@ void EdgePlugin::antiAliasPass2x(const uint8 *src, uint8 *dst,
x > 0 && x < w - 1 && y > 0 && y < h - 1 &&
#endif
checkUnchangedPixels<Pixel>(oldSptr, pixels, oldSrcPitch / sizeof(Pixel))) {
//draw_unchanged_grid_2x(dptr16, dstPitch, old_dptr16,
// old_dst_inc);
drawUnchangedGrid2x<Pixel>((byte *)dptr16, dstPitch, (const byte *)oldDptr, bufferPitch);
#if DEBUG_REFRESH_RANDOM_XOR
*(dptr16 + 1) = 0;
@ -3561,31 +3565,31 @@ void EdgePlugin::scale(const uint8 *srcPtr, uint32 srcPitch,
#endif
void EdgePlugin::internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch, int width, int height) {
uint8 *dstPtr, uint32 dstPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch, int width, int height, const uint8 *buffer, uint32 bufferPitch) {
bool enable = oldSrcPtr != NULL;
if (_format.bytesPerPixel == 2) {
if (_factor == 2) {
if (_format.gLoss == 2)
antiAliasPass2x<Graphics::ColorMasks<565>, uint16>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass2x<Graphics::ColorMasks<565>, uint16>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
else
antiAliasPass2x<Graphics::ColorMasks<555>, uint16>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass2x<Graphics::ColorMasks<555>, uint16>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
} else {
if (_format.gLoss == 2)
antiAliasPass3x<Graphics::ColorMasks<565>, uint16>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass3x<Graphics::ColorMasks<565>, uint16>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
else
antiAliasPass3x<Graphics::ColorMasks<555>, uint16>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass3x<Graphics::ColorMasks<555>, uint16>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
}
} else {
if (_factor == 2) {
if (_format.aLoss == 0)
antiAliasPass2x<Graphics::ColorMasks<8888>, uint32>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass2x<Graphics::ColorMasks<8888>, uint32>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
else
antiAliasPass2x<Graphics::ColorMasks<888>, uint32>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass2x<Graphics::ColorMasks<888>, uint32>(srcPtr, dstPtr, width, height, 2 * width, 2 * height, srcPitch, dstPitch, 1, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
} else {
if (_format.aLoss == 0)
antiAliasPass3x<Graphics::ColorMasks<8888>, uint32>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass3x<Graphics::ColorMasks<8888>, uint32>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
else
antiAliasPass3x<Graphics::ColorMasks<888>, uint32>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch);
antiAliasPass3x<Graphics::ColorMasks<888>, uint32>(srcPtr, dstPtr, width, height, 3 * width, 3 * height, srcPitch, dstPitch, enable, oldSrcPtr, oldSrcPitch, buffer, bufferPitch);
}
}
}

View File

@ -42,7 +42,7 @@ protected:
virtual void internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch,
const uint8 *oldSrcPtr, uint32 oldSrcPitch,
int width, int height);
int width, int height, const uint8 *buffer, uint32 bufferPitch);
private:
@ -153,7 +153,8 @@ private:
int srcPitch, int dstPitch,
int interpolate_2x,
bool haveOldSrc,
const uint8 *oldSrc, int oldSrcPitch);
const uint8 *oldSrc, int oldSrcPitch,
const uint8 *buffer, int bufferPitch);
/**
* Perform edge detection, draw the new 3x pixels
@ -163,7 +164,8 @@ private:
int w, int h, int w_new, int h_new,
int srcPitch, int dstPitch,
bool haveOldSrc,
const uint8* oldSrc, int oldPitch);
const uint8* oldSrc, int oldPitch,
const uint8 *buffer, int bufferPitch);
int16 _rgbTable[65536][3]; ///< table lookup for RGB
int16 _greyscaleTable[3][65536]; ///< greyscale tables

View File

@ -68,6 +68,11 @@ SourceScaler::~SourceScaler() {
delete[] _oldSrc;
}
void SourceScaler::deinitialize() {
_bufferedOutput.free();
ScalerPluginObject::deinitialize();
}
void SourceScaler::setSource(const byte *src, uint pitch, int width, int height, int padding) {
if (_oldSrc != NULL)
delete[] _oldSrc;
@ -77,6 +82,8 @@ void SourceScaler::setSource(const byte *src, uint pitch, int width, int height,
int size = (height + padding * 2) * pitch;
_oldSrc = new byte[size];
memset(_oldSrc, 0, size);
_bufferedOutput.create(width * _factor, height * _factor, _format);
}
void SourceScaler::scaleIntern(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr,
@ -86,7 +93,8 @@ void SourceScaler::scaleIntern(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstP
internScale(srcPtr, srcPitch,
dstPtr, dstPitch,
NULL, 0,
width, height);
width, height,
NULL, 0);
return;
}
int offset = (_padding + x) * _format.bytesPerPixel + (_padding + y) * srcPitch;
@ -94,7 +102,17 @@ void SourceScaler::scaleIntern(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstP
internScale(srcPtr, srcPitch,
dstPtr, dstPitch,
_oldSrc + offset, srcPitch,
width, height);
width, height,
(uint8 *)_bufferedOutput.getBasePtr(x * _factor, y * _factor), _bufferedOutput.pitch);
// Update the destination buffer
byte *buffer = (byte *)_bufferedOutput.getBasePtr(x * _factor, y * _factor);
for (uint i = 0; i < height * _factor; ++i) {
memcpy(buffer, dstPtr, width * _factor * _format.bytesPerPixel);
buffer += _bufferedOutput.pitch;
dstPtr += dstPitch;
}
// Update old src
byte *oldSrc = _oldSrc + offset;
while (height--) {

View File

@ -24,6 +24,7 @@
#include "base/plugins.h"
#include "graphics/pixelformat.h"
#include "graphics/surface.h"
class ScalerPluginObject : public PluginObject {
public:
@ -160,6 +161,8 @@ public:
SourceScaler();
virtual ~SourceScaler();
virtual void deinitialize();
virtual void setSource(const byte *src, uint pitch, int width, int height, int padding);
virtual void enableSource(bool enable) { _enable = enable; }
@ -179,14 +182,14 @@ protected:
virtual void internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch,
const uint8 *oldSrcPtr, uint32 oldSrcPitch,
int width, int height) = 0;
int width, int height, const uint8 *buffer, uint32 bufferPitch) = 0;
private:
int _padding;
bool _enable;
byte *_oldSrc;
Graphics::Surface _bufferedOutput;
};
/**