From 9d44ca55f69ec90ee66e66ab24c532cbe366c5fc Mon Sep 17 00:00:00 2001 From: rogerman Date: Thu, 13 Feb 2014 23:30:01 +0000 Subject: [PATCH] Video Filters: - Have the xBRZ filter handle the alpha channel. - Minor code cleanup of video filter managing code. --- desmume/src/filter/videofilter.cpp | 42 +++++++++++++----------------- desmume/src/filter/videofilter.h | 6 ++--- desmume/src/filter/xbrz.cpp | 23 +++++++++++----- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/desmume/src/filter/videofilter.cpp b/desmume/src/filter/videofilter.cpp index db652a92c..c7f2f3ad2 100644 --- a/desmume/src/filter/videofilter.cpp +++ b/desmume/src/filter/videofilter.cpp @@ -189,7 +189,7 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height) ThreadLockUnlock(&this->_lockSrc); const VideoFilterAttributes vfAttr = this->GetAttributes(); - result = this->ChangeFilterByAttributes(&vfAttr); + result = this->ChangeFilterByAttributes(vfAttr); return result; } @@ -216,7 +216,7 @@ bool VideoFilter::ChangeFilterByID(const VideoFilterTypeID typeID) return result; } - result = this->ChangeFilterByAttributes(&VideoFilterAttributesList[typeID]); + result = this->ChangeFilterByAttributes(VideoFilterAttributesList[typeID]); return result; } @@ -233,28 +233,23 @@ bool VideoFilter::ChangeFilterByID(const VideoFilterTypeID typeID) A bool that reports if the filter change was successful. A value of true means success, while a value of false means failure. ********************************************************************************************/ -bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr) +bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr) { bool result = false; - if (vfAttr == NULL) + if (vfAttr.scaleMultiply == 0 || vfAttr.scaleDivide < 1) { return result; } - if (vfAttr->scaleMultiply == 0 || vfAttr->scaleDivide < 1) - { - return result; - } - - if (this->_vfDstSurface.Surface != NULL && this->_vfAttributes.scaleMultiply == vfAttr->scaleMultiply && this->_vfAttributes.scaleDivide == vfAttr->scaleDivide) + if (this->_vfDstSurface.Surface != NULL && this->_vfAttributes.scaleMultiply == vfAttr.scaleMultiply && this->_vfAttributes.scaleDivide == vfAttr.scaleDivide) { // If we have an existing buffer and the new size is identical to the old size, // we can skip the costly construction of the buffer and simply clear it instead. ThreadLockLock(&this->_lockDst); memset(this->_vfDstSurface.Surface, 0, this->_vfDstSurface.Width * _vfDstSurface.Height * sizeof(uint32_t)); - this->_vfFunc = vfAttr->filterFunction; + this->_vfFunc = vfAttr.filterFunction; const size_t threadCount = this->_vfThread.size(); for (size_t i = 0; i < threadCount; i++) @@ -272,9 +267,9 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr) const size_t srcHeight = this->_vfSrcSurface.Height; ThreadLockUnlock(&this->_lockSrc); - const size_t dstWidth = srcWidth * vfAttr->scaleMultiply / vfAttr->scaleDivide; - const size_t dstHeight = srcHeight * vfAttr->scaleMultiply / vfAttr->scaleDivide; - const VideoFilterFunc filterFunction = vfAttr->filterFunction; + const size_t dstWidth = srcWidth * vfAttr.scaleMultiply / vfAttr.scaleDivide; + const size_t dstHeight = srcHeight * vfAttr.scaleMultiply / vfAttr.scaleDivide; + const VideoFilterFunc filterFunction = vfAttr.filterFunction; ThreadLockLock(&this->_lockDst); @@ -312,7 +307,7 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr) ThreadLockUnlock(&this->_lockDst); } - this->SetAttributes(*vfAttr); + this->SetAttributes(vfAttr); result = true; return result; @@ -408,7 +403,7 @@ void VideoFilter::RunFilterCustomByID(const uint32_t *__restrict srcBuffer, uint return; } - VideoFilter::RunFilterCustomByAttributes(srcBuffer, dstBuffer, srcWidth, srcHeight, &VideoFilterAttributesList[typeID]); + VideoFilter::RunFilterCustomByAttributes(srcBuffer, dstBuffer, srcWidth, srcHeight, VideoFilterAttributesList[typeID]); } /******************************************************************************************** @@ -440,24 +435,23 @@ void VideoFilter::RunFilterCustomByID(const uint32_t *__restrict srcBuffer, uint ********************************************************************************************/ void VideoFilter::RunFilterCustomByAttributes(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, - const VideoFilterAttributes *vfAttr) + const VideoFilterAttributes &vfAttr) { // Parameter check if (srcBuffer == NULL || dstBuffer == NULL || srcWidth < 1 || srcHeight < 1 || - vfAttr == NULL || - vfAttr->scaleMultiply == 0 || - vfAttr->scaleDivide < 1) + vfAttr.scaleMultiply == 0 || + vfAttr.scaleDivide < 1) { return; } // Get the filter attributes - const size_t dstWidth = srcWidth * vfAttr->scaleMultiply / vfAttr->scaleDivide; - const size_t dstHeight = srcHeight * vfAttr->scaleMultiply / vfAttr->scaleDivide; - const VideoFilterFunc filterFunction = vfAttr->filterFunction; + const size_t dstWidth = srcWidth * vfAttr.scaleMultiply / vfAttr.scaleDivide; + const size_t dstHeight = srcHeight * vfAttr.scaleMultiply / vfAttr.scaleDivide; + const VideoFilterFunc filterFunction = vfAttr.filterFunction; // Assign the surfaces and run the filter SSurface srcSurface; @@ -517,7 +511,7 @@ VideoFilterAttributes VideoFilter::GetAttributes() return vfAttr; } -void VideoFilter::SetAttributes(const VideoFilterAttributes vfAttr) +void VideoFilter::SetAttributes(const VideoFilterAttributes &vfAttr) { ThreadLockLock(&this->_lockAttributes); this->_vfAttributes = vfAttr; diff --git a/desmume/src/filter/videofilter.h b/desmume/src/filter/videofilter.h index b92951d12..6bae8e144 100644 --- a/desmume/src/filter/videofilter.h +++ b/desmume/src/filter/videofilter.h @@ -180,7 +180,7 @@ private: ThreadLock _lockAttributes; ThreadCond _condRunning; - void SetAttributes(const VideoFilterAttributes vfAttr); + void SetAttributes(const VideoFilterAttributes &vfAttr); public: VideoFilter(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount); @@ -188,11 +188,11 @@ public: bool SetSourceSize(const size_t width, const size_t height); bool ChangeFilterByID(const VideoFilterTypeID typeID); - bool ChangeFilterByAttributes(const VideoFilterAttributes *vfAttr); + bool ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr); uint32_t* RunFilter(); static void RunFilterCustomByID(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, const VideoFilterTypeID typeID); - static void RunFilterCustomByAttributes(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, const VideoFilterAttributes *vfAttr); + static void RunFilterCustomByAttributes(const uint32_t *__restrict srcBuffer, uint32_t *__restrict dstBuffer, const size_t srcWidth, const size_t srcHeight, const VideoFilterAttributes &vfAttr); static const char* GetTypeStringByID(const VideoFilterTypeID typeID); VideoFilterAttributes GetAttributes(); diff --git a/desmume/src/filter/xbrz.cpp b/desmume/src/filter/xbrz.cpp index 997f503aa..fb2803afd 100644 --- a/desmume/src/filter/xbrz.cpp +++ b/desmume/src/filter/xbrz.cpp @@ -27,6 +27,7 @@ namespace template inline unsigned char getByte(uint32_t val) { return static_cast((val >> (8 * N)) & 0xff); } +inline unsigned char getAlpha(uint32_t val) { return getByte<3>(val); } inline unsigned char getRed (uint32_t val) { return getByte<2>(val); } inline unsigned char getGreen(uint32_t val) { return getByte<1>(val); } inline unsigned char getBlue (uint32_t val) { return getByte<0>(val); } @@ -38,9 +39,10 @@ T abs(T value) return value < 0 ? -value : value; } -const uint32_t redMask = 0xff0000; -const uint32_t greenMask = 0x00ff00; -const uint32_t blueMask = 0x0000ff; +static const uint32_t alphaMask = 0xFF000000; +static const uint32_t redMask = 0x00FF0000; +static const uint32_t greenMask = 0x0000FF00; +static const uint32_t blueMask = 0x000000FF; template inline void alphaBlend(uint32_t& dst, uint32_t col) //blend color over destination with opacity N / M @@ -48,9 +50,15 @@ void alphaBlend(uint32_t& dst, uint32_t col) //blend color over destination with //static_assert(N < 256, "possible overflow of (col & redMask) * N"); //static_assert(M < 256, "possible overflow of (col & redMask ) * N + (dst & redMask ) * (M - N)"); //static_assert(0 < N && N < M, ""); - dst = (redMask & ((col & redMask ) * N + (dst & redMask ) * (M - N)) / M) | //this works because 8 upper bits are free - (greenMask & ((col & greenMask) * N + (dst & greenMask) * (M - N)) / M) | - (blueMask & ((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M); + //dst = (redMask & ((col & redMask ) * N + (dst & redMask ) * (M - N)) / M) | //this works because 8 upper bits are free + // (greenMask & ((col & greenMask) * N + (dst & greenMask) * (M - N)) / M) | + // (blueMask & ((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M); + + // 2014-02-06 (rogerman): Modified to take the alpha channel into account. + dst = ((((col >> 24) * N + (dst >> 24) * (M - N) ) / M) << 24) | + (redMask & (((col & redMask ) * N + (dst & redMask ) * (M - N)) / M)) | + (greenMask & (((col & greenMask) * N + (dst & greenMask) * (M - N)) / M)) | + (blueMask & (((col & blueMask ) * N + (dst & blueMask ) * (M - N)) / M)); } @@ -397,7 +405,8 @@ double distYCbCr(uint32_t pix1, uint32_t pix2, double lumaWeight) const double c_r = scale_r * (r_diff - y); //we skip division by 255 to have similar range like other distance functions - return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)); + //return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)); + return std::sqrt(square(lumaWeight * y) + square(c_b) + square(c_r)+ square(static_cast(getAlpha(pix1)) - getAlpha(pix2))); }