Optimize blur filter
authorHeeyong Song <heeyong.song@samsung.com>
Fri, 14 Mar 2014 04:15:05 +0000 (13:15 +0900)
committerHeeyong Song <heeyong.song@samsung.com>
Fri, 14 Mar 2014 04:15:05 +0000 (13:15 +0900)
Change-Id: Ida7ad741bac4c00df2ce44b07aafbfc639bfac30

src/ui/animations/FUiAnim_GlRenderManager.cpp
src/ui/animations/FUiAnim_ShaderProgramGenerator.cpp
src/ui/animations/FUiAnim_VisualElementFilterImpl.cpp
src/ui/animations/FUiAnim_VisualElementFilterImpl.h

index d23e49c..b08fa62 100644 (file)
@@ -425,16 +425,11 @@ _GlRenderManager::_RenderObject::SetObject(_GlNode* pNode, bool useStencil, unsi
        }
 #endif
 
-       if (pNode->__pFilter && pNode->__useFilter)
+       if (pNode->__pFilter && pNode->__useFilter && pNode->__pFilter->IsEnabled())
        {
-               _VisualElementFilterImpl* pFilterImpl = _VisualElementFilterImpl::GetInstance(*pNode->__pFilter);
+               shaderType |= SHADER_TYPE_BLUR;
 
-               if (pFilterImpl->IsEnabled())
-               {
-                       shaderType |= SHADER_TYPE_BLUR;
-
-                       __pFilter = pNode->__pFilter;
-               }
+               __pFilter = pNode->__pFilter;
        }
 
        if (likely(!pNode->__pMesh))
@@ -1304,11 +1299,22 @@ _GlRenderManager::FlushRenderQueue(void)
                        if (__pRenderQueue[i].__pFilter)
                        {
                                _VisualElementFilterImpl* pFilterImpl = _VisualElementFilterImpl::GetInstance(*__pRenderQueue[i].__pFilter);
+                               float x, y;
+
+                               if (pFilterImpl->__isFirstPass)
+                               {
+                                       x = 1.0f / __pRenderQueue[i].__pSurfaceInfo->width;
+                                       y = 0.0f;
+                               }
+                               else
+                               {
+                                       x = 0.0f;
+                                       y = 1.0f / __pRenderQueue[i].__pSurfaceInfo->height;
+                               }
 
-                               glUniform1i(glGetUniformLocation(pProgramImpl->__program, "u_blurSize"), pFilterImpl->__kernelSize);
-                               glUniform1i(glGetUniformLocation(pProgramImpl->__program, "u_horizontalPass"), pFilterImpl->__isFirstPass ? 1 : 0);
+                               glUniform1f(glGetUniformLocation(pProgramImpl->__program, "u_radius"), pFilterImpl->__radius);
                                glUniform1f(glGetUniformLocation(pProgramImpl->__program, "u_sigma"), pFilterImpl->__sigma);
-                               glUniform2f(glGetUniformLocation(pProgramImpl->__program, "u_texcoordOffset"), 1.0f / __pRenderQueue[i].__pSurfaceInfo->width, 1.0f / __pRenderQueue[i].__pSurfaceInfo->height);
+                               glUniform2f(glGetUniformLocation(pProgramImpl->__program, "u_directionVec"), x, y);
                        }
                }
                else
