From a09763f8c3db572ced4a4f01a5480473d4350df9 Mon Sep 17 00:00:00 2001 From: rogerman Date: Tue, 7 Feb 2017 15:19:32 -0800 Subject: [PATCH] Video Filters: Reorganize the VideoFilter class and simplify RenderDeposterize(). --- desmume/src/filter/deposterize.cpp | 243 ++++++++++++++++---------- desmume/src/filter/videofilter.cpp | 270 +++++++++++++++-------------- desmume/src/filter/videofilter.h | 28 +-- 3 files changed, 313 insertions(+), 228 deletions(-) diff --git a/desmume/src/filter/deposterize.cpp b/desmume/src/filter/deposterize.cpp index 84ebebb34..b0b246ff0 100644 --- a/desmume/src/filter/deposterize.cpp +++ b/desmume/src/filter/deposterize.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2016 DeSmuME team + Copyright (C) 2016-2017 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,11 +38,11 @@ static u32 Deposterize_InterpLTE(const u32 pixA, const u32 pixB) const u32 gB = (pixB & 0x0000FF00) >> 8; const u32 bB = (pixB & 0x00FF0000) >> 16; - const u32 rC = ( (rB - rA <= DEPOSTERIZE_THRESHOLD) || (rA - rB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((rA+rB)>>1) ) : rA; - const u32 gC = ( (gB - gA <= DEPOSTERIZE_THRESHOLD) || (gA - gB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((gA+gB)>>1) ) : gA; - const u32 bC = ( (bB - bA <= DEPOSTERIZE_THRESHOLD) || (bA - bB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((bA+bB)>>1) ) : bA; - const u32 aC = ( (bB - aA <= DEPOSTERIZE_THRESHOLD) || (aA - aB <= DEPOSTERIZE_THRESHOLD) ) ? ( ((aA+aB)>>1) ) : aA; - + const u32 rC = ( (rB - rA <= DEPOSTERIZE_THRESHOLD) || (rA - rB <= DEPOSTERIZE_THRESHOLD) ) ? ((rA+rB)>>1) : rA; + const u32 gC = ( (gB - gA <= DEPOSTERIZE_THRESHOLD) || (gA - gB <= DEPOSTERIZE_THRESHOLD) ) ? ((gA+gB)>>1) : gA; + const u32 bC = ( (bB - bA <= DEPOSTERIZE_THRESHOLD) || (bA - bB <= DEPOSTERIZE_THRESHOLD) ) ? ((bA+bB)>>1) : bA; + const u32 aC = ( (aB - aA <= DEPOSTERIZE_THRESHOLD) || (aA - aB <= DEPOSTERIZE_THRESHOLD) ) ? ((aA+aB)>>1) : aA; + return (rC | (gC << 8) | (bC << 16) | (aC << 24)); } @@ -54,8 +54,6 @@ static u32 Deposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA, return pixA; } - const u32 weightSum = weightA + weightB; - const u32 rbA = pixA & 0x00FF00FF; const u32 gA = pixA & 0x0000FF00; const u32 aA = (pixA & 0xFF000000) >> 24; @@ -63,13 +61,45 @@ static u32 Deposterize_Blend(const u32 pixA, const u32 pixB, const u32 weightA, const u32 rbB = pixB & 0x00FF00FF; const u32 gB = pixB & 0x0000FF00; - const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / weightSum ) & 0x00FF00FF; - const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / weightSum ) & 0x0000FF00; - const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / weightSum ) << 24; + // Note: The sum of weightA and weightB must equal 16. + const u32 rbC = ( ((rbA * weightA) + (rbB * weightB)) / 16 ) & 0x00FF00FF; + const u32 gC = ( (( gA * weightA) + ( gB * weightB)) / 16 ) & 0x0000FF00; + const u32 aC = ( (( aA * weightA) + ( aB * weightB)) / 16 ) << 24; return (rbC | gC | aC); } +static u32 Deposterize_BlendPixel(const u32 color[9]) +{ + const u32 blend[9] = { + color[0], + Deposterize_InterpLTE(color[0], color[1]), + Deposterize_InterpLTE(color[0], color[2]), + Deposterize_InterpLTE(color[0], color[3]), + Deposterize_InterpLTE(color[0], color[4]), + Deposterize_InterpLTE(color[0], color[5]), + Deposterize_InterpLTE(color[0], color[6]), + Deposterize_InterpLTE(color[0], color[7]), + Deposterize_InterpLTE(color[0], color[8]) + }; + + return Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 2, 14), + Deposterize_Blend(blend[0], blend[1], 2, 14), + 8, 8), + Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 2, 14), + Deposterize_Blend(blend[0], blend[3], 2, 14), + 8, 8), + 8, 8), + Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9), + Deposterize_Blend(blend[0], blend[2], 7, 9), + 8, 8), + Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9), + Deposterize_Blend(blend[0], blend[4], 7, 9), + 8, 8), + 8, 8), + 12, 4); +} + void RenderDeposterize(SSurface Src, SSurface Dst) { //---------------------------------------\n\ @@ -79,19 +109,40 @@ void RenderDeposterize(SSurface Src, SSurface Dst) // // Output Pixel Mapping: 00 - const int w = Src.Width; - const int h = Src.Height; + const size_t w = Src.Width; + const size_t h = Src.Height; u32 color[9]; - u32 blend[9]; u32 *src = (u32 *)Src.Surface; u32 *workingDst = (u32 *)Dst.workingSurface[0]; u32 *finalDst = (u32 *)Dst.Surface; - int i = 0; - for (int y = 0; y < h; y++) + size_t i = 0; + + for (size_t x = 0; x < w; x++, i++) { - for (int x = 0; x < w; x++, i++) + if ((src[i] & 0xFF000000) == 0) + { + workingDst[i] = src[i]; + continue; + } + + color[0] = src[i]; + color[1] = (x < w-1) ? src[i+1] : src[i]; + color[2] = (x < w-1) ? src[i+w+1] : src[i]; + color[3] = src[i]; + color[4] = (x > 0) ? src[i+w-1] : src[i]; + color[5] = (x > 0) ? src[i-1] : src[i]; + color[6] = src[i]; + color[7] = src[i]; + color[8] = src[i]; + + workingDst[i] = Deposterize_BlendPixel(color); + } + + for (size_t y = 1; y < h-1; y++) + { + for (size_t x = 0; x < w; x++, i++) { if ((src[i] & 0xFF000000) == 0) { @@ -99,48 +150,67 @@ void RenderDeposterize(SSurface Src, SSurface Dst) continue; } - color[0] = src[i]; - color[1] = (x < w-1) ? src[i+1] : src[i]; - color[2] = ((x < w-1) && (y < h-1)) ? src[i+w+1] : src[i]; - color[3] = (y < h-1) ? src[i+w] : src[i]; - color[4] = ((x > 0) && (y < h-1)) ? src[i+w-1] : src[i]; - color[5] = (x > 0) ? src[i-1] : src[i]; - color[6] = ((x > 0) && (y > 0)) ? src[i-w-1] : src[i]; - color[7] = (y > 0) ? src[i-w] : src[i]; - color[8] = ((x < w-1) && (y > 0)) ? src[i-w+1] : src[i]; + color[0] = src[i]; + color[1] = (x < w-1) ? src[i+1] : src[i]; + color[2] = (x < w-1) ? src[i+w+1] : src[i]; + color[3] = src[i+w]; + color[4] = (x > 0) ? src[i+w-1] : src[i]; + color[5] = (x > 0) ? src[i-1] : src[i]; + color[6] = (x > 0) ? src[i-w-1] : src[i]; + color[7] = src[i-w]; + color[8] = (x < w-1) ? src[i-w+1] : src[i]; - blend[0] = color[0]; - blend[1] = Deposterize_InterpLTE(color[0], color[1]); - blend[2] = Deposterize_InterpLTE(color[0], color[2]); - blend[3] = Deposterize_InterpLTE(color[0], color[3]); - blend[4] = Deposterize_InterpLTE(color[0], color[4]); - blend[5] = Deposterize_InterpLTE(color[0], color[5]); - blend[6] = Deposterize_InterpLTE(color[0], color[6]); - blend[7] = Deposterize_InterpLTE(color[0], color[7]); - blend[8] = Deposterize_InterpLTE(color[0], color[8]); - - workingDst[i] = Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 1, 7), - Deposterize_Blend(blend[0], blend[1], 1, 7), - 1, 1), - Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 1, 7), - Deposterize_Blend(blend[0], blend[3], 1, 7), - 1, 1), - 1, 1), - Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9), - Deposterize_Blend(blend[0], blend[2], 7, 9), - 1, 1), - Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9), - Deposterize_Blend(blend[0], blend[4], 7, 9), - 1, 1), - 1, 1), - 3, 1); + workingDst[i] = Deposterize_BlendPixel(color); } } - i = 0; - for (int y = 0; y < h; y++) + for (size_t x = 0; x < w; x++, i++) { - for (int x = 0; x < w; x++, i++) + if ((src[i] & 0xFF000000) == 0) + { + workingDst[i] = src[i]; + continue; + } + + color[0] = src[i]; + color[1] = (x < w-1) ? src[i+1] : src[i]; + color[2] = src[i]; + color[3] = src[i]; + color[4] = src[i]; + color[5] = (x > 0) ? src[i-1] : src[i]; + color[6] = (x > 0) ? src[i-w-1] : src[i]; + color[7] = src[i]; + color[8] = (x < w-1) ? src[i-w+1] : src[i]; + + workingDst[i] = Deposterize_BlendPixel(color); + } + + i = 0; + + for (size_t x = 0; x < w; x++, i++) + { + if ((src[i] & 0xFF000000) == 0) + { + finalDst[i] = src[i]; + continue; + } + + color[0] = workingDst[i]; + color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i]; + color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i]; + color[3] = workingDst[i]; + color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i]; + color[5] = (x > 0) ? workingDst[i-1] : workingDst[i]; + color[6] = workingDst[i]; + color[7] = workingDst[i]; + color[8] = workingDst[i]; + + finalDst[i] = Deposterize_BlendPixel(color); + } + + for (size_t y = 1; y < h-1; y++) + { + for (size_t x = 0; x < w; x++, i++) { if ((src[i] & 0xFF000000) == 0) { @@ -148,41 +218,38 @@ void RenderDeposterize(SSurface Src, SSurface Dst) continue; } - color[0] = workingDst[i]; - color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i]; - color[2] = ((x < w-1) && (y < h-1)) ? workingDst[i+w+1] : workingDst[i]; - color[3] = (y < h-1) ? workingDst[i+w] : workingDst[i]; - color[4] = ((x > 0) && (y < h-1)) ? workingDst[i+w-1] : workingDst[i]; - color[5] = (x > 0) ? workingDst[i-1] : workingDst[i]; - color[6] = ((x > 0) && (y > 0)) ? workingDst[i-w-1] : workingDst[i]; - color[7] = (y > 0) ? workingDst[i-w] : workingDst[i]; - color[8] = ((x < w-1) && (y > 0)) ? workingDst[i-w+1] : workingDst[i]; + color[0] = workingDst[i]; + color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i]; + color[2] = (x < w-1) ? workingDst[i+w+1] : workingDst[i]; + color[3] = workingDst[i+w]; + color[4] = (x > 0) ? workingDst[i+w-1] : workingDst[i]; + color[5] = (x > 0) ? workingDst[i-1] : workingDst[i]; + color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i]; + color[7] = workingDst[i-w]; + color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i]; - blend[0] = color[0]; - blend[1] = Deposterize_InterpLTE(color[0], color[1]); - blend[2] = Deposterize_InterpLTE(color[0], color[2]); - blend[3] = Deposterize_InterpLTE(color[0], color[3]); - blend[4] = Deposterize_InterpLTE(color[0], color[4]); - blend[5] = Deposterize_InterpLTE(color[0], color[5]); - blend[6] = Deposterize_InterpLTE(color[0], color[6]); - blend[7] = Deposterize_InterpLTE(color[0], color[7]); - blend[8] = Deposterize_InterpLTE(color[0], color[8]); - - finalDst[i] = Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[5], 1, 7), - Deposterize_Blend(blend[0], blend[1], 1, 7), - 1, 1), - Deposterize_Blend(Deposterize_Blend(blend[0], blend[7], 1, 7), - Deposterize_Blend(blend[0], blend[3], 1, 7), - 1, 1), - 1, 1), - Deposterize_Blend(Deposterize_Blend(Deposterize_Blend(blend[0], blend[6], 7, 9), - Deposterize_Blend(blend[0], blend[2], 7, 9), - 1, 1), - Deposterize_Blend(Deposterize_Blend(blend[0], blend[8], 7, 9), - Deposterize_Blend(blend[0], blend[4], 7, 9), - 1, 1), - 1, 1), - 3, 1); + finalDst[i] = Deposterize_BlendPixel(color); } } + + for (size_t x = 0; x < w; x++, i++) + { + if ((src[i] & 0xFF000000) == 0) + { + finalDst[i] = src[i]; + continue; + } + + color[0] = workingDst[i]; + color[1] = (x < w-1) ? workingDst[i+1] : workingDst[i]; + color[2] = workingDst[i]; + color[3] = workingDst[i]; + color[4] = workingDst[i]; + color[5] = (x > 0) ? workingDst[i-1] : workingDst[i]; + color[6] = (x > 0) ? workingDst[i-w-1] : workingDst[i]; + color[7] = workingDst[i]; + color[8] = (x < w-1) ? workingDst[i-w+1] : workingDst[i]; + + finalDst[i] = Deposterize_BlendPixel(color); + } } diff --git a/desmume/src/filter/videofilter.cpp b/desmume/src/filter/videofilter.cpp index d140be566..c78fae8f1 100644 --- a/desmume/src/filter/videofilter.cpp +++ b/desmume/src/filter/videofilter.cpp @@ -76,10 +76,71 @@ static const _VideoFilterParamAttributes _VideoFilterParamAttributesList[] = { /******************************************************************************************** CLASS CONSTRUCTORS ********************************************************************************************/ +VideoFilter::VideoFilter() +{ + __InstanceInit(32, 32, VideoFilterTypeID_None, 0); +} + VideoFilter::VideoFilter(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID = VideoFilterTypeID_None, size_t threadCount = 0) +{ + __InstanceInit(srcWidth, srcHeight, VideoFilterTypeID_None, threadCount); +} + +/******************************************************************************************** + CLASS DESTRUCTOR + ********************************************************************************************/ +VideoFilter::~VideoFilter() +{ + // Destroy all threads first + for (size_t i = 0; i < __vfThread.size(); i++) + { + __vfThread[i].task->finish(); + __vfThread[i].task->shutdown(); + + delete __vfThread[i].task; + } + + __vfThread.clear(); + + // Destroy everything else + ThreadLockLock(&_lockSrc); + ThreadLockLock(&_lockDst); + + while (__isCPUFilterRunning) + { + ThreadCondWait(&__condCPUFilterRunning, &_lockDst); + } + + if (_useInternalDstBuffer) + { + free(__vfDstSurface.Surface); + __vfDstSurface.Surface = NULL; + } + + for (size_t i = 0; i < _vfAttributes.workingSurfaceCount; i++) + { + free(__vfDstSurface.workingSurface[i]); + __vfDstSurface.workingSurface[i] = NULL; + } + + ThreadLockUnlock(&_lockDst); + + free(__vfSrcSurfacePixBuffer); + __vfSrcSurfacePixBuffer = NULL; + __vfSrcSurface.Surface = NULL; + + ThreadLockUnlock(&_lockSrc); + + ThreadLockDestroy(&_lockSrc); + ThreadLockDestroy(&_lockDst); + ThreadLockDestroy(&_lockAttributes); + ThreadCondDestroy(&__condCPUFilterRunning); +} + +void VideoFilter::__InstanceInit(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount) { SSurface newSurface; newSurface.Surface = NULL; @@ -93,12 +154,12 @@ VideoFilter::VideoFilter(size_t srcWidth, newSurface.workingSurface[i] = NULL; } - _vfSrcSurface = newSurface; - _vfDstSurface = newSurface; + __vfSrcSurface = newSurface; + __vfDstSurface = newSurface; _useInternalDstBuffer = true; - _isFilterRunning = false; - _vfSrcSurfacePixBuffer = NULL; + __isCPUFilterRunning = false; + __vfSrcSurfacePixBuffer = NULL; if (typeID < VideoFilterTypeIDCount) { @@ -109,80 +170,31 @@ VideoFilter::VideoFilter(size_t srcWidth, _vfAttributes = VideoFilterAttributesList[VideoFilterTypeID_None]; } + _pixelScale = (float)_vfAttributes.scaleMultiply / (float)_vfAttributes.scaleDivide; + ThreadLockInit(&_lockSrc); ThreadLockInit(&_lockDst); ThreadLockInit(&_lockAttributes); - ThreadCondInit(&_condRunning); + ThreadCondInit(&__condCPUFilterRunning); // Create all threads - _vfThread.resize(threadCount); + __vfThread.resize(threadCount); for (size_t i = 0; i < threadCount; i++) { - _vfThread[i].param.srcSurface = _vfSrcSurface; - _vfThread[i].param.dstSurface = _vfDstSurface; - _vfThread[i].param.filterFunction = NULL; + __vfThread[i].param.srcSurface = __vfSrcSurface; + __vfThread[i].param.dstSurface = __vfDstSurface; + __vfThread[i].param.filterFunction = NULL; - _vfThread[i].task = new Task; - _vfThread[i].task->start(false); + __vfThread[i].task = new Task; + __vfThread[i].task->start(false); } - _vfFunc = _vfAttributes.filterFunction; + __vfFunc = _vfAttributes.filterFunction; SetSourceSize(srcWidth, srcHeight); } -/******************************************************************************************** - CLASS DESTRUCTOR - ********************************************************************************************/ -VideoFilter::~VideoFilter() -{ - // Destroy all threads first - for (size_t i = 0; i < _vfThread.size(); i++) - { - _vfThread[i].task->finish(); - _vfThread[i].task->shutdown(); - - delete _vfThread[i].task; - } - - _vfThread.clear(); - - // Destroy everything else - ThreadLockLock(&_lockSrc); - ThreadLockLock(&_lockDst); - - while (_isFilterRunning) - { - ThreadCondWait(&_condRunning, &_lockDst); - } - - if (_useInternalDstBuffer) - { - free(_vfDstSurface.Surface); - _vfDstSurface.Surface = NULL; - } - - for (size_t i = 0; i < _vfAttributes.workingSurfaceCount; i++) - { - free(_vfDstSurface.workingSurface[i]); - _vfDstSurface.workingSurface[i] = NULL; - } - - ThreadLockUnlock(&_lockDst); - - free(_vfSrcSurfacePixBuffer); - _vfSrcSurfacePixBuffer = NULL; - _vfSrcSurface.Surface = NULL; - - ThreadLockUnlock(&_lockSrc); - - ThreadLockDestroy(&_lockSrc); - ThreadLockDestroy(&_lockDst); - ThreadLockDestroy(&_lockAttributes); - ThreadCondDestroy(&_condRunning); -} - -bool VideoFilter::AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount) +bool VideoFilter::__AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount) { bool result = false; unsigned char *newSurfaceBuffer = NULL; @@ -201,32 +213,32 @@ bool VideoFilter::AllocateDstBuffer(const size_t dstWidth, const size_t dstHeigh for (size_t i = 0; i < FILTER_MAX_WORKING_SURFACE_COUNT; i++) { - unsigned char *oldWorkingSurface = this->_vfDstSurface.workingSurface[i]; - this->_vfDstSurface.workingSurface[i] = (i < workingSurfaceCount) ? (unsigned char *)calloc(dstWidth * dstHeight, sizeof(uint32_t)) : NULL; + unsigned char *oldWorkingSurface = this->__vfDstSurface.workingSurface[i]; + this->__vfDstSurface.workingSurface[i] = (i < workingSurfaceCount) ? (unsigned char *)calloc(dstWidth * dstHeight, sizeof(uint32_t)) : NULL; free(oldWorkingSurface); } // Set up SSurface structure. - this->_vfDstSurface.Width = dstWidth; - this->_vfDstSurface.Height = dstHeight; - this->_vfDstSurface.Pitch = dstWidth * 2; + this->__vfDstSurface.Width = dstWidth; + this->__vfDstSurface.Height = dstHeight; + this->__vfDstSurface.Pitch = dstWidth * 2; if (_useInternalDstBuffer) { - unsigned char *oldBuffer = this->_vfDstSurface.Surface; - this->_vfDstSurface.Surface = newSurfaceBuffer; + unsigned char *oldBuffer = this->__vfDstSurface.Surface; + this->__vfDstSurface.Surface = newSurfaceBuffer; free(oldBuffer); } // Update the surfaces on threads. - const size_t threadCount = this->_vfThread.size(); + const size_t threadCount = this->__vfThread.size(); const unsigned int linesPerThread = (threadCount > 1) ? dstHeight/threadCount : dstHeight; unsigned int remainingLines = dstHeight; for (size_t i = 0; i < threadCount; i++) { - SSurface &threadDstSurface = this->_vfThread[i].param.dstSurface; - threadDstSurface = this->_vfDstSurface; + SSurface &threadDstSurface = this->__vfThread[i].param.dstSurface; + threadDstSurface = this->__vfDstSurface; threadDstSurface.Height = (linesPerThread < remainingLines) ? linesPerThread : remainingLines; remainingLines -= threadDstSurface.Height; @@ -238,7 +250,7 @@ bool VideoFilter::AllocateDstBuffer(const size_t dstWidth, const size_t dstHeigh if (i > 0) { - SSurface &prevThreadDstSurface = this->_vfThread[i - 1].param.dstSurface; + SSurface &prevThreadDstSurface = this->__vfThread[i - 1].param.dstSurface; threadDstSurface.Surface = (unsigned char *)((uint32_t *)prevThreadDstSurface.Surface + (prevThreadDstSurface.Width * prevThreadDstSurface.Height)); for (size_t j = 0; j < workingSurfaceCount; j++) @@ -284,30 +296,30 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height) return result; } - if (this->_vfSrcSurface.Surface == NULL || this->_vfSrcSurface.Width != width || this->_vfSrcSurface.Height != height) + if (this->__vfSrcSurface.Surface == NULL || this->__vfSrcSurface.Width != width || this->__vfSrcSurface.Height != height) { sizeChanged = true; } - this->_vfSrcSurface.Width = width; - this->_vfSrcSurface.Height = height; - this->_vfSrcSurface.Pitch = width * 2; + this->__vfSrcSurface.Width = width; + this->__vfSrcSurface.Height = height; + this->__vfSrcSurface.Pitch = width * 2; // Set the working source buffer pointer so that the working memory block is padded // with 4 pixel rows worth of memory on both sides. - this->_vfSrcSurface.Surface = (unsigned char *)(newPixBuffer + (width * 4)); + this->__vfSrcSurface.Surface = (unsigned char *)(newPixBuffer + (width * 4)); - free(this->_vfSrcSurfacePixBuffer); - this->_vfSrcSurfacePixBuffer = newPixBuffer; + free(this->__vfSrcSurfacePixBuffer); + this->__vfSrcSurfacePixBuffer = newPixBuffer; // Update the surfaces on threads. - size_t threadCount = this->_vfThread.size(); - const unsigned int linesPerThread = (threadCount > 1) ? this->_vfSrcSurface.Height/threadCount : this->_vfSrcSurface.Height; - unsigned int remainingLines = this->_vfSrcSurface.Height; + size_t threadCount = this->__vfThread.size(); + const unsigned int linesPerThread = (threadCount > 1) ? this->__vfSrcSurface.Height/threadCount : this->__vfSrcSurface.Height; + unsigned int remainingLines = this->__vfSrcSurface.Height; for (size_t i = 0; i < threadCount; i++) { - SSurface &threadSrcSurface = this->_vfThread[i].param.srcSurface; - threadSrcSurface = this->_vfSrcSurface; + SSurface &threadSrcSurface = this->__vfThread[i].param.srcSurface; + threadSrcSurface = this->__vfSrcSurface; threadSrcSurface.Height = (linesPerThread < remainingLines) ? linesPerThread : remainingLines; remainingLines -= threadSrcSurface.Height; @@ -319,7 +331,7 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height) if (i > 0) { - SSurface &prevThreadSrcSurface = this->_vfThread[i - 1].param.srcSurface; + SSurface &prevThreadSrcSurface = this->__vfThread[i - 1].param.srcSurface; threadSrcSurface.Surface = (unsigned char *)((uint32_t *)prevThreadSrcSurface.Surface + (prevThreadSrcSurface.Width * prevThreadSrcSurface.Height)); } } @@ -332,7 +344,9 @@ bool VideoFilter::SetSourceSize(const size_t width, const size_t height) const size_t dstWidth = width * vfAttr.scaleMultiply / vfAttr.scaleDivide; const size_t dstHeight = height * vfAttr.scaleMultiply / vfAttr.scaleDivide; - result = this->AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount); + this->_pixelScale = (float)vfAttr.scaleMultiply / (float)vfAttr.scaleDivide; + + result = this->__AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount); if (!result) { return result; @@ -392,11 +406,11 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr) } ThreadLockLock(&this->_lockDst); - unsigned char *dstSurface = this->_vfDstSurface.Surface; + unsigned char *dstSurface = this->__vfDstSurface.Surface; ThreadLockUnlock(&this->_lockDst); const VideoFilterAttributes currentAttr = this->GetAttributes(); - const size_t threadCount = this->_vfThread.size(); + const size_t threadCount = this->__vfThread.size(); if (dstSurface != NULL && currentAttr.scaleMultiply == vfAttr.scaleMultiply && @@ -408,18 +422,18 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr) ThreadLockLock(&this->_lockDst); - const size_t bufferSizeBytes = this->_vfDstSurface.Width * this->_vfDstSurface.Height * sizeof(uint32_t); + const size_t bufferSizeBytes = this->__vfDstSurface.Width * this->__vfDstSurface.Height * sizeof(uint32_t); - memset(this->_vfDstSurface.Surface, 0, bufferSizeBytes); + memset(this->__vfDstSurface.Surface, 0, bufferSizeBytes); for (size_t i = 0; i < currentAttr.workingSurfaceCount; i++) { - memset(this->_vfDstSurface.workingSurface[i], 0, bufferSizeBytes); + memset(this->__vfDstSurface.workingSurface[i], 0, bufferSizeBytes); } - this->_vfFunc = vfAttr.filterFunction; + this->__vfFunc = vfAttr.filterFunction; for (size_t i = 0; i < threadCount; i++) { - this->_vfThread[i].param.filterFunction = this->_vfFunc; + this->__vfThread[i].param.filterFunction = this->__vfFunc; } ThreadLockUnlock(&this->_lockDst); @@ -428,28 +442,30 @@ bool VideoFilter::ChangeFilterByAttributes(const VideoFilterAttributes &vfAttr) { // Construct a new destination buffer per filter attributes. ThreadLockLock(&this->_lockSrc); - const size_t dstWidth = this->_vfSrcSurface.Width * vfAttr.scaleMultiply / vfAttr.scaleDivide; - const size_t dstHeight = this->_vfSrcSurface.Height * vfAttr.scaleMultiply / vfAttr.scaleDivide; + const size_t dstWidth = this->__vfSrcSurface.Width * vfAttr.scaleMultiply / vfAttr.scaleDivide; + const size_t dstHeight = this->__vfSrcSurface.Height * vfAttr.scaleMultiply / vfAttr.scaleDivide; ThreadLockUnlock(&this->_lockSrc); ThreadLockLock(&this->_lockDst); - this->_vfFunc = vfAttr.filterFunction; + this->__vfFunc = vfAttr.filterFunction; for (size_t i = 0; i < threadCount; i++) { - this->_vfThread[i].param.filterFunction = this->_vfFunc; + this->__vfThread[i].param.filterFunction = this->__vfFunc; } ThreadLockUnlock(&this->_lockDst); - result = this->AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount); + result = this->__AllocateDstBuffer(dstWidth, dstHeight, vfAttr.workingSurfaceCount); if (!result) { return result; } } - this->SetAttributes(vfAttr); + ThreadLockLock(&this->_lockAttributes); + this->_vfAttributes = vfAttr; + ThreadLockUnlock(&this->_lockAttributes); result = true; return result; @@ -472,40 +488,40 @@ uint32_t* VideoFilter::RunFilter() ThreadLockLock(&this->_lockSrc); ThreadLockLock(&this->_lockDst); - this->_isFilterRunning = true; + this->__isCPUFilterRunning = true; - if (this->_vfFunc == NULL) + if (this->__vfFunc == NULL) { - memcpy(this->_vfDstSurface.Surface, this->_vfSrcSurface.Surface, this->_vfDstSurface.Width * this->_vfDstSurface.Height * sizeof(uint32_t)); + memcpy(this->__vfDstSurface.Surface, this->__vfSrcSurface.Surface, this->__vfDstSurface.Width * this->__vfDstSurface.Height * sizeof(uint32_t)); } else { - const size_t threadCount = this->_vfThread.size(); + const size_t threadCount = this->__vfThread.size(); if (threadCount > 0) { for (size_t i = 0; i < threadCount; i++) { - this->_vfThread[i].task->execute(&RunVideoFilterTask, &this->_vfThread[i].param); + this->__vfThread[i].task->execute(&RunVideoFilterTask, &this->__vfThread[i].param); } for (size_t i = 0; i < threadCount; i++) { - this->_vfThread[i].task->finish(); + this->__vfThread[i].task->finish(); } } else { - this->_vfFunc(this->_vfSrcSurface, this->_vfDstSurface); + this->__vfFunc(this->__vfSrcSurface, this->__vfDstSurface); } } - this->_isFilterRunning = false; - ThreadCondSignal(&this->_condRunning); + this->__isCPUFilterRunning = false; + ThreadCondSignal(&this->__condCPUFilterRunning); ThreadLockUnlock(&this->_lockDst); ThreadLockUnlock(&this->_lockSrc); - return (uint32_t *)this->_vfDstSurface.Surface; + return (uint32_t *)this->__vfDstSurface.Surface; } /******************************************************************************************** @@ -686,13 +702,6 @@ VideoFilterAttributes VideoFilter::GetAttributes() return vfAttr; } -void VideoFilter::SetAttributes(const VideoFilterAttributes &vfAttr) -{ - ThreadLockLock(&this->_lockAttributes); - this->_vfAttributes = vfAttr; - ThreadLockUnlock(&this->_lockAttributes); -} - VideoFilterTypeID VideoFilter::GetTypeID() { ThreadLockLock(&this->_lockAttributes); @@ -714,7 +723,7 @@ const char* VideoFilter::GetTypeString() uint32_t* VideoFilter::GetSrcBufferPtr() { ThreadLockLock(&this->_lockSrc); - uint32_t *ptr = (uint32_t *)this->_vfSrcSurface.Surface; + uint32_t *ptr = (uint32_t *)this->__vfSrcSurface.Surface; ThreadLockUnlock(&this->_lockSrc); return ptr; @@ -723,7 +732,7 @@ uint32_t* VideoFilter::GetSrcBufferPtr() uint32_t* VideoFilter::GetDstBufferPtr() { ThreadLockLock(&this->_lockDst); - uint32_t *ptr = (uint32_t *)this->_vfDstSurface.Surface; + uint32_t *ptr = (uint32_t *)this->__vfDstSurface.Surface; ThreadLockUnlock(&this->_lockDst); return ptr; @@ -759,8 +768,8 @@ void VideoFilter::SetDstBufferPtr(uint32_t *theBuffer) } else { - unsigned char *oldDstBuffer = this->_vfDstSurface.Surface; - this->_vfDstSurface.Surface = (unsigned char *)theBuffer; + unsigned char *oldDstBuffer = this->__vfDstSurface.Surface; + this->__vfDstSurface.Surface = (unsigned char *)theBuffer; if (this->_useInternalDstBuffer) { @@ -772,13 +781,13 @@ void VideoFilter::SetDstBufferPtr(uint32_t *theBuffer) ThreadLockUnlock(&this->_lockDst); - this->AllocateDstBuffer(this->_vfDstSurface.Width, this->_vfDstSurface.Height, this->_vfAttributes.workingSurfaceCount); + this->__AllocateDstBuffer(this->__vfDstSurface.Width, this->__vfDstSurface.Height, this->_vfAttributes.workingSurfaceCount); } size_t VideoFilter::GetSrcWidth() { ThreadLockLock(&this->_lockSrc); - size_t width = this->_vfSrcSurface.Width; + size_t width = this->__vfSrcSurface.Width; ThreadLockUnlock(&this->_lockSrc); return width; @@ -787,7 +796,7 @@ size_t VideoFilter::GetSrcWidth() size_t VideoFilter::GetSrcHeight() { ThreadLockLock(&this->_lockSrc); - size_t height = this->_vfSrcSurface.Height; + size_t height = this->__vfSrcSurface.Height; ThreadLockUnlock(&this->_lockSrc); return height; @@ -796,7 +805,7 @@ size_t VideoFilter::GetSrcHeight() size_t VideoFilter::GetDstWidth() { ThreadLockLock(&this->_lockDst); - size_t width = this->_vfDstSurface.Width; + size_t width = this->__vfDstSurface.Width; ThreadLockUnlock(&this->_lockDst); return width; @@ -805,12 +814,17 @@ size_t VideoFilter::GetDstWidth() size_t VideoFilter::GetDstHeight() { ThreadLockLock(&this->_lockDst); - size_t height = this->_vfDstSurface.Height; + size_t height = this->__vfDstSurface.Height; ThreadLockUnlock(&this->_lockDst); return height; } +float VideoFilter::GetPixelScale() +{ + return this->_pixelScale; +} + VideoFilterParamType VideoFilter::GetFilterParameterType(VideoFilterParamID paramID) const { return _VideoFilterParamAttributesList[paramID].type; diff --git a/desmume/src/filter/videofilter.h b/desmume/src/filter/videofilter.h index d4b8656db..9a101cd27 100644 --- a/desmume/src/filter/videofilter.h +++ b/desmume/src/filter/videofilter.h @@ -151,25 +151,28 @@ typedef struct class VideoFilter { private: - VideoFilterAttributes _vfAttributes; - - SSurface _vfSrcSurface; - SSurface _vfDstSurface; - uint32_t *_vfSrcSurfacePixBuffer; - VideoFilterFunc _vfFunc; - std::vector _vfThread; + SSurface __vfSrcSurface; + SSurface __vfDstSurface; + uint32_t *__vfSrcSurfacePixBuffer; + VideoFilterFunc __vfFunc; + std::vector __vfThread; bool _useInternalDstBuffer; - bool _isFilterRunning; + bool __isCPUFilterRunning; + ThreadCond __condCPUFilterRunning; + + void __InstanceInit(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount); + bool __AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount); + +protected: + VideoFilterAttributes _vfAttributes; ThreadLock _lockSrc; ThreadLock _lockDst; ThreadLock _lockAttributes; - ThreadCond _condRunning; - - bool AllocateDstBuffer(const size_t dstWidth, const size_t dstHeight, const size_t workingSurfaceCount); - void SetAttributes(const VideoFilterAttributes &vfAttr); + float _pixelScale; public: + VideoFilter(); VideoFilter(size_t srcWidth, size_t srcHeight, VideoFilterTypeID typeID, size_t threadCount); ~VideoFilter(); @@ -193,6 +196,7 @@ public: size_t GetSrcHeight(); size_t GetDstWidth(); size_t GetDstHeight(); + float GetPixelScale(); VideoFilterParamType GetFilterParameterType(VideoFilterParamID paramID) const; int GetFilterParameteri(VideoFilterParamID paramID); unsigned int GetFilterParameterui(VideoFilterParamID paramID);