mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-27 11:20:40 +00:00
BACKENDS: Drop launcherInitSize() and use 2d backend gfx manager for launcher.
This commit is contained in:
parent
d0713f1072
commit
6f69981904
@ -128,7 +128,7 @@ bool LegacySdlEventSource::handleKbdMouse(Common::Event &event) {
|
||||
|
||||
if (_km.x != oldKmX || _km.y != oldKmY) {
|
||||
if (_graphicsManager) {
|
||||
_graphicsManager->getWindow()->warpMouseInWindow((Uint16)(_km.x / MULTIPLIER), (Uint16)(_km.y / MULTIPLIER));
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->getWindow()->warpMouseInWindow((Uint16)(_km.x / MULTIPLIER), (Uint16)(_km.y / MULTIPLIER)); // ResidualVM
|
||||
}
|
||||
|
||||
event.type = Common::EVENT_MOUSEMOVE;
|
||||
@ -240,8 +240,8 @@ void LegacySdlEventSource::checkScreenChange() {
|
||||
return;
|
||||
}
|
||||
|
||||
int newMaxX = _graphicsManager->getWindowWidth() - 1;
|
||||
int newMaxY = _graphicsManager->getWindowHeight() - 1;
|
||||
int newMaxX = dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->getWindowWidth() - 1; // ResidualVM
|
||||
int newMaxY = dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->getWindowHeight() - 1; // ResidualVM
|
||||
|
||||
if (_km.x_max != newMaxX || _km.y_max != newMaxY) {
|
||||
resetKeyboardEmulation(newMaxX, newMaxY);
|
||||
|
@ -270,6 +270,9 @@ bool ResVmSdlEventSource::handleKbdMouse(Common::Event &event) {
|
||||
|
||||
updateKbdMouse();
|
||||
|
||||
if (!dynamic_cast<SdlGraphics3dManager *>(_graphicsManager))
|
||||
return false;
|
||||
|
||||
if (_km.x != oldKmX || _km.y != oldKmY) {
|
||||
SdlGraphics3dManager *graphicsManager = dynamic_cast<SdlGraphics3dManager *>(_graphicsManager);
|
||||
|
||||
|
@ -187,7 +187,13 @@ bool SdlEventSource::processMouseEvent(Common::Event &event, int x, int y, int r
|
||||
event.mouse.y = y;
|
||||
|
||||
if (_graphicsManager) {
|
||||
return _graphicsManager->notifyMousePosition(event.mouse);
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->notifyMousePosition(event.mouse);
|
||||
} else if (dynamic_cast<SdlGraphicsManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->notifyMousePosition(event.mouse);
|
||||
}
|
||||
// ResidualVM end
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -508,8 +514,15 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (ev.window.event) {
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
if (_graphicsManager)
|
||||
_graphicsManager->notifyVideoExpose();
|
||||
if (_graphicsManager) {
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->notifyVideoExpose();
|
||||
} else if (dynamic_cast<SdlGraphicsManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->notifyVideoExpose();
|
||||
}
|
||||
// ResidualVM end
|
||||
}
|
||||
return false;
|
||||
|
||||
// SDL2 documentation indicate that SDL_WINDOWEVENT_SIZE_CHANGED is sent either as a result
|
||||
@ -566,8 +579,15 @@ bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
|
||||
return true;
|
||||
#else
|
||||
case SDL_VIDEOEXPOSE:
|
||||
if (_graphicsManager)
|
||||
_graphicsManager->notifyVideoExpose();
|
||||
if (_graphicsManager) {
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->notifyVideoExpose();
|
||||
} else if (dynamic_cast<SdlGraphicsManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->notifyVideoExpose();
|
||||
}
|
||||
// ResidualVM end
|
||||
}
|
||||
return false;
|
||||
|
||||
case SDL_VIDEORESIZE:
|
||||
@ -960,8 +980,13 @@ void SdlEventSource::setEngineRunning(const bool value) {
|
||||
|
||||
bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) {
|
||||
if (_graphicsManager) {
|
||||
_graphicsManager->notifyResize(w, h);
|
||||
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->notifyResize(w, h);
|
||||
} else if (dynamic_cast<SdlGraphicsManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->notifyResize(w, h);
|
||||
}
|
||||
// ResidualVM end
|
||||
// If the screen changed, send an Common::EVENT_SCREEN_CHANGED
|
||||
int screenID = g_system->getScreenChangeID();
|
||||
if (screenID != _lastScreenID) {
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
SdlEventSource();
|
||||
virtual ~SdlEventSource();
|
||||
|
||||
void setGraphicsManager(SdlGraphics3dManager *gMan) { _graphicsManager = gMan; }
|
||||
void setGraphicsManager(GraphicsManager *gMan) { _graphicsManager = gMan; } // ResidualVM specific
|
||||
|
||||
/**
|
||||
* Gets and processes SDL events.
|
||||
@ -86,7 +86,7 @@ protected:
|
||||
/**
|
||||
* The associated graphics manager.
|
||||
*/
|
||||
SdlGraphics3dManager *_graphicsManager;
|
||||
GraphicsManager *_graphicsManager; // ResidualVM specific
|
||||
|
||||
/**
|
||||
* Search for a game controller db file and load it.
|
||||
|
@ -45,7 +45,7 @@ SdlGraphicsManager::SdlGraphicsManager(SdlEventSource *source, SdlWindow *window
|
||||
}
|
||||
|
||||
void SdlGraphicsManager::activateManager() {
|
||||
_eventSource->setGraphicsManager(dynamic_cast<SdlGraphics3dManager *>(this));
|
||||
_eventSource->setGraphicsManager(this);
|
||||
|
||||
// Register the graphics manager as a event observer
|
||||
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
|
||||
|
@ -2626,7 +2626,7 @@ void SurfaceSdlGraphicsManager::recreateScreenTexture() {
|
||||
SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) {
|
||||
deinitializeRenderer();
|
||||
|
||||
uint32 createWindowFlags = SDL_WINDOW_RESIZABLE;
|
||||
uint32 createWindowFlags = 0;//SDL_WINDOW_RESIZABLE; // ResidualVM specific
|
||||
if ((flags & SDL_FULLSCREEN) != 0) {
|
||||
createWindowFlags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
}
|
||||
|
@ -463,11 +463,6 @@ Common::KeymapperDefaultBindings *OSystem_Android::getKeymapperDefaultBindings()
|
||||
return keymapperDefaultBindings;
|
||||
}
|
||||
|
||||
// ResidualVM specific method
|
||||
void OSystem_Android::launcherInitSize(uint w, uint h) {
|
||||
dynamic_cast<AndroidGraphicsManager *>(_graphicsManager)->setupScreen(w, h, true, true, false);
|
||||
}
|
||||
|
||||
uint32 OSystem_Android::getMillis(bool skipRecord) {
|
||||
timeval curTime;
|
||||
|
||||
|
@ -193,7 +193,6 @@ public:
|
||||
virtual char *convertEncoding(const char *to, const char *from, const char *string, size_t length);
|
||||
|
||||
// ResidualVM specific method
|
||||
virtual void launcherInitSize(uint w, uint h);
|
||||
void updateEventScale(const GLESBaseTexture *tex);
|
||||
TouchControls* getTouchControls() { return &_touchControls; }
|
||||
};
|
||||
|
@ -93,6 +93,7 @@ OSystem_SDL::OSystem_SDL()
|
||||
_eventSource(0),
|
||||
_eventSourceWrapper(nullptr),
|
||||
_window(0) {
|
||||
_gfxManagerState = {};
|
||||
}
|
||||
|
||||
OSystem_SDL::~OSystem_SDL() {
|
||||
@ -105,7 +106,13 @@ OSystem_SDL::~OSystem_SDL() {
|
||||
delete _savefileManager;
|
||||
_savefileManager = 0;
|
||||
if (_graphicsManager) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->deactivateManager();
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->deactivateManager();
|
||||
} else {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->deactivateManager();
|
||||
}
|
||||
// ResidualVM end
|
||||
}
|
||||
delete _graphicsManager;
|
||||
_graphicsManager = 0;
|
||||
@ -257,7 +264,14 @@ void OSystem_SDL::initBackend() {
|
||||
#endif
|
||||
|
||||
if (_graphicsManager == 0) {
|
||||
_graphicsManager = dynamic_cast<GraphicsManager *>(new SurfaceSdlGraphics3dManager(_eventSource, _window)); // ResidualVM specific
|
||||
// ResidualVM start:
|
||||
#ifdef USE_OPENGL
|
||||
_graphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window);
|
||||
_graphicsMode = _firstGLMode;
|
||||
#else
|
||||
_graphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window);
|
||||
#endif
|
||||
// ResidualVM end
|
||||
}
|
||||
}
|
||||
|
||||
@ -296,7 +310,13 @@ void OSystem_SDL::initBackend() {
|
||||
// so the virtual keyboard can be initialized, but we have to add the
|
||||
// graphics manager as an event observer after initializing the event
|
||||
// manager.
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->activateManager();
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->activateManager();
|
||||
} else {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->activateManager();
|
||||
}
|
||||
// ResidualVM end
|
||||
}
|
||||
|
||||
// ResidualVM specific code - Start
|
||||
@ -381,7 +401,13 @@ void OSystem_SDL::detectAntiAliasingSupport() {
|
||||
|
||||
void OSystem_SDL::engineInit() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->unlockWindowSize();
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->unlockWindowSize();
|
||||
} else {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->unlockWindowSize();
|
||||
}
|
||||
// ResidualVM end
|
||||
// Disable screen saver when engine starts
|
||||
SDL_DisableScreenSaver();
|
||||
#endif
|
||||
@ -403,7 +429,13 @@ void OSystem_SDL::engineInit() {
|
||||
|
||||
void OSystem_SDL::engineDone() {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->unlockWindowSize();
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->unlockWindowSize();
|
||||
} else {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->unlockWindowSize();
|
||||
}
|
||||
// ResidualVM end
|
||||
SDL_EnableScreenSaver();
|
||||
#endif
|
||||
#ifdef USE_TASKBAR
|
||||
@ -489,9 +521,17 @@ void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool
|
||||
switchedManager = true;
|
||||
}
|
||||
|
||||
if (dynamic_cast<SdlGraphicsManager *>(_graphicsManager)) {
|
||||
_gfxManagerState = dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->getState();
|
||||
}
|
||||
|
||||
if (switchedManager) {
|
||||
SdlGraphics3dManager *sdlGraphicsManager = dynamic_cast<SdlGraphics3dManager *>(_graphicsManager);
|
||||
sdlGraphicsManager->deactivateManager();
|
||||
SdlGraphics3dManager *sdlGraphicsManager;
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->deactivateManager();
|
||||
} else {
|
||||
dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->deactivateManager();
|
||||
}
|
||||
delete _graphicsManager;
|
||||
|
||||
if (accel3d) {
|
||||
@ -510,16 +550,6 @@ Common::Array<uint> OSystem_SDL::getSupportedAntiAliasingLevels() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
void OSystem_SDL::launcherInitSize(uint w, uint h) {
|
||||
Common::String rendererConfig = ConfMan.get("renderer");
|
||||
Graphics::RendererType desiredRendererType = Graphics::parseRendererTypeCode(rendererConfig);
|
||||
Graphics::RendererType matchingRendererType = Graphics::getBestMatchingAvailableRendererType(desiredRendererType);
|
||||
|
||||
bool fullscreen = ConfMan.getBool("fullscreen");
|
||||
|
||||
setupScreen(w, h, fullscreen, matchingRendererType != Graphics::kRendererTypeTinyGL);
|
||||
}
|
||||
|
||||
// End of ResidualVM specific code
|
||||
|
||||
void OSystem_SDL::quit() {
|
||||
@ -535,8 +565,15 @@ void OSystem_SDL::fatalError() {
|
||||
Common::KeymapArray OSystem_SDL::getGlobalKeymaps() {
|
||||
Common::KeymapArray globalMaps = BaseBackend::getGlobalKeymaps();
|
||||
|
||||
SdlGraphics3dManager *graphicsManager = dynamic_cast<SdlGraphics3dManager *>(_graphicsManager);
|
||||
globalMaps.push_back(graphicsManager->getKeymap());
|
||||
// ResidualVM start:
|
||||
Common::Keymap *keymap;
|
||||
if (dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)) {
|
||||
keymap = dynamic_cast<SdlGraphics3dManager *>(_graphicsManager)->getKeymap();
|
||||
} else {
|
||||
keymap = dynamic_cast<SdlGraphicsManager *>(_graphicsManager)->getKeymap();
|
||||
}
|
||||
globalMaps.push_back(keymap);
|
||||
// ResidualVM end
|
||||
|
||||
return globalMaps;
|
||||
}
|
||||
@ -745,6 +782,52 @@ int OSystem_SDL::getDefaultGraphicsMode() const {
|
||||
}
|
||||
|
||||
bool OSystem_SDL::setGraphicsMode(int mode) {
|
||||
// ResidualVM start:
|
||||
if (dynamic_cast<OpenGLSdlGraphics3dManager *>(_graphicsManager) ||
|
||||
dynamic_cast<SurfaceSdlGraphics3dManager *>(_graphicsManager)) {
|
||||
if (dynamic_cast<OpenGLSdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<OpenGLSdlGraphics3dManager *>(_graphicsManager)->deactivateManager();
|
||||
}
|
||||
if (dynamic_cast<SurfaceSdlGraphics3dManager *>(_graphicsManager)) {
|
||||
dynamic_cast<SurfaceSdlGraphics3dManager *>(_graphicsManager)->deactivateManager();
|
||||
}
|
||||
delete _graphicsManager;
|
||||
|
||||
SdlGraphicsManager *sdlGraphicsManager = nullptr;
|
||||
if (mode < _firstGLMode) {
|
||||
debug(1, "switching to plain SDL graphics");
|
||||
_graphicsManager = sdlGraphicsManager = new SurfaceSdlGraphicsManager(_eventSource, _window);
|
||||
} else if (mode >= _firstGLMode) {
|
||||
debug(1, "switching to OpenGL graphics");
|
||||
_graphicsManager = sdlGraphicsManager = new OpenGLSdlGraphicsManager(_eventSource, _window);
|
||||
}
|
||||
|
||||
_graphicsMode = mode;
|
||||
|
||||
assert(sdlGraphicsManager);
|
||||
sdlGraphicsManager->activateManager();
|
||||
|
||||
// This failing will probably have bad consequences...
|
||||
if (!sdlGraphicsManager->setState(_gfxManagerState)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Next setup the cursor again
|
||||
CursorMan.pushCursor(0, 0, 0, 0, 0, 0);
|
||||
CursorMan.popCursor();
|
||||
|
||||
// Next setup cursor palette if needed
|
||||
if (_graphicsManager->getFeatureState(kFeatureCursorPalette)) {
|
||||
CursorMan.pushCursorPalette(0, 0, 0);
|
||||
CursorMan.popCursorPalette();
|
||||
}
|
||||
|
||||
_graphicsManager->beginGFXTransaction();
|
||||
// Oh my god if this failed the client code might just explode.
|
||||
return _graphicsManager->setGraphicsMode(_graphicsModeIds[mode]);
|
||||
}
|
||||
// ResidualVM end
|
||||
|
||||
if (_graphicsModes.empty()) {
|
||||
return _graphicsManager->setGraphicsMode(mode);
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ public:
|
||||
virtual void setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) override;
|
||||
Common::Array<uint> getSupportedAntiAliasingLevels() const override;
|
||||
#endif
|
||||
virtual void launcherInitSize(uint w, uint h) override;
|
||||
// ResidualVM - End
|
||||
|
||||
protected:
|
||||
@ -132,6 +131,8 @@ protected:
|
||||
*/
|
||||
SdlWindow *_window;
|
||||
|
||||
SdlGraphicsManager::State _gfxManagerState; // ResidualVM
|
||||
|
||||
// ResidualVM specific code - start
|
||||
#ifdef USE_OPENGL
|
||||
// Graphics capabilities
|
||||
|
@ -159,8 +159,7 @@ static Common::Error runGame(const Plugin *plugin, OSystem &system, const Common
|
||||
Common::Error err = Common::kNoError;
|
||||
Engine *engine = 0;
|
||||
|
||||
// Disabled in ResidualVM:
|
||||
#if 0//defined(SDL_BACKEND) && defined(USE_OPENGL) && defined(USE_RGB_COLOR)
|
||||
#if defined(SDL_BACKEND) && defined(USE_OPENGL) && defined(USE_RGB_COLOR)
|
||||
// HACK: We set up the requested graphics mode setting here to allow the
|
||||
// backend to switch from Surface SDL to OpenGL if necessary. This is
|
||||
// needed because otherwise the g_system->getSupportedFormats might return
|
||||
@ -328,7 +327,6 @@ static void setupGraphics(OSystem &system) {
|
||||
system.setGraphicsMode(ConfMan.get("gfx_mode").c_str());
|
||||
|
||||
system.initSize(320, 200);
|
||||
system.launcherInitSize(640, 480); //ResidualVM specific
|
||||
|
||||
if (ConfMan.hasKey("aspect_ratio"))
|
||||
system.setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio"));
|
||||
|
@ -128,7 +128,6 @@ void OSystem::destroy() {
|
||||
}
|
||||
|
||||
bool OSystem::setGraphicsMode(const char *name) {
|
||||
return true; //ResidualVM not use it
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
|
@ -859,15 +859,6 @@ public:
|
||||
*/
|
||||
virtual void initSizeHint(const Graphics::ModeList &modes) {}
|
||||
|
||||
/**
|
||||
* !!! ResidualVM specific method !!!
|
||||
* Set the size of the launcher virtual screen.
|
||||
*
|
||||
* @param width the new virtual screen width
|
||||
* @param height the new virtual screen height
|
||||
*/
|
||||
virtual void launcherInitSize(uint width, uint height) {};
|
||||
|
||||
/**
|
||||
* !!! Not used in ResidualVM !!!
|
||||
*
|
||||
|
7
configure
vendored
7
configure
vendored
@ -134,8 +134,7 @@ done
|
||||
# Default settings
|
||||
#
|
||||
#ResidualVM defaults: sdlnet=no libcurl=no flac=no seq_midi=no sndio=no timidity=no
|
||||
# a52=no faad=no fluidsynth=no mt32emu=no lua=no build_scalers=no
|
||||
# build_hq_scalers=no nuked_opl=no tts=no osxdockplugin=no discord=no
|
||||
# a52=no faad=no fluidsynth=no mt32emu=no lua=no nuked_opl=no tts=no osxdockplugin=no discord=no
|
||||
#
|
||||
# Default lib behavior yes/no/auto
|
||||
_sdl=no
|
||||
@ -189,8 +188,8 @@ _verbose_build=no
|
||||
_text_console=no
|
||||
_mt32emu=no
|
||||
_lua=no
|
||||
_build_scalers=no
|
||||
_build_hq_scalers=no
|
||||
_build_scalers=yes
|
||||
_build_hq_scalers=yes
|
||||
_enable_prof=no
|
||||
_enable_asan=no
|
||||
_enable_tsan=no
|
||||
|
@ -412,7 +412,6 @@ void GUIErrorMessage(const Common::U32String &msg, const char *url) {
|
||||
g_system->beginGFXTransaction();
|
||||
initCommonGFX();
|
||||
g_system->initSize(320, 200);
|
||||
g_system->launcherInitSize(640, 480);//ResidualVM specific
|
||||
if (g_system->endGFXTransaction() == OSystem::kTransactionSuccess) {
|
||||
if (url) {
|
||||
GUI::MessageDialogWithURL dialog(msg, url);
|
||||
|
412
graphics/scaler/2xsai.cpp
Normal file
412
graphics/scaler/2xsai.cpp
Normal file
@ -0,0 +1,412 @@
|
||||
/* 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/scaler/intern.h"
|
||||
|
||||
|
||||
|
||||
static inline int GetResult(uint32 A, uint32 B, uint32 C, uint32 D) {
|
||||
const bool ac = (A==C);
|
||||
const bool bc = (B==C);
|
||||
const int x1 = ac;
|
||||
const int y1 = (bc & !ac);
|
||||
const bool ad = (A==D);
|
||||
const bool bd = (B==D);
|
||||
const int x2 = ad;
|
||||
const int y2 = (bd & !ad);
|
||||
const int x = x1+x2;
|
||||
const int y = y1+y2;
|
||||
return (y>>1) - (x>>1);
|
||||
}
|
||||
|
||||
#define interpolate_1_1 interpolate16_1_1<ColorMask>
|
||||
#define interpolate_3_1 interpolate16_3_1<ColorMask>
|
||||
#define interpolate_6_1_1 interpolate16_6_1_1<ColorMask>
|
||||
#define interpolate_1_1_1_1 interpolate16_1_1_1_1<ColorMask>
|
||||
|
||||
template<typename ColorMask>
|
||||
void Super2xSaITemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
const uint16 *bP;
|
||||
uint16 *dP;
|
||||
const uint32 nextlineSrc = srcPitch >> 1;
|
||||
|
||||
while (height--) {
|
||||
bP = (const uint16 *)srcPtr;
|
||||
dP = (uint16 *)dstPtr;
|
||||
|
||||
for (int i = 0; i < width; ++i) {
|
||||
unsigned color4, color5, color6;
|
||||
unsigned color1, color2, color3;
|
||||
unsigned colorA0, colorA1, colorA2, colorA3;
|
||||
unsigned colorB0, colorB1, colorB2, colorB3;
|
||||
unsigned colorS1, colorS2;
|
||||
unsigned product1a, product1b, product2a, product2b;
|
||||
|
||||
//--------------------------------------- B1 B2
|
||||
// 4 5 6 S2
|
||||
// 1 2 3 S1
|
||||
// A1 A2
|
||||
|
||||
colorB0 = *(bP - nextlineSrc - 1);
|
||||
colorB1 = *(bP - nextlineSrc);
|
||||
colorB2 = *(bP - nextlineSrc + 1);
|
||||
colorB3 = *(bP - nextlineSrc + 2);
|
||||
|
||||
color4 = *(bP - 1);
|
||||
color5 = *(bP);
|
||||
color6 = *(bP + 1);
|
||||
colorS2 = *(bP + 2);
|
||||
|
||||
color1 = *(bP + nextlineSrc - 1);
|
||||
color2 = *(bP + nextlineSrc);
|
||||
color3 = *(bP + nextlineSrc + 1);
|
||||
colorS1 = *(bP + nextlineSrc + 2);
|
||||
|
||||
colorA0 = *(bP + 2 * nextlineSrc - 1);
|
||||
colorA1 = *(bP + 2 * nextlineSrc);
|
||||
colorA2 = *(bP + 2 * nextlineSrc + 1);
|
||||
colorA3 = *(bP + 2 * nextlineSrc + 2);
|
||||
|
||||
//--------------------------------------
|
||||
if (color2 == color6 && color5 != color3) {
|
||||
product2b = product1b = color2;
|
||||
} else if (color5 == color3 && color2 != color6) {
|
||||
product2b = product1b = color5;
|
||||
} else if (color5 == color3 && color2 == color6) {
|
||||
int r = 0;
|
||||
|
||||
r += GetResult(color6, color5, color1, colorA1);
|
||||
r += GetResult(color6, color5, color4, colorB1);
|
||||
r += GetResult(color6, color5, colorA2, colorS1);
|
||||
r += GetResult(color6, color5, colorB2, colorS2);
|
||||
|
||||
if (r > 0)
|
||||
product2b = product1b = color6;
|
||||
else if (r < 0)
|
||||
product2b = product1b = color5;
|
||||
else {
|
||||
product2b = product1b = interpolate_1_1(color5, color6);
|
||||
}
|
||||
} else {
|
||||
if (color6 == color3 && color3 == colorA1 && color2 != colorA2 && color3 != colorA0)
|
||||
product2b = interpolate_3_1(color3, color2);
|
||||
else if (color5 == color2 && color2 == colorA2 && colorA1 != color3 && color2 != colorA3)
|
||||
product2b = interpolate_3_1(color2, color3);
|
||||
else
|
||||
product2b = interpolate_1_1(color2, color3);
|
||||
|
||||
if (color6 == color3 && color6 == colorB1 && color5 != colorB2 && color6 != colorB0)
|
||||
product1b = interpolate_3_1(color6, color5);
|
||||
else if (color5 == color2 && color5 == colorB2 && colorB1 != color6 && color5 != colorB3)
|
||||
product1b = interpolate_3_1(color5, color6);
|
||||
else
|
||||
product1b = interpolate_1_1(color5, color6);
|
||||
}
|
||||
|
||||
if (color5 == color3 && color2 != color6 && color4 == color5 && color5 != colorA2)
|
||||
product2a = interpolate_1_1(color2, color5);
|
||||
else if (color5 == color1 && color6 == color5 && color4 != color2 && color5 != colorA0)
|
||||
product2a = interpolate_1_1(color2, color5);
|
||||
else
|
||||
product2a = color2;
|
||||
|
||||
if (color2 == color6 && color5 != color3 && color1 == color2 && color2 != colorB2)
|
||||
product1a = interpolate_1_1(color2, color5);
|
||||
else if (color4 == color2 && color3 == color2 && color1 != color5 && color2 != colorB0)
|
||||
product1a = interpolate_1_1(color2, color5);
|
||||
else
|
||||
product1a = color5;
|
||||
|
||||
*(dP + 0) = (uint16) product1a;
|
||||
*(dP + 1) = (uint16) product1b;
|
||||
*(dP + dstPitch/2 + 0) = (uint16) product2a;
|
||||
*(dP + dstPitch/2 + 1) = (uint16) product2b;
|
||||
|
||||
bP += 1;
|
||||
dP += 2;
|
||||
}
|
||||
|
||||
srcPtr += srcPitch;
|
||||
dstPtr += dstPitch * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void Super2xSaI(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
extern int gBitFormat;
|
||||
if (gBitFormat == 565)
|
||||
Super2xSaITemplate<Graphics::ColorMasks<565> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
else
|
||||
Super2xSaITemplate<Graphics::ColorMasks<555> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
}
|
||||
|
||||
template<typename ColorMask>
|
||||
void SuperEagleTemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
const uint16 *bP;
|
||||
uint16 *dP;
|
||||
const uint32 nextlineSrc = srcPitch >> 1;
|
||||
|
||||
while (height--) {
|
||||
bP = (const uint16 *)srcPtr;
|
||||
dP = (uint16 *)dstPtr;
|
||||
for (int i = 0; i < width; ++i) {
|
||||
unsigned color4, color5, color6;
|
||||
unsigned color1, color2, color3;
|
||||
unsigned colorA1, colorA2, colorB1, colorB2, colorS1, colorS2;
|
||||
unsigned product1a, product1b, product2a, product2b;
|
||||
|
||||
colorB1 = *(bP - nextlineSrc);
|
||||
colorB2 = *(bP - nextlineSrc + 1);
|
||||
|
||||
color4 = *(bP - 1);
|
||||
color5 = *(bP);
|
||||
color6 = *(bP + 1);
|
||||
colorS2 = *(bP + 2);
|
||||
|
||||
color1 = *(bP + nextlineSrc - 1);
|
||||
color2 = *(bP + nextlineSrc);
|
||||
color3 = *(bP + nextlineSrc + 1);
|
||||
colorS1 = *(bP + nextlineSrc + 2);
|
||||
|
||||
colorA1 = *(bP + 2 * nextlineSrc);
|
||||
colorA2 = *(bP + 2 * nextlineSrc + 1);
|
||||
|
||||
// --------------------------------------
|
||||
if (color5 != color3) {
|
||||
if (color2 == color6) {
|
||||
product1b = product2a = color2;
|
||||
if ((color1 == color2) || (color6 == colorB2)) {
|
||||
product1a = interpolate_3_1(color2, color5);
|
||||
} else {
|
||||
product1a = interpolate_1_1(color5, color6);
|
||||
}
|
||||
|
||||
if ((color6 == colorS2) || (color2 == colorA1)) {
|
||||
product2b = interpolate_3_1(color2, color3);
|
||||
} else {
|
||||
product2b = interpolate_1_1(color2, color3);
|
||||
}
|
||||
} else {
|
||||
product2b = interpolate_6_1_1(color3, color2, color6);
|
||||
product1a = interpolate_6_1_1(color5, color2, color6);
|
||||
|
||||
product2a = interpolate_6_1_1(color2, color5, color3);
|
||||
product1b = interpolate_6_1_1(color6, color5, color3);
|
||||
}
|
||||
} else {
|
||||
if (color2 != color6) {
|
||||
product2b = product1a = color5;
|
||||
|
||||
if ((colorB1 == color5) || (color3 == colorS1)) {
|
||||
product1b = interpolate_3_1(color5, color6);
|
||||
} else {
|
||||
product1b = interpolate_1_1(color5, color6);
|
||||
}
|
||||
|
||||
if ((color3 == colorA2) || (color4 == color5)) {
|
||||
product2a = interpolate_3_1(color5, color2);
|
||||
} else {
|
||||
product2a = interpolate_1_1(color2, color3);
|
||||
}
|
||||
} else {
|
||||
int r = 0;
|
||||
|
||||
r += GetResult(color6, color5, color1, colorA1);
|
||||
r += GetResult(color6, color5, color4, colorB1);
|
||||
r += GetResult(color6, color5, colorA2, colorS1);
|
||||
r += GetResult(color6, color5, colorB2, colorS2);
|
||||
|
||||
if (r > 0) {
|
||||
product1b = product2a = color2;
|
||||
product1a = product2b = interpolate_1_1(color5, color6);
|
||||
} else if (r < 0) {
|
||||
product2b = product1a = color5;
|
||||
product1b = product2a = interpolate_1_1(color5, color6);
|
||||
} else {
|
||||
product2b = product1a = color5;
|
||||
product1b = product2a = color2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*(dP + 0) = (uint16) product1a;
|
||||
*(dP + 1) = (uint16) product1b;
|
||||
*(dP + dstPitch/2 + 0) = (uint16) product2a;
|
||||
*(dP + dstPitch/2 + 1) = (uint16) product2b;
|
||||
|
||||
bP += 1;
|
||||
dP += 2;
|
||||
}
|
||||
|
||||
srcPtr += srcPitch;
|
||||
dstPtr += dstPitch * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SuperEagle(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
extern int gBitFormat;
|
||||
if (gBitFormat == 565)
|
||||
SuperEagleTemplate<Graphics::ColorMasks<565> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
else
|
||||
SuperEagleTemplate<Graphics::ColorMasks<555> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
}
|
||||
|
||||
template<typename ColorMask>
|
||||
void _2xSaITemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
const uint16 *bP;
|
||||
uint16 *dP;
|
||||
const uint32 nextlineSrc = srcPitch >> 1;
|
||||
|
||||
while (height--) {
|
||||
bP = (const uint16 *)srcPtr;
|
||||
dP = (uint16 *)dstPtr;
|
||||
|
||||
for (int i = 0; i < width; ++i) {
|
||||
|
||||
unsigned colorA, colorB, colorC, colorD,
|
||||
colorE, colorF, colorG, colorH, colorI, colorJ, colorK, colorL, colorM, colorN, colorO;
|
||||
unsigned product, product1, product2;
|
||||
|
||||
//---------------------------------------
|
||||
// Map of the pixels: I|E F|J
|
||||
// G|A B|K
|
||||
// H|C D|L
|
||||
// M|N O|P
|
||||
colorI = *(bP - nextlineSrc - 1);
|
||||
colorE = *(bP - nextlineSrc);
|
||||
colorF = *(bP - nextlineSrc + 1);
|
||||
colorJ = *(bP - nextlineSrc + 2);
|
||||
|
||||
colorG = *(bP - 1);
|
||||
colorA = *(bP);
|
||||
colorB = *(bP + 1);
|
||||
colorK = *(bP + 2);
|
||||
|
||||
colorH = *(bP + nextlineSrc - 1);
|
||||
colorC = *(bP + nextlineSrc);
|
||||
colorD = *(bP + nextlineSrc + 1);
|
||||
colorL = *(bP + nextlineSrc + 2);
|
||||
|
||||
colorM = *(bP + 2 * nextlineSrc - 1);
|
||||
colorN = *(bP + 2 * nextlineSrc);
|
||||
colorO = *(bP + 2 * nextlineSrc + 1);
|
||||
|
||||
if ((colorA == colorD) && (colorB != colorC)) {
|
||||
if (((colorA == colorE) && (colorB == colorL)) ||
|
||||
((colorA == colorC) && (colorA == colorF) && (colorB != colorE) && (colorB == colorJ))) {
|
||||
product = colorA;
|
||||
} else {
|
||||
product = interpolate_1_1(colorA, colorB);
|
||||
}
|
||||
|
||||
if (((colorA == colorG) && (colorC == colorO)) ||
|
||||
((colorA == colorB) && (colorA == colorH) && (colorG != colorC) && (colorC == colorM))) {
|
||||
product1 = colorA;
|
||||
} else {
|
||||
product1 = interpolate_1_1(colorA, colorC);
|
||||
}
|
||||
product2 = colorA;
|
||||
} else if ((colorB == colorC) && (colorA != colorD)) {
|
||||
if (((colorB == colorF) && (colorA == colorH)) ||
|
||||
((colorB == colorE) && (colorB == colorD) && (colorA != colorF) && (colorA == colorI))) {
|
||||
product = colorB;
|
||||
} else {
|
||||
product = interpolate_1_1(colorA, colorB);
|
||||
}
|
||||
|
||||
if (((colorC == colorH) && (colorA == colorF)) ||
|
||||
((colorC == colorG) && (colorC == colorD) && (colorA != colorH) && (colorA == colorI))) {
|
||||
product1 = colorC;
|
||||
} else {
|
||||
product1 = interpolate_1_1(colorA, colorC);
|
||||
}
|
||||
product2 = colorB;
|
||||
} else if ((colorA == colorD) && (colorB == colorC)) {
|
||||
if (colorA == colorB) {
|
||||
product = colorA;
|
||||
product1 = colorA;
|
||||
product2 = colorA;
|
||||
} else {
|
||||
int r = 0;
|
||||
|
||||
product1 = interpolate_1_1(colorA, colorC);
|
||||
product = interpolate_1_1(colorA, colorB);
|
||||
|
||||
r += GetResult(colorA, colorB, colorG, colorE);
|
||||
r -= GetResult(colorB, colorA, colorK, colorF);
|
||||
r -= GetResult(colorB, colorA, colorH, colorN);
|
||||
r += GetResult(colorA, colorB, colorL, colorO);
|
||||
|
||||
if (r > 0)
|
||||
product2 = colorA;
|
||||
else if (r < 0)
|
||||
product2 = colorB;
|
||||
else {
|
||||
product2 = interpolate_1_1_1_1(colorA, colorB, colorC, colorD);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
product2 = interpolate_1_1_1_1(colorA, colorB, colorC, colorD);
|
||||
|
||||
if ((colorA == colorC) && (colorA == colorF)
|
||||
&& (colorB != colorE) && (colorB == colorJ)) {
|
||||
product = colorA;
|
||||
} else if ((colorB == colorE) && (colorB == colorD)
|
||||
&& (colorA != colorF) && (colorA == colorI)) {
|
||||
product = colorB;
|
||||
} else {
|
||||
product = interpolate_1_1(colorA, colorB);
|
||||
}
|
||||
|
||||
if ((colorA == colorB) && (colorA == colorH)
|
||||
&& (colorG != colorC) && (colorC == colorM)) {
|
||||
product1 = colorA;
|
||||
} else if ((colorC == colorG) && (colorC == colorD)
|
||||
&& (colorA != colorH) && (colorA == colorI)) {
|
||||
product1 = colorC;
|
||||
} else {
|
||||
product1 = interpolate_1_1(colorA, colorC);
|
||||
}
|
||||
}
|
||||
|
||||
*(dP + 0) = (uint16) colorA;
|
||||
*(dP + 1) = (uint16) product;
|
||||
*(dP + dstPitch/2 + 0) = (uint16) product1;
|
||||
*(dP + dstPitch/2 + 1) = (uint16) product2;
|
||||
|
||||
bP += 1;
|
||||
dP += 2;
|
||||
}
|
||||
|
||||
srcPtr += srcPitch;
|
||||
dstPtr += dstPitch * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _2xSaI(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
extern int gBitFormat;
|
||||
if (gBitFormat == 565)
|
||||
_2xSaITemplate<Graphics::ColorMasks<565> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
else
|
||||
_2xSaITemplate<Graphics::ColorMasks<555> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
}
|
276
graphics/scaler/aspect.cpp
Normal file
276
graphics/scaler/aspect.cpp
Normal file
@ -0,0 +1,276 @@
|
||||
/* 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/scaler/intern.h"
|
||||
#include "graphics/scaler/aspect.h"
|
||||
|
||||
#ifdef USE_ARM_NEON_ASPECT_CORRECTOR
|
||||
#include <arm_neon.h>
|
||||
#endif
|
||||
|
||||
#define kSuperFastAndUglyAspectMode 0 // No interpolation at all, but super-fast
|
||||
#define kVeryFastAndGoodAspectMode 1 // Good quality with very good speed
|
||||
#define kFastAndVeryGoodAspectMode 2 // Very good quality with good speed
|
||||
#define kSlowAndPerfectAspectMode 3 // Accurate but slow code
|
||||
|
||||
#define ASPECT_MODE kVeryFastAndGoodAspectMode
|
||||
|
||||
|
||||
#if ASPECT_MODE == kSlowAndPerfectAspectMode
|
||||
|
||||
template<typename ColorMask, int scale>
|
||||
static inline uint16 interpolate5(uint16 A, uint16 B) {
|
||||
uint16 r = (uint16)(((A & ColorMask::kRedBlueMask & 0xFF00) * scale + (B & ColorMask::kRedBlueMask & 0xFF00) * (5 - scale)) / 5);
|
||||
uint16 g = (uint16)(((A & ColorMask::kGreenMask) * scale + (B & ColorMask::kGreenMask) * (5 - scale)) / 5);
|
||||
uint16 b = (uint16)(((A & ColorMask::kRedBlueMask & 0x00FF) * scale + (B & ColorMask::kRedBlueMask & 0x00FF) * (5 - scale)) / 5);
|
||||
|
||||
return (uint16)((r & ColorMask::kRedBlueMask & 0xFF00) | (g & ColorMask::kGreenMask) | (b & ColorMask::kRedBlueMask & 0x00FF));
|
||||
}
|
||||
|
||||
|
||||
template<typename ColorMask, int scale>
|
||||
static inline void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width) {
|
||||
// Accurate but slightly slower code
|
||||
while (width--) {
|
||||
*dst++ = interpolate5<ColorMask, scale>(*srcA++, *srcB++);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASPECT_MODE == kVeryFastAndGoodAspectMode
|
||||
|
||||
#ifdef USE_ARM_NEON_ASPECT_CORRECTOR
|
||||
|
||||
template<typename ColorMask>
|
||||
static void interpolate5LineNeon(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width, int k1, int k2) {
|
||||
uint16x4_t kRedBlueMask_4 = vdup_n_u16(ColorMask::kRedBlueMask);
|
||||
uint16x4_t kGreenMask_4 = vdup_n_u16(ColorMask::kGreenMask);
|
||||
uint16x4_t k1_4 = vdup_n_u16(k1);
|
||||
uint16x4_t k2_4 = vdup_n_u16(k2);
|
||||
while (width >= 4) {
|
||||
uint16x4_t srcA_4 = vld1_u16(srcA);
|
||||
uint16x4_t srcB_4 = vld1_u16(srcB);
|
||||
uint16x4_t p1_4 = srcB_4;
|
||||
uint16x4_t p2_4 = srcA_4;
|
||||
|
||||
uint16x4_t p1_rb_4 = vand_u16(p1_4, kRedBlueMask_4);
|
||||
uint16x4_t p1_g_4 = vand_u16(p1_4, kGreenMask_4);
|
||||
uint16x4_t p2_rb_4 = vand_u16(p2_4, kRedBlueMask_4);
|
||||
uint16x4_t p2_g_4 = vand_u16(p2_4, kGreenMask_4);
|
||||
|
||||
uint32x4_t tmp_rb_4 = vshrq_n_u32(vmlal_u16(vmull_u16(p2_rb_4, k2_4), p1_rb_4, k1_4), 3);
|
||||
uint32x4_t tmp_g_4 = vshrq_n_u32(vmlal_u16(vmull_u16(p2_g_4, k2_4), p1_g_4, k1_4), 3);
|
||||
uint16x4_t p_rb_4 = vmovn_u32(tmp_rb_4);
|
||||
p_rb_4 = vand_u16(p_rb_4, kRedBlueMask_4);
|
||||
uint16x4_t p_g_4 = vmovn_u32(tmp_g_4);
|
||||
p_g_4 = vand_u16(p_g_4, kGreenMask_4);
|
||||
|
||||
uint16x4_t result_4 = p_rb_4 | p_g_4;
|
||||
vst1_u16(dst, result_4);
|
||||
|
||||
dst += 4;
|
||||
srcA += 4;
|
||||
srcB += 4;
|
||||
width -= 4;
|
||||
}
|
||||
}
|
||||
#endif // USE_ARM_NEON_ASPECT_CORRECTOR
|
||||
|
||||
template<typename ColorMask, int scale>
|
||||
static void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width) {
|
||||
if (scale == 1) {
|
||||
#ifdef USE_NEON_ASPECT_CORRECTOR
|
||||
int width4 = width & ~3;
|
||||
interpolate5LineNeon<ColorMask>(dst, srcA, srcB, width4, 7, 1);
|
||||
srcA += width4;
|
||||
srcB += width4;
|
||||
dst += width4;
|
||||
width -= width4;
|
||||
#endif // USE_ARM_NEON_ASPECT_CORRECTOR
|
||||
while (width--) {
|
||||
*dst++ = interpolate16_7_1<ColorMask>(*srcB++, *srcA++);
|
||||
}
|
||||
} else {
|
||||
#ifdef USE_ARM_NEON_ASPECT_CORRECTOR
|
||||
int width4 = width & ~3;
|
||||
interpolate5LineNeon<ColorMask>(dst, srcA, srcB, width4, 5, 3);
|
||||
srcA += width4;
|
||||
srcB += width4;
|
||||
dst += width4;
|
||||
width -= width4;
|
||||
#endif // USE_ARM_NEON_ASPECT_CORRECTOR
|
||||
while (width--) {
|
||||
*dst++ = interpolate16_5_3<ColorMask>(*srcB++, *srcA++);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ASPECT_MODE == kFastAndVeryGoodAspectMode
|
||||
|
||||
template<typename ColorMask, int scale>
|
||||
static inline void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width) {
|
||||
// For efficiency reasons we blit two pixels at a time, so it is important
|
||||
// that makeRectStretchable() guarantees that the width is even and that
|
||||
// the rect starts on a well-aligned address. (Even where unaligned memory
|
||||
// access is allowed there may be a speed penalty for it.)
|
||||
|
||||
// These asserts are disabled for maximal speed; but I leave them in here
|
||||
// in case other people want to test if the memory alignment (to an
|
||||
// address divisible by 4) is really working properly.
|
||||
//assert(((int)dst & 3) == 0);
|
||||
//assert(((int)srcA & 3) == 0);
|
||||
//assert(((int)srcB & 3) == 0);
|
||||
//assert((width & 1) == 0);
|
||||
|
||||
width /= 2;
|
||||
const uint32 *sA = (const uint32 *)srcA;
|
||||
const uint32 *sB = (const uint32 *)srcB;
|
||||
uint32 *d = (uint32 *)dst;
|
||||
if (scale == 1) {
|
||||
while (width--) {
|
||||
*d++ = interpolate32_3_1<ColorMask>(*sB++, *sA++);
|
||||
}
|
||||
} else {
|
||||
while (width--) {
|
||||
*d++ = interpolate32_1_1<ColorMask>(*sB++, *sA++);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void makeRectStretchable(int &x, int &y, int &w, int &h, bool interpolate) {
|
||||
#if ASPECT_MODE != kSuperFastAndUglyAspectMode
|
||||
if (!interpolate)
|
||||
return;
|
||||
int m = real2Aspect(y) % 6;
|
||||
|
||||
// Ensure that the rect will start on a line that won't have its
|
||||
// colors changed by the stretching function.
|
||||
if (m != 0 && m != 5) {
|
||||
y -= m;
|
||||
h += m;
|
||||
}
|
||||
|
||||
#if ASPECT_MODE == kVeryFastAndGoodAspectMode
|
||||
// Force x to be even, to ensure aligned memory access (this assumes
|
||||
// that each line starts at an even memory location, but that should
|
||||
// be the case on every target anyway).
|
||||
if (x & 1) {
|
||||
x--;
|
||||
w++;
|
||||
}
|
||||
|
||||
// Finally force the width to be even, since we blit 2 pixels at a time.
|
||||
// While this means we may sometimes blit one column more than necessary,
|
||||
// this should actually be faster than having the check for the
|
||||
if (w & 1)
|
||||
w++;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Stretch a 16bpp image vertically by factor 1.2. Used to correct the
|
||||
* aspect-ratio in games using 320x200 pixel graphics with non-qudratic
|
||||
* pixels. Applying this method effectively turns that into 320x240, which
|
||||
* provides the correct aspect-ratio on modern displays.
|
||||
*
|
||||
* The image would normally have occupied y coordinates origSrcY through
|
||||
* origSrcY + height - 1.
|
||||
*
|
||||
* However, we have already placed it at srcY - the aspect-corrected y
|
||||
* coordinate - to allow in-place stretching.
|
||||
*
|
||||
* Therefore, the source image now occupies Y coordinates srcY through
|
||||
* srcY + height - 1, and it should be stretched to Y coordinates srcY
|
||||
* through real2Aspect(srcY + height - 1).
|
||||
*/
|
||||
|
||||
int stretch200To240Nearest(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY) {
|
||||
int maxDstY = real2Aspect(origSrcY + height - 1);
|
||||
int y;
|
||||
const uint8 *startSrcPtr = buf + srcX * 2 + (srcY - origSrcY) * pitch;
|
||||
uint8 *dstPtr = buf + srcX * 2 + maxDstY * pitch;
|
||||
|
||||
for (y = maxDstY; y >= srcY; y--) {
|
||||
const uint8 *srcPtr = startSrcPtr + aspect2Real(y) * pitch;
|
||||
if (srcPtr == dstPtr)
|
||||
break;
|
||||
memcpy(dstPtr, srcPtr, sizeof(uint16) * width);
|
||||
dstPtr -= pitch;
|
||||
}
|
||||
|
||||
return 1 + maxDstY - srcY;
|
||||
}
|
||||
|
||||
template<typename ColorMask>
|
||||
int stretch200To240Interpolated(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY) {
|
||||
int maxDstY = real2Aspect(origSrcY + height - 1);
|
||||
int y;
|
||||
const uint8 *startSrcPtr = buf + srcX * 2 + (srcY - origSrcY) * pitch;
|
||||
uint8 *dstPtr = buf + srcX * 2 + maxDstY * pitch;
|
||||
|
||||
for (y = maxDstY; y >= srcY; y--) {
|
||||
const uint8 *srcPtr = startSrcPtr + aspect2Real(y) * pitch;
|
||||
switch (y % 6) {
|
||||
case 0:
|
||||
case 5:
|
||||
if (srcPtr != dstPtr)
|
||||
memcpy(dstPtr, srcPtr, sizeof(uint16) * width);
|
||||
break;
|
||||
case 1:
|
||||
interpolate5Line<ColorMask, 1>((uint16 *)dstPtr, (const uint16 *)(srcPtr - pitch), (const uint16 *)srcPtr, width);
|
||||
break;
|
||||
case 2:
|
||||
interpolate5Line<ColorMask, 2>((uint16 *)dstPtr, (const uint16 *)(srcPtr - pitch), (const uint16 *)srcPtr, width);
|
||||
break;
|
||||
case 3:
|
||||
interpolate5Line<ColorMask, 2>((uint16 *)dstPtr, (const uint16 *)srcPtr, (const uint16 *)(srcPtr - pitch), width);
|
||||
break;
|
||||
case 4:
|
||||
interpolate5Line<ColorMask, 1>((uint16 *)dstPtr, (const uint16 *)srcPtr, (const uint16 *)(srcPtr - pitch), width);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
dstPtr -= pitch;
|
||||
}
|
||||
|
||||
return 1 + maxDstY - srcY;
|
||||
}
|
||||
|
||||
int stretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY, bool interpolate) {
|
||||
#if ASPECT_MODE != kSuperFastAndUglyAspectMode
|
||||
extern int gBitFormat;
|
||||
if (interpolate) {
|
||||
if (gBitFormat == 565)
|
||||
return stretch200To240Interpolated<Graphics::ColorMasks<565> >(buf, pitch, width, height, srcX, srcY, origSrcY);
|
||||
else // gBitFormat == 555
|
||||
return stretch200To240Interpolated<Graphics::ColorMasks<555> >(buf, pitch, width, height, srcX, srcY, origSrcY);
|
||||
} else {
|
||||
#endif
|
||||
return stretch200To240Nearest(buf, pitch, width, height, srcX, srcY, origSrcY);
|
||||
#if ASPECT_MODE != kSuperFastAndUglyAspectMode
|
||||
}
|
||||
#endif
|
||||
}
|
74
graphics/scaler/downscaler.cpp
Normal file
74
graphics/scaler/downscaler.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
/* 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/scaler/downscaler.h"
|
||||
#include "graphics/scaler/intern.h"
|
||||
|
||||
#ifdef USE_ARM_SCALER_ASM
|
||||
extern "C" {
|
||||
void DownscaleAllByHalfARM(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height, int mask, int round);
|
||||
}
|
||||
|
||||
void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
// Rounding constants and masks used for different pixel formats
|
||||
static const int roundingconstants[] = { 0x00200802, 0x00201002 };
|
||||
static const int redbluegreenMasks[] = { 0x03E07C1F, 0x07E0F81F };
|
||||
|
||||
extern int gBitFormat;
|
||||
|
||||
const int maskUsed = (gBitFormat == 565);
|
||||
DownscaleAllByHalfARM(srcPtr, srcPitch, dstPtr, dstPitch, width, height, redbluegreenMasks[maskUsed], roundingconstants[maskUsed]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template<typename ColorMask>
|
||||
void DownscaleAllByHalfTemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
uint8 *work;
|
||||
uint16 srcPitch16 = (uint16)(srcPitch / sizeof(uint16));
|
||||
|
||||
while ((height -= 2) >= 0) {
|
||||
work = dstPtr;
|
||||
|
||||
for (int i=0; i<width; i+=2) {
|
||||
// Another lame filter attempt :)
|
||||
uint16 color1 = *(((const uint16 *)srcPtr) + i);
|
||||
uint16 color2 = *(((const uint16 *)srcPtr) + (i + 1));
|
||||
uint16 color3 = *(((const uint16 *)srcPtr) + (i + srcPitch16));
|
||||
uint16 color4 = *(((const uint16 *)srcPtr) + (i + srcPitch16 + 1));
|
||||
*(((uint16 *)work) + 0) = interpolate16_1_1_1_1<ColorMask>(color1, color2, color3, color4);
|
||||
|
||||
work += sizeof(uint16);
|
||||
}
|
||||
srcPtr += 2 * srcPitch;
|
||||
dstPtr += dstPitch;
|
||||
}
|
||||
}
|
||||
|
||||
void DownscaleAllByHalf(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {
|
||||
extern int gBitFormat;
|
||||
if (gBitFormat == 565)
|
||||
DownscaleAllByHalfTemplate<Graphics::ColorMasks<565> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
else
|
||||
DownscaleAllByHalfTemplate<Graphics::ColorMasks<555> >(srcPtr, srcPitch, dstPtr, dstPitch, width, height);
|
||||
}
|
||||
|
||||
#endif
|
35
graphics/scaler/downscaler.h
Normal file
35
graphics/scaler/downscaler.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_SCALER_DOWNSCALER_H
|
||||
#define GRAPHICS_SCALER_DOWNSCALER_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
/**
|
||||
* This filter (down)scales the source image by a factor of 1/2.
|
||||
* For example, a 320x200 image is scaled to 160x100.
|
||||
*/
|
||||
DECLARE_SCALER(DownscaleAllByHalf);
|
||||
|
||||
#endif
|
1970
graphics/scaler/hq2x.cpp
Normal file
1970
graphics/scaler/hq2x.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2947
graphics/scaler/hq3x.cpp
Normal file
2947
graphics/scaler/hq3x.cpp
Normal file
File diff suppressed because it is too large
Load Diff
502
graphics/scaler/scale2x.cpp
Normal file
502
graphics/scaler/scale2x.cpp
Normal file
@ -0,0 +1,502 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "graphics/scaler/scale2x.h"
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x C implementation */
|
||||
|
||||
static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* @param dst0 First destination row, double length in pixels.
|
||||
* @param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) {
|
||||
scale2x_8_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_def() but for 16 bits pixels.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* @param dst0 First destination row, double length in pixels.
|
||||
* @param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) {
|
||||
scale2x_16_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_def() but for 32 bits pixels.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* @param dst0 First destination row, double length in pixels.
|
||||
* @param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) {
|
||||
scale2x_32_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x MMX implementation */
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
/*
|
||||
* Apply the Scale2x effect at a single row.
|
||||
* This function must be called only by the other scale2x functions.
|
||||
*
|
||||
* Considering the pixel map :
|
||||
*
|
||||
* ABC (src0)
|
||||
* DEF (src1)
|
||||
* GHI (src2)
|
||||
*
|
||||
* this functions compute 2 new pixels in substitution of the source pixel E
|
||||
* like this map :
|
||||
*
|
||||
* ab (dst)
|
||||
*
|
||||
* with these variables :
|
||||
*
|
||||
* ¤t -> E
|
||||
* ¤t_left -> D
|
||||
* ¤t_right -> F
|
||||
* ¤t_upper -> B
|
||||
* ¤t_lower -> H
|
||||
*
|
||||
* %0 -> current_upper
|
||||
* %1 -> current
|
||||
* %2 -> current_lower
|
||||
* %3 -> dst
|
||||
* %4 -> counter
|
||||
*
|
||||
* %mm0 -> *current_left
|
||||
* %mm1 -> *current_next
|
||||
* %mm2 -> tmp0
|
||||
* %mm3 -> tmp1
|
||||
* %mm4 -> tmp2
|
||||
* %mm5 -> tmp3
|
||||
* %mm6 -> *current_upper
|
||||
* %mm7 -> *current
|
||||
*/
|
||||
static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) {
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* central runs */
|
||||
"shr $3, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"add $8, %0\n"
|
||||
"add $8, %1\n"
|
||||
"add $8, %2\n"
|
||||
"add $16, %3\n"
|
||||
|
||||
"dec %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) {
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* central runs */
|
||||
"shr $2, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"add $8, %0\n"
|
||||
"add $8, %1\n"
|
||||
"add $8, %2\n"
|
||||
"add $16, %3\n"
|
||||
|
||||
"dec %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) {
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* central runs */
|
||||
"shr $1, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"add $8, %0\n"
|
||||
"add $8, %1\n"
|
||||
"add $8, %2\n"
|
||||
"add $16, %3\n"
|
||||
|
||||
"dec %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* This is a very fast MMX implementation.
|
||||
* The implementation uses a combination of cmp/and/not operations to
|
||||
* completly remove the need of conditional jumps. This trick give the
|
||||
* major speed improvement.
|
||||
* Also, using the 8 bytes MMX registers more than one pixel are computed
|
||||
* at the same time.
|
||||
* Before calling this function you must ensure that the currenct CPU supports
|
||||
* the MMX instruction set. After calling it you must be sure to call the EMMS
|
||||
* instruction before any floating-point operation.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 16 and a multiple of 8.
|
||||
* @param dst0 First destination row, double length in pixels.
|
||||
* @param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) {
|
||||
if (count % 8 != 0 || count < 16) {
|
||||
scale2x_8_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
scale2x_8_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 16 bits pixels.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 8 and a multiple of 4.
|
||||
* @param dst0 First destination row, double length in pixels.
|
||||
* @param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) {
|
||||
if (count % 4 != 0 || count < 8) {
|
||||
scale2x_16_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
scale2x_16_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 32 bits pixels.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 4 and a multiple of 2.
|
||||
* @param dst0 First destination row, double length in pixels.
|
||||
* @param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) {
|
||||
if (count % 2 != 0 || count < 4) {
|
||||
scale2x_32_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
scale2x_32_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
68
graphics/scaler/scale2x.h
Normal file
68
graphics/scaler/scale2x.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef SCALER_SCALE2X_H
|
||||
#define SCALER_SCALE2X_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define __restrict__
|
||||
#endif
|
||||
|
||||
#ifdef __sgi
|
||||
#define __restrict__ __restrict
|
||||
#endif
|
||||
|
||||
|
||||
typedef unsigned char scale2x_uint8;
|
||||
typedef unsigned short scale2x_uint16;
|
||||
typedef unsigned scale2x_uint32;
|
||||
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
/**
|
||||
* End the use of the MMX instructions.
|
||||
* This function must be called before using any floating-point operations.
|
||||
*/
|
||||
static inline void scale2x_mmx_emms(void)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"emms"
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USE_ARM_SCALER_ASM)
|
||||
|
||||
extern "C" void scale2x_8_arm(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
extern "C" void scale2x_16_arm(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
extern "C" void scale2x_32_arm(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
222
graphics/scaler/scale3x.cpp
Normal file
222
graphics/scaler/scale3x.cpp
Normal file
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "graphics/scaler/scale3x.h"
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale3x C implementation */
|
||||
|
||||
static inline void scale3x_8_def_border(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale3x_8_def_center(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_border(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_center(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_border(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_center(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count) {
|
||||
/* central pixels */
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* @param dst0 First destination row, triple length in pixels.
|
||||
* @param dst1 Second destination row, triple length in pixels.
|
||||
* @param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) {
|
||||
scale3x_8_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_8_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_8_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 16 bits.
|
||||
* This function operates like scale3x_8_def() but for 16 bits pixels.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* @param dst0 First destination row, triple length in pixels.
|
||||
* @param dst1 Second destination row, triple length in pixels.
|
||||
* @param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) {
|
||||
scale3x_16_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_16_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_16_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 32 bits.
|
||||
* This function operates like scale3x_8_def() but for 32 bits pixels.
|
||||
* @param src0 Pointer at the first pixel of the previous row.
|
||||
* @param src1 Pointer at the first pixel of the current row.
|
||||
* @param src2 Pointer at the first pixel of the next row.
|
||||
* @param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* @param dst0 First destination row, triple length in pixels.
|
||||
* @param dst1 Second destination row, triple length in pixels.
|
||||
* @param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) {
|
||||
scale3x_32_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_32_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_32_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
40
graphics/scaler/scale3x.h
Normal file
40
graphics/scaler/scale3x.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef SCALER_SCALE3X_H
|
||||
#define SCALER_SCALE3X_H
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define __restrict__
|
||||
#endif
|
||||
|
||||
#ifdef __sgi
|
||||
#define __restrict__ __restrict
|
||||
#endif
|
||||
|
||||
typedef unsigned char scale3x_uint8;
|
||||
typedef unsigned short scale3x_uint16;
|
||||
typedef unsigned scale3x_uint32;
|
||||
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count);
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count);
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count);
|
||||
|
||||
#endif
|
350
graphics/scaler/scalebit.cpp
Normal file
350
graphics/scaler/scalebit.cpp
Normal file
@ -0,0 +1,350 @@
|
||||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "graphics/scaler/scale2x.h"
|
||||
#include "graphics/scaler/scale3x.h"
|
||||
|
||||
#define DST(bits, num) (scale2x_uint ## bits *)dst ## num
|
||||
#define SRC(bits, num) (const scale2x_uint ## bits *)src ## num
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) {
|
||||
switch (pixel) {
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
case 1: scale2x_8_mmx( DST( 8,0), DST( 8,1), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
|
||||
case 2: scale2x_16_mmx(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
|
||||
case 4: scale2x_32_mmx(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
|
||||
#elif defined(USE_ARM_SCALER_ASM)
|
||||
case 1: scale2x_8_arm( DST( 8,0), DST( 8,1), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
|
||||
case 2: scale2x_16_arm(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
|
||||
case 4: scale2x_32_arm(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
|
||||
#else
|
||||
case 1: scale2x_8_def( DST( 8,0), DST( 8,1), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
|
||||
case 2: scale2x_16_def(DST(16,0), DST(16,1), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
|
||||
case 4: scale2x_32_def(DST(32,0), DST(32,1), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale3x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row) {
|
||||
switch (pixel) {
|
||||
case 1: scale3x_8_def( DST( 8,0), DST( 8,1), DST( 8,2), SRC( 8,0), SRC( 8,1), SRC( 8,2), pixel_per_row); break;
|
||||
case 2: scale3x_16_def(DST(16,0), DST(16,1), DST(16,2), SRC(16,0), SRC(16,1), SRC(16,2), pixel_per_row); break;
|
||||
case 4: scale3x_32_def(DST(32,0), DST(32,1), DST(32,2), SRC(32,0), SRC(32,1), SRC(32,2), pixel_per_row); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row) {
|
||||
stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
|
||||
stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
|
||||
}
|
||||
|
||||
#define SCDST(i) (dst+(i)*dst_slice)
|
||||
#define SCSRC(i) (src+(i)*src_slice)
|
||||
#define SCMID(i) (mid[(i)])
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 2x2 times the size of the source bitmap.
|
||||
* @param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* @param dst_slice Size in bytes of a destination bitmap row.
|
||||
* @param void_src Pointer at the first pixel of the source bitmap.
|
||||
* @param src_slice Size in bytes of a source bitmap row.
|
||||
* @param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* @param width Horizontal size in pixels of the source bitmap.
|
||||
* @param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (const unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
while (count) {
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale3x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 3x3 times the size of the source bitmap.
|
||||
* @param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* @param dst_slice Size in bytes of a destination bitmap row.
|
||||
* @param void_src Pointer at the first pixel of the source bitmap.
|
||||
* @param src_slice Size in bytes of a source bitmap row.
|
||||
* @param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* @param width Horizontal size in pixels of the source bitmap.
|
||||
* @param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (const unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
while (count) {
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function requires also a small buffer bitmap used internally to store
|
||||
* intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
|
||||
* and a vertical size of 6 rows. The memory of this buffer must not be allocated
|
||||
* in video memory because it's also read and not only written. Generally
|
||||
* a heap (malloc) or a stack (alloca) buffer is the best choices.
|
||||
* @param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* @param dst_slice Size in bytes of a destination bitmap row.
|
||||
* @param void_mid Pointer at the first pixel of the buffer bitmap.
|
||||
* @param mid_slice Size in bytes of a buffer bitmap row.
|
||||
* @param void_src Pointer at the first pixel of the source bitmap.
|
||||
* @param src_slice Size in bytes of a source bitmap row.
|
||||
* @param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* @param width Horizontal size in pixels of the source bitmap.
|
||||
* @param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (const unsigned char*)void_src;
|
||||
unsigned count;
|
||||
unsigned char* mid[6];
|
||||
|
||||
assert(height >= 4);
|
||||
|
||||
count = height;
|
||||
|
||||
/* set the 6 buffer pointers */
|
||||
mid[0] = (unsigned char*)void_mid;
|
||||
mid[1] = mid[0] + mid_slice;
|
||||
mid[2] = mid[1] + mid_slice;
|
||||
mid[3] = mid[2] + mid_slice;
|
||||
mid[4] = mid[3] + mid_slice;
|
||||
mid[5] = mid[4] + mid_slice;
|
||||
|
||||
while (count) {
|
||||
unsigned char* tmp;
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
src = SCSRC(1);
|
||||
|
||||
tmp = SCMID(0); /* shift by 2 position */
|
||||
SCMID(0) = SCMID(2);
|
||||
SCMID(2) = SCMID(4);
|
||||
SCMID(4) = tmp;
|
||||
tmp = SCMID(1);
|
||||
SCMID(1) = SCMID(3);
|
||||
SCMID(3) = SCMID(5);
|
||||
SCMID(5) = tmp;
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function operates like ::scale4x_buf() but the intermediate buffer is
|
||||
* automatically allocated in the stack.
|
||||
* @param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* @param dst_slice Size in bytes of a destination bitmap row.
|
||||
* @param void_src Pointer at the first pixel of the source bitmap.
|
||||
* @param src_slice Size in bytes of a source bitmap row.
|
||||
* @param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* @param width Horizontal size in pixels of the source bitmap.
|
||||
* @param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height) {
|
||||
unsigned mid_slice;
|
||||
void* mid;
|
||||
|
||||
mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
|
||||
|
||||
mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
|
||||
|
||||
#if defined(HAVE_ALLOCA)
|
||||
mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
assert(mid != 0); /* alloca should never fails */
|
||||
#else
|
||||
mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
if (!mid)
|
||||
return;
|
||||
#endif
|
||||
|
||||
scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
|
||||
|
||||
#if !defined(HAVE_ALLOCA)
|
||||
free(mid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the scale implementation is applicable at the given arguments.
|
||||
* @param scale Scale factor. 2, 3 or 4.
|
||||
* @param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* @param width Horizontal size in pixels of the source bitmap.
|
||||
* @param height Vertical size in pixels of the source bitmap.
|
||||
* \return
|
||||
* - -1 on precondition violated.
|
||||
* - 0 on success.
|
||||
*/
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
if (scale != 2 && scale != 3 && scale != 4)
|
||||
return -1;
|
||||
|
||||
if (pixel != 1 && pixel != 2 && pixel != 4)
|
||||
return -1;
|
||||
|
||||
switch (scale) {
|
||||
case 2:
|
||||
case 3:
|
||||
if (height < 2)
|
||||
return -1;
|
||||
break;
|
||||
case 4:
|
||||
if (height < 4)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
switch (scale) {
|
||||
case 2:
|
||||
case 4:
|
||||
if (width < (16 / pixel))
|
||||
return -1;
|
||||
if (width % (8 / pixel) != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 3:
|
||||
if (width < 2)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (width < 2)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale effect on a bitmap.
|
||||
* This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
|
||||
* @param scale Scale factor. 2, 3 or 4.
|
||||
* @param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* @param dst_slice Size in bytes of a destination bitmap row.
|
||||
* @param void_src Pointer at the first pixel of the source bitmap.
|
||||
* @param src_slice Size in bytes of a source bitmap row.
|
||||
* @param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* @param width Horizontal size in pixels of the source bitmap.
|
||||
* @param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
switch (scale) {
|
||||
case 2:
|
||||
scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 3:
|
||||
scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 4:
|
||||
scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user