@@ -1600,7 +1606,7 @@ _GlRenderManager::CompositeNode(VisualElement* pRenderObject, Tizen::Base::Colle
                useStencil |= (pNode->__useStencil) ? true : false;
                updateStencil = (pNode->__useStencil && pChildImpl->GetChildrenCount() > 0) ? true : false;
 
-               if (pNode->__pFilter)
+               if (pNode->__pFilter && pNode->__pFilter->IsEnabled())
                {
                        _VisualElementFilterImpl* pFilterImpl = _VisualElementFilterImpl::GetInstance(*pNode->__pFilter);
                        bool useTempNode = false;
@@ -1619,6 +1625,8 @@ _GlRenderManager::CompositeNode(VisualElement* pRenderObject, Tizen::Base::Colle
 
                                pNode->__useFilter = false;
 
+                               glViewport(0, 0, pRenderTextureInfo->width, pRenderTextureInfo->height);
+
                                EnqueueRenderObject(pNode, false, 0, true);
 
                                FlushRenderQueue();
@@ -1645,6 +1653,8 @@ _GlRenderManager::CompositeNode(VisualElement* pRenderObject, Tizen::Base::Colle
 
                                pFilterImpl->__isFirstPass = true;
 
+                               glViewport(0, 0, pInternalTextureInfo->width, pInternalTextureInfo->height);
+
                                if (useTempNode)
                                {
                                        __pTempNode->__useBlend = pNode->__useBlend;
@@ -1686,6 +1696,8 @@ _GlRenderManager::CompositeNode(VisualElement* pRenderObject, Tizen::Base::Colle
                                __pTempNode->__textureId = textureId;
                                __pTempNode->__pSurface = pSurface;
 
+                               glViewport(__viewport.x, __viewport.y, __viewport.width, __viewport.height);
+
                                EnqueueRenderObject(__pTempNode, useStencil, stencilIndex, true);
                        }
                        else
index 3be1244..1c081bc 100644 (file)
@@ -255,25 +255,22 @@ namespace Tizen { namespace Ui { namespace Animations {
 
 #define BLUR_FUNCTION  L"vec4 blur(void)\n"\
                                                "{\n"\
-                                               "       float numBlurPixelsPerSide = float(u_blurSize / 2);\n"\
-                                               "       vec2 blurMultiplyVec = u_horizontalPass > 0 ? vec2(1.0, 0.0) : vec2(0.0, 1.0);\n"\
-                                               "\n"\
                                                "       vec3 incrementalGaussian;\n"\
-                                               "       incrementalGaussian.x = 1.0 / (sqrt(2.0 * pi) * u_sigma);\n"\
+                                               "       incrementalGaussian.x = 1.0 / (sqrt_pi2 * u_sigma);\n"\
                                                "       incrementalGaussian.y = exp(-0.5 / (u_sigma * u_sigma));\n"\
                                                "       incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;\n"\
                                                "\n"\
                                                "       vec4 avgValue = vec4(0.0, 0.0, 0.0, 0.0);\n"\
                                                "       float coefficientSum = 0.0;\n"\
                                                "\n"\
-                                               "       avgValue += texture2D(u_tex2d, v_texcoord).bgra * incrementalGaussian.x;\n"\
-                                               "       coefficientSum += incrementalGaussian.x;\n"\
+                                               "       avgValue = texture2D(u_tex2d, v_texcoord).bgra * incrementalGaussian.x;\n"\
+                                               "       coefficientSum = incrementalGaussian.x;\n"\
                                                "       incrementalGaussian.xy *= incrementalGaussian.yz;\n"\
                                                "\n"\
-                                               "       for (float i = 1.0; i <= numBlurPixelsPerSide; i++)\n"\
+                                               "       for (float i = 1.0; i <= u_radius; i++)\n"\
                                                "       {\n"\
-                                               "               avgValue += texture2D(u_tex2d, v_texcoord.st - i * u_texcoordOffset * blurMultiplyVec).bgra * incrementalGaussian.x;\n"\
-                                               "               avgValue += texture2D(u_tex2d, v_texcoord.st + i * u_texcoordOffset * blurMultiplyVec).bgra * incrementalGaussian.x;\n"\
+                                               "               avgValue += texture2D(u_tex2d, v_texcoord.st - i * u_directionVec).bgra * incrementalGaussian.x;\n"\
+                                               "               avgValue += texture2D(u_tex2d, v_texcoord.st + i * u_directionVec).bgra * incrementalGaussian.x;\n"\
                                                "               coefficientSum += 2.0 * incrementalGaussian.x;\n"\
                                                "               incrementalGaussian.xy *= incrementalGaussian.yz;\n"\
                                                "       }\n"\
@@ -774,12 +771,11 @@ _ShaderProgramGenerator::GenerateShaderProgramN(int type)
 
                if (blur)
                {
-                       InsertUniform(L"int", L"u_blurSize", fragmentShader);
-                       InsertUniform(L"int", L"u_horizontalPass", fragmentShader);
+                       InsertUniform(L"float", L"u_radius", fragmentShader);
                        InsertUniform(L"float", L"u_sigma", fragmentShader);
-                       InsertUniform(L"vec2", L"u_texcoordOffset", fragmentShader);
+                       InsertUniform(L"vec2", L"u_directionVec", fragmentShader);
 
-                       InsertVariable(L"const float", L"pi", L"3.14159265", fragmentShader);
+                       InsertVariable(L"const float", L"sqrt_pi2", L"2.50662827", fragmentShader);
 
                        InsertFunction(BLUR_FUNCTION, fragmentShader);
 
index ab7049e..ee696a9 100644 (file)
@@ -27,6 +27,8 @@
 #include "FUiAnim_NativeLayer.h"
 #include "FUiAnim_VisualElementFilterImpl.h"
 
+#define SMALL_SURFACE_SIZE     100
+
 #define PRINT(...) fprintf(stderr, __VA_ARGS__)
 //#define PRINT(...)
 
@@ -35,13 +37,16 @@ namespace Tizen { namespace Ui { namespace Animations
 
 _VisualElementFilterImpl::_VisualElementFilterImpl(void)
        : __type(VisualElementFilter::TYPE_BLUR)
-       , __isFirstPass(true)
        , __size()
+       , __surfaceSize()
        , __pInternalSurface(null)
        , __pRenderSurface(null)
        , __enabled(true)
        , __kernelSize(0.0f)
+       , __radius(0.0f)
        , __sigma(0.0f)
+       , __needRenderSurface(false)
+       , __isFirstPass(true)
 {
 }
 
@@ -108,7 +113,7 @@ _VisualElementFilterImpl::SetKernelSize(float kernelSize)
 
        __kernelSize = kernelSize;
 
-       __sigma = __kernelSize / 2;
+       CalcFilterInfo();
 
        return E_SUCCESS;
 }
@@ -122,32 +127,74 @@ _VisualElementFilterImpl::GetKernelSize(void)
 bool
 _VisualElementFilterImpl::Prepare(const _NativeLayer& layer, const Tizen::Graphics::Dimension& size, bool needRenderSurface)
 {
-       if (__size == size)
-       {
-               return true;
-       }
-
-       DisplayContext* pDisplayContext = layer.GetDisplayContext();
-
-       if (__type == VisualElementFilter::TYPE_BLUR)
-       {
-               // create internal surface
-               __pInternalSurface = new (std::nothrow) VisualElementSurface();
-
-               __pInternalSurface->Construct(*pDisplayContext, size, SURFACE_RENDER_TARGET);
-       }
-
-       if (__pRenderSurface)
-       {
-               delete __pRenderSurface;
-               __pRenderSurface = null;
-       }
+//     if (!__enabled)
+//     {
+//             return true;
+//     }
 
-       if (needRenderSurface)
+       if (__size != size || __needRenderSurface != needRenderSurface)
        {
-               __pRenderSurface = new (std::nothrow) VisualElementSurface();
-
-               __pRenderSurface->Construct(*pDisplayContext, size, SURFACE_RENDER_TARGET);
+               DisplayContext* pDisplayContext = layer.GetDisplayContext();
+               Tizen::Graphics::Dimension surfaceSize;
+
+               if (size.width < SMALL_SURFACE_SIZE || size.height < SMALL_SURFACE_SIZE)
+               {
+                       surfaceSize = size;
+               }
+               else
+               {
+                       surfaceSize.width = size.width / 2;
+                       surfaceSize.height = size.height / 2;
+
+                       needRenderSurface = true;
+               }
+
+               if (__type == VisualElementFilter::TYPE_BLUR)
+               {
+                       if (__surfaceSize != surfaceSize)
+                       {
+                               if (__pInternalSurface)
+                               {
+                                       delete __pInternalSurface;
+                                       __pInternalSurface = null;
+                               }
+
+                               // create internal surface
+                               __pInternalSurface = new (std::nothrow) VisualElementSurface();
+
+                               __pInternalSurface->Construct(*pDisplayContext, surfaceSize, SURFACE_RENDER_TARGET);
+                       }
+               }
+
+               if (needRenderSurface)
+               {
+                       if (__surfaceSize != surfaceSize)
+                       {
+                               if (__pRenderSurface)
+                               {
+                                       delete __pRenderSurface;
+                                       __pRenderSurface = null;
+                               }
+
+                               __pRenderSurface = new (std::nothrow) VisualElementSurface();
+
+                               __pRenderSurface->Construct(*pDisplayContext, surfaceSize, SURFACE_RENDER_TARGET);
+                       }
+               }
+               else
+               {
+                       if (__pRenderSurface)
+                       {
+                               delete __pRenderSurface;
+                               __pRenderSurface = null;
+                       }
+               }
+
+               __size = size;
+               __surfaceSize = surfaceSize;
+               __needRenderSurface = needRenderSurface;
+
+               CalcFilterInfo();
        }
 
        return true;
@@ -165,4 +212,19 @@ _VisualElementFilterImpl::GetInstance(const VisualElementFilter& filter)
        return filter.__pVisualElementFilterImpl;
 }
 
+void
+_VisualElementFilterImpl::CalcFilterInfo(void)
+{
+       if (__size == __surfaceSize)
+       {
+               __radius = __kernelSize / 2;
+       }
+       else
+       {
+               __radius = __kernelSize / 4;
+       }
+
+       __sigma = __kernelSize / 2;
+}
+
 }}}            // Tizen::Ui::Animations
index 199edce..30fe200 100644 (file)
@@ -61,11 +61,13 @@ public:
 private:
        _VisualElementFilterImpl& operator =(const _VisualElementFilterImpl& rhs);
 
+       void CalcFilterInfo(void);
+
 private:
        VisualElementFilter::FilterType __type;
-       bool __isFirstPass;
 
        Tizen::Graphics::Dimension __size;
+       Tizen::Graphics::Dimension __surfaceSize;
 
        VisualElementSurface* __pInternalSurface;
        VisualElementSurface* __pRenderSurface;
@@ -73,8 +75,12 @@ private:
        bool __enabled;
 
        float __kernelSize;
+       float __radius;
        float __sigma;
 
+       bool __needRenderSurface;
+       bool __isFirstPass;
+
        friend class _GlRenderManager;
 }; // _VisualElementFilterImpl