Rewrite the Interframe filters using proper C++ classes.

Also drop support for MMX and 16 bit filters
This commit is contained in:
Arthur Moore 2015-03-10 21:24:17 -04:00
parent a25179e4d5
commit 52db9a46f6
8 changed files with 228 additions and 6 deletions

View File

@ -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

View File

@ -7,7 +7,6 @@
#include <stdexcept>
#include <iostream>
#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);

View File

@ -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 <stdlib.h>
#include <memory.h>
#include <stdexcept>
#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++;
}
}

View File

@ -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 <string>
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

View File

@ -22,6 +22,7 @@
#include "../System.h"
#include "../filters/filters.hpp"
#include "../filters/interframe.hpp"
namespace VBA
{

View File

@ -18,8 +18,6 @@
#include "filters.h"
#include "../filters/filters.hpp"
//
// Screen filters
//

View File

@ -21,6 +21,7 @@
#include "../System.h"
#include "../filters/filters.hpp"
#include "../filters/interframe.hpp"
//
// Screen filters

View File

@ -28,6 +28,7 @@
#include "../gba/Cheats.h"
#include "../filters/filters.hpp"
#include "../filters/interframe.hpp"
template <typename T>
void CheckPointer(T pointer)