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

View file

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

View file

@ -31,6 +31,7 @@ MODULE_OBJS := \
primitives.o \ primitives.o \
renderer.o \ renderer.o \
scaler.o \ scaler.o \
scalerplugin.o \
scaler/thumbnail_intern.o \ scaler/thumbnail_intern.o \
screen.o \ screen.o \
scaler/normal.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, void EdgePlugin::internScale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch, int width, int height, int x, int y) { uint8 *dstPtr, uint32 dstPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch, int width, int height) {
if (_format.bytesPerPixel == 2) { if (_format.bytesPerPixel == 2) {
if (_factor == 2) { if (_factor == 2) {
if (_format.gLoss == 2) if (_format.gLoss == 2)

View file

@ -24,7 +24,7 @@
#include "graphics/scalerplugin.h" #include "graphics/scalerplugin.h"
class EdgePlugin : public ScalerPluginObject { class EdgePlugin : public SourceScaler {
public: public:
EdgePlugin(); EdgePlugin();
@ -32,10 +32,10 @@ public:
virtual void deinitialize(); virtual void deinitialize();
virtual void scale(const uint8 *srcPtr, uint32 srcPitch, virtual void scale(const uint8 *srcPtr, uint32 srcPitch,
uint8 *dstPtr, uint32 dstPitch, int width, int height, int x, int y); 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, uint8 *dstPtr, uint32 dstPitch,
const uint8 *oldSrcPtr, uint32 oldSrcPitch, const uint8 *oldSrcPtr, uint32 oldSrcPitch,
int width, int height, int x, int y); int width, int height);
virtual uint increaseFactor(); virtual uint increaseFactor();
virtual uint decreaseFactor(); virtual uint decreaseFactor();
virtual uint getFactor() const { return _factor; } 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 "base/plugins.h"
#include "graphics/pixelformat.h" #include "graphics/pixelformat.h"
enum SourceType {
SRC_SCREEN = 0,
SRC_CURSOR,
SRC_OTHER,
SRC_MAX
};
class ScalerPluginObject : public PluginObject { class ScalerPluginObject : public PluginObject {
public: public:
@ -96,18 +105,29 @@ public:
* optionally call it. * optionally call it.
* *
* @see oldSourceScale * @see oldSourceScale
* @see setSource
*/ */
virtual bool useOldSrc() const { return false; } 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, virtual void setSource(byte *src, uint pitch, int width, int height, int padding, SourceType type) {
uint8 *dstPtr, uint32 dstPitch, // Should not be called unless overriden
const uint8 *oldSrcPtr, uint32 oldSrcPitch, assert(0);
int width, int height, int x, int y) { }
/**
* 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 // Should not be called unless overriden
assert(0); assert(0);
} }
@ -118,6 +138,40 @@ protected:
Graphics::PixelFormat _format; 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; typedef PluginSubclass<ScalerPluginObject> ScalerPlugin;
/** /**