GRAPHICS,SDL: Change oldSrcScale api

More bookkeeping is kept in common scaler code instead of the backend.
Plugins inheriting SourceScaler will have this functionality.

TODO: Some new functions may still be able to be combined to simplify
the API.
This commit is contained in:
Eric Culp 2012-07-16 18:24:57 -04:00 committed by Filippos Karapetis
parent c915efa452
commit c5c5662330
7 changed files with 127 additions and 55 deletions

View File

@ -120,7 +120,7 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
#if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
_originalBitsPerPixel(0),
#endif
_screen(0), _tmpscreen(0), _oldscreen(0), _destbuffer(0),
_screen(0), _tmpscreen(0), _destbuffer(0),
_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
_useOldSrc(false),
@ -682,17 +682,8 @@ void SurfaceSdlGraphicsManager::setGraphicsModeIntern() {
_extraPixels = (*_scalerPlugin)->extraPixels();
_useOldSrc = (*_scalerPlugin)->useOldSrc();
if (_useOldSrc) {
if (!_oldscreen) {
_oldscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + _maxExtraPixels * 2,
_videoMode.screenHeight + _maxExtraPixels * 2,
16,
_hwscreen->format->Rmask,
_hwscreen->format->Gmask,
_hwscreen->format->Bmask,
_hwscreen->format->Amask);
if (_oldscreen == NULL)
error("allocating _oldscreen failed");
}
(*_scalerPlugin)->setSource((byte *)_tmpscreen->pixels, _tmpscreen->pitch,
_videoMode.screenWidth, _videoMode.screenHeight, _maxExtraPixels, SRC_SCREEN);
if (!_destbuffer) {
_destbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth * _videoMode.scaleFactor,
_videoMode.screenHeight * _videoMode.scaleFactor,
@ -989,15 +980,8 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
if (_useOldSrc) {
// Create surface containing previous frame's data to pass to scaler
_oldscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + _maxExtraPixels * 2,
_videoMode.screenHeight + _maxExtraPixels * 2,
16,
_hwscreen->format->Rmask,
_hwscreen->format->Gmask,
_hwscreen->format->Bmask,
_hwscreen->format->Amask);
if (_oldscreen == NULL)
error("allocating _oldscreen failed");
(*_scalerPlugin)->setSource((byte *)_tmpscreen->pixels, _tmpscreen->pitch,
_videoMode.screenWidth, _videoMode.screenHeight, _maxExtraPixels, SRC_SCREEN);
// Create surface containing the raw output from the scaler
_destbuffer = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth * _videoMode.scaleFactor,
@ -1057,11 +1041,6 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
_tmpscreen = NULL;
}
if (_oldscreen) {
SDL_FreeSurface(_oldscreen);
_oldscreen = NULL;
}
if (_destbuffer) {
SDL_FreeSurface(_destbuffer);
_destbuffer = NULL;
@ -1110,6 +1089,7 @@ bool SurfaceSdlGraphicsManager::hotswapGFXMode() {
_overlayscreen = NULL;
// Release the HW screen surface
<<<<<<< HEAD
if (_hwScreen) {
SDL_FreeSurface(_hwScreen);
_hwScreen = NULL;
@ -1118,10 +1098,6 @@ bool SurfaceSdlGraphicsManager::hotswapGFXMode() {
SDL_FreeSurface(_tmpscreen);
_tmpscreen = NULL;
}
if (_oldscreen) {
SDL_FreeSurface(_oldscreen);
_oldscreen = NULL;
}
if (_destbuffer) {
SDL_FreeSurface(_destbuffer);
_destbuffer = NULL;
@ -1277,7 +1253,6 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
SDL_LockSurface(srcSurf);
SDL_LockSurface(_hwScreen);
if (_useOldSrc && !_overlayVisible) {
SDL_LockSurface(_oldscreen);
SDL_LockSurface(_destbuffer);
}
@ -1322,10 +1297,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
} else {
if (_useOldSrc) {
// scale into _destbuffer instead of _hwscreen to avoid AR problems
(*_scalerPlugin)->oldSrcScale((byte *)srcSurf->pixels + (r->x + _maxExtraPixels) * 2 + (r->y + _maxExtraPixels) * srcPitch, srcPitch,
(byte *)_destbuffer->pixels + rx1 * 2 + orig_dst_y * scale1 * _destbuffer->pitch, _destbuffer->pitch,
(byte *)_oldscreen->pixels + (r->x + _maxExtraPixels) * 2 + (r->y + _maxExtraPixels) * _oldscreen->pitch, _oldscreen->pitch,
r->w, dst_h, r->x, r->y);
(*_scalerPlugin)->oldSrcScale((byte *)_destbuffer->pixels, _destbuffer->pitch, SRC_SCREEN);
} else
(*_scalerPlugin)->scale((byte *)srcSurf->pixels + (r->x + _maxExtraPixels) * 2 + (r->y + _maxExtraPixels) * srcPitch, srcPitch,
(byte *)_hwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h, r->x, r->y);
@ -1363,14 +1335,7 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
SDL_UnlockSurface(_hwScreen);
if (_useOldSrc && !_overlayVisible) {
SDL_UnlockSurface(_oldscreen);
SDL_UnlockSurface(_destbuffer);
// Swap old and new screen
SDL_Surface *tmp;
tmp = _oldscreen;
_oldscreen = _tmpscreen;
_tmpscreen = tmp;
}
// Readjust the dirty rect list in case we are doing a full update.

View File

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

View File

@ -31,6 +31,7 @@ MODULE_OBJS := \
primitives.o \
renderer.o \
scaler.o \
scalerplugin.o \
scaler/thumbnail_intern.o \
screen.o \
scaler/normal.o \

View File

@ -3561,8 +3561,8 @@ void EdgePlugin::scale(const uint8 *srcPtr, uint32 srcPitch,
}
}
void EdgePlugin::oldSrcScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch, int width, int height, int x, int y) {
void EdgePlugin::internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch, int width, int height) {
if (_format.bytesPerPixel == 2) {
if (_factor == 2) {
if (_format.gLoss == 2)

View File

@ -24,7 +24,7 @@
#include "graphics/scalerplugin.h"
class EdgePlugin : public ScalerPluginObject {
class EdgePlugin : public SourceScaler {
public:
EdgePlugin();
@ -32,10 +32,10 @@ public:
virtual void deinitialize();
virtual void scale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch, int width, int height, int x, int y);
virtual void oldSrcScale(const uint8 *srcPtr, uint32 srcPitch,
virtual void internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch,
const uint8 *oldSrcPtr, uint32 oldSrcPitch,
int width, int height, int x, int y);
int width, int height);
virtual uint increaseFactor();
virtual uint decreaseFactor();
virtual uint getFactor() const { return _factor; }

54
graphics/scalerplugin.cpp Normal file
View File

@ -0,0 +1,54 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "graphics/scalerplugin.h"
SourceScaler::SourceScaler() {
for (int i = 0; i < SRC_MAX; ++i) {
oldSrcs[i] = NULL;
}
}
void SourceScaler::setSource(byte *src, uint pitch, int width, int height, int padding, SourceType type) {
widths[type] = width;
heights[type] = height;
pitches[type] = pitch;
newSrcs[type] = src;
paddings[type] = padding;
if (oldSrcs[type] != NULL)
free(oldSrcs[type]);
int size = (height + _format.bytesPerPixel * padding) * 2 * pitch;
oldSrcs[type] = new byte[size];
memset(oldSrcs[type], 0, size);
}
void SourceScaler::oldSrcScale(byte *dst, uint dstPitch, SourceType type) {
// Call user defined scale function
internScale(newSrcs[type] + paddings[type] * 2 + pitches[type] * paddings[type], pitches[type],
dst, dstPitch,
oldSrcs[type] + paddings[type] * 2 + pitches[type] * paddings[type], pitches[type],
widths[type], heights[type]);
// Update old src
memcpy(oldSrcs[type], newSrcs[type], (heights[type] + _format.bytesPerPixel * paddings[type]) * 2 * pitches[type]);
}

View File

@ -25,6 +25,15 @@
#include "base/plugins.h"
#include "graphics/pixelformat.h"
enum SourceType {
SRC_SCREEN = 0,
SRC_CURSOR,
SRC_OTHER,
SRC_MAX
};
class ScalerPluginObject : public PluginObject {
public:
@ -96,18 +105,29 @@ public:
* optionally call it.
*
* @see oldSourceScale
* @see setSource
*/
virtual bool useOldSrc() const { return false; }
/**
* Secondary scaling method for computationally intense scalers.
* Set the source to be used when scaling and copying to the old buffer.
*
* @see useOldSource
* @param padding The number of pixels on the border (Used to prevent memory access crashes)
* @param type The surface type. This source will only be used when calling oldSrcScale with the same type.
*/
virtual void oldSrcScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch,
const uint8 *oldSrcPtr, uint32 oldSrcPitch,
int width, int height, int x, int y) {
virtual void setSource(byte *src, uint pitch, int width, int height, int padding, SourceType type) {
// Should not be called unless overriden
assert(0);
}
/**
* Scale using the source from setSource called with the same value as type.
* The source will be compared against previous frames to avoid computations
* on unchanged pixels.
*
* @param type The surface type set previously with setSource
*/
virtual void oldSrcScale(byte *dst, uint dstPitch, SourceType type) {
// Should not be called unless overriden
assert(0);
}
@ -118,6 +138,40 @@ protected:
Graphics::PixelFormat _format;
};
/**
* Convenience class that implements some bookkeeping for keeping track of
* old source images.
*/
class SourceScaler : public ScalerPluginObject {
public:
SourceScaler();
virtual void setSource(byte *src, uint pitch, int width, int height, int padding, SourceType type);
virtual void oldSrcScale(byte *dst, uint dstPitch, SourceType type);
protected:
/**
* Scalers must implement this function. It will be called by oldSrcScale.
* If by comparing the src and oldsrc images it is discovered that no change
* is necessary, do not write a pixel.
*/
virtual void internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch,
const uint8 *oldSrcPtr, uint32 oldSrcPitch,
int width, int height) = 0;
int widths[SRC_MAX];
int heights[SRC_MAX];
uint paddings[SRC_MAX];
uint pitches[SRC_MAX];
byte *newSrcs[SRC_MAX];
byte *oldSrcs[SRC_MAX];
};
typedef PluginSubclass<ScalerPluginObject> ScalerPlugin;
/**