From 52db9a46f65b54d7d75e0a57edc792b8008acce2 Mon Sep 17 00:00:00 2001 From: Arthur Moore Date: Tue, 10 Mar 2015 21:24:17 -0400 Subject: [PATCH] Rewrite the Interframe filters using proper C++ classes. Also drop support for MMX and 16 bit filters --- CMakeLists.txt | 1 + src/filters/filters.hpp | 7 +- src/filters/new_interframe.cpp | 153 +++++++++++++++++++++++++++++++++ src/filters/new_interframe.hpp | 68 +++++++++++++++ src/gtk/filters.h | 1 + src/sdl/filters.cpp | 2 - src/sdl/filters.h | 1 + src/wx/wxvbam.h | 1 + 8 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/filters/new_interframe.cpp create mode 100644 src/filters/new_interframe.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d7491cf4..29298395 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,7 @@ SET(SRC_SDL SET(SRC_FILTERS src/filters/filters.cpp + src/filters/new_interframe.cpp src/filters/2xSaI.cpp src/filters/admame.cpp src/filters/bilinear.cpp diff --git a/src/filters/filters.hpp b/src/filters/filters.hpp index c970ea06..5b7b9da6 100644 --- a/src/filters/filters.hpp +++ b/src/filters/filters.hpp @@ -7,7 +7,6 @@ #include #include -#include "interframe.hpp" #include "../common/Types.h" //sdl @@ -121,7 +120,9 @@ public: * This one is smart. * It knows it's a 32 bit filter, and the input width will not change from when it is initialized. * - * \param[in] srcPtr A pointer to a 16/32 bit RGB Pixel Array + * \param[in] srcPtr A pointer to the input 32 bit RGB Pixel Array + * \param[in] deltaPtr A pointer to a 32 bit RGB Pixel Array (used to store the difference between frames) + * \param[in] dstPtr A pointer to the output 32 bit RGB Pixel Array */ void run(u8 *srcPtr, u8 *deltaPtr, u8 *dstPtr, int height) { @@ -187,8 +188,6 @@ void Scanlines (u8 *srcPtr, u32 srcPitch, u8 *, u8 *dstPtr, u32 dstPitch, int wi void Scanlines32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, u8 *dstPtr, u32 dstPitch, int width, int height); // "TV" here means each pixel is faded horizontally & vertically rather than // inserting black scanlines -// this depends on RGB_LOW_BITS_MASK (included from interframe.hpp -//extern int RGB_LOW_BITS_MASK; void ScanlinesTV(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, u8 *dstPtr, u32 dstPitch, int width, int height); void ScanlinesTV32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */, u8 *dstPtr, u32 dstPitch, int width, int height); diff --git a/src/filters/new_interframe.cpp b/src/filters/new_interframe.cpp new file mode 100644 index 00000000..55fccb6c --- /dev/null +++ b/src/filters/new_interframe.cpp @@ -0,0 +1,153 @@ +//Credits: +// Kawaks' Mr. K for the code +// Incorporated into vba by Anthony Di Franco +// Converted to C++ by Arthur Moore +#include "../System.h" +#include +#include +#include + +#include "new_interframe.hpp" + +void interframe_filter::setWidth(unsigned int _width) +{ + width = _width; + + //32 bit filter, so 8 bytes per pixel + // The +1 is for a 1 pixel border that the emulator spits out + horiz_bytes = (width+1) * 4; + //Unfortunately, the filter keeps the border on the scaled output, but DOES NOT scale it +// horiz_bytes_out = width * 4 * myScale + 4; + +} + +SmartIB::SmartIB() +{ + frm1 = (u8 *)calloc(322*242,4); + // 1 frame ago + frm2 = (u8 *)calloc(322*242,4); + // 2 frames ago + frm3 = (u8 *)calloc(322*242,4); + // 3 frames ago +} + +SmartIB::~SmartIB() +{ + //\HACK to prevent double freeing. (It looks like this is not being called in a thread safe manner!!!) + + if(frm1) + free(frm1); + if( frm2 && (frm1 != frm2) ) + free(frm2); + if( frm3 && (frm1 != frm3) && (frm2 != frm3) ) + free(frm3); + frm1 = frm2 = frm3 = NULL; +} + +void SmartIB::run(u8 *srcPtr, int starty, int height) +{ + if(!getWidth()) + { + throw std::runtime_error("ERROR: Filter width not set"); + } + run(srcPtr, get_horiz_bytes(), getWidth(), starty, height); +} + +void SmartIB::run(u8 *srcPtr, u32 srcPitch, int width, int starty, int height) +{ + setWidth(width); + //Make sure the math was correct + if( (srcPitch != get_horiz_bytes()) ) + { + throw std::runtime_error("ERROR: Filter programmer is an idiot, and messed up an important calculation!"); + } + + u32 *src0 = (u32 *)srcPtr + starty * srcPitch / 4; + u32 *src1 = (u32 *)frm1 + starty * srcPitch / 4; + u32 *src2 = (u32 *)frm2 + starty * srcPitch / 4; + u32 *src3 = (u32 *)frm3 + starty * srcPitch / 4; + + u32 colorMask = 0xfefefe; + + int sPitch = srcPitch >> 2; + int pos = 0; + + for (int j = 0; j < height; j++) + for (int i = 0; i < sPitch; i++) { + u32 color = src0[pos]; + src0[pos] = + (src1[pos] != src2[pos]) && + (src3[pos] != color) && + ((color == src2[pos]) || (src1[pos] == src3[pos])) + ? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) : + color; + src3[pos] = color; /* oldest buffer now holds newest frame */ + pos++; + } + + /* Swap buffers around */ + u8 *temp = frm1; + frm1 = frm3; + frm3 = frm2; + frm2 = temp; +} + + +MotionBlurIB::MotionBlurIB() +{ + frm1 = (u8 *)calloc(322*242,4); + // 1 frame ago + frm2 = (u8 *)calloc(322*242,4); + // 2 frames ago + frm3 = (u8 *)calloc(322*242,4); + // 3 frames ago +} + +MotionBlurIB::~MotionBlurIB() +{ + //\HACK to prevent double freeing. (It looks like this is not being called in a thread safe manner!!!) + + if(frm1) + free(frm1); + if( frm2 && (frm1 != frm2) ) + free(frm2); + if( frm3 && (frm1 != frm3) && (frm2 != frm3) ) + free(frm3); + frm1 = frm2 = frm3 = NULL; +} + +void MotionBlurIB::run(u8 *srcPtr, int starty, int height) +{ + if(!getWidth()) + { + throw std::runtime_error("ERROR: Filter width not set"); + } + run(srcPtr, get_horiz_bytes(), getWidth(), starty, height); +} + +void MotionBlurIB::run(u8 *srcPtr, u32 srcPitch, int width, int starty, int height) +{ + setWidth(width); + //Make sure the math was correct + if( (srcPitch != get_horiz_bytes()) ) + { + throw std::runtime_error("ERROR: Filter programmer is an idiot, and messed up an important calculation!"); + } + + u32 *src0 = (u32 *)srcPtr + starty * srcPitch / 4; + u32 *src1 = (u32 *)frm1 + starty * srcPitch / 4; + + u32 colorMask = 0xfefefe; + + int sPitch = srcPitch >> 2; + int pos = 0; + + for (int j = 0; j < height; j++) + for (int i = 0; i < sPitch; i++) { + u32 color = src0[pos]; + src0[pos] = (((color & colorMask) >> 1) + + ((src1[pos] & colorMask) >> 1)); + src1[pos] = color; + pos++; + } +} diff --git a/src/filters/new_interframe.hpp b/src/filters/new_interframe.hpp new file mode 100644 index 00000000..93382e46 --- /dev/null +++ b/src/filters/new_interframe.hpp @@ -0,0 +1,68 @@ +/// Filters (Using propper C++ classes instead of statics) + +#ifndef NEW_INTERFRAME_HPP +#define NEW_INTERFRAME_HPP + +#include "../common/Types.h" +#include + +class interframe_filter +{ +private: + ///The filter's width + unsigned int width; + ///Don't need to calculate these every time (based off width) + unsigned int horiz_bytes; +// unsigned int horiz_bytes_out; +//Children need this pre-calculated data, but it's NOT public +protected: + unsigned int get_horiz_bytes() {return horiz_bytes;} +// unsigned int get_horiz_bytes_out() {return horiz_bytes_out;} +public: + interframe_filter(): width(0) {} + virtual std::string getName() {return "Dummy Filter";} + virtual int getScale() {return 0;} + ///Set the number of pixels per horizontal row + ///Always use this after initialization if using the new run function. + void setWidth(unsigned int _width); + unsigned int getWidth() {return width;} + ///DEPRECATED Original Interframe function + virtual void run(u8 *srcPtr, u32 srcPitch, int width, int starty, int height) {} + ///New smarter Interframe function + virtual void run(u8 *srcPtr, int starty, int height) {} +}; + + +// Interframe blending filters (These are the 32 bit versions) +class SmartIB : interframe_filter +{ +private: + u8 *frm1 = NULL; + u8 *frm2 = NULL; + u8 *frm3 = NULL; +public: + SmartIB(); + ~SmartIB(); + std::string getName() {return "SmartIB";} + void run(u8 *srcPtr, u32 srcPitch, int width, int starty, int height); + void run(u8 *srcPtr, int starty, int height); +}; + +class MotionBlurIB : interframe_filter +{ +private: + u8 *frm1 = NULL; + u8 *frm2 = NULL; + u8 *frm3 = NULL; +public: + MotionBlurIB(); + ~MotionBlurIB(); + std::string getName() {return "MotionBlurIB";} + void run(u8 *srcPtr, u32 srcPitch, int width, int starty, int height); + void run(u8 *srcPtr, int starty, int height); +}; + + + +#endif //NEW_INTERFRAME_HPP + diff --git a/src/gtk/filters.h b/src/gtk/filters.h index f95711d0..32b3c421 100644 --- a/src/gtk/filters.h +++ b/src/gtk/filters.h @@ -22,6 +22,7 @@ #include "../System.h" #include "../filters/filters.hpp" +#include "../filters/interframe.hpp" namespace VBA { diff --git a/src/sdl/filters.cpp b/src/sdl/filters.cpp index 9fa87871..9261ab1d 100644 --- a/src/sdl/filters.cpp +++ b/src/sdl/filters.cpp @@ -18,8 +18,6 @@ #include "filters.h" -#include "../filters/filters.hpp" - // // Screen filters // diff --git a/src/sdl/filters.h b/src/sdl/filters.h index 3250599b..29743471 100644 --- a/src/sdl/filters.h +++ b/src/sdl/filters.h @@ -21,6 +21,7 @@ #include "../System.h" #include "../filters/filters.hpp" +#include "../filters/interframe.hpp" // // Screen filters diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 0aa5a4f0..005f1d86 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -28,6 +28,7 @@ #include "../gba/Cheats.h" #include "../filters/filters.hpp" +#include "../filters/interframe.hpp" template void CheckPointer(T pointer)