summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorByunghun Jeon <bjeon@codeaurora.org>2014-12-05 18:28:32 -0800
committerSteve Kondik <steve@cyngn.com>2015-11-08 01:07:13 -0800
commit987034b5633d0eb7fca806acfe00ddbe3305b159 (patch)
tree9d186252541a857729a9f3920bd8369d4a056e0d /services
parentb53d92c3eb9319dbf725b3e59b3c52acfa6d77f0 (diff)
downloadframeworks_native-987034b5633d0eb7fca806acfe00ddbe3305b159.zip
frameworks_native-987034b5633d0eb7fca806acfe00ddbe3305b159.tar.gz
frameworks_native-987034b5633d0eb7fca806acfe00ddbe3305b159.tar.bz2
SurfaceFlinger: Native changes to add blur effect
Native changes to add blur-behind and blur mask effect Change-Id: I54faf82d750e8299de6d261f6a893ab26d08df84 SurfaceFlinger: Adding template for LayerBlur files Change-Id: I444009113b7bdd6c5284863fd1f56358e67d9fe6 SurfaceFlinger: Featurize libuiblur module for OSS build Change-Id: Ifdc176e699434125d17b111c044b8ba954cf717c
Diffstat (limited to 'services')
-rw-r--r--services/surfaceflinger/Android.mk7
-rw-r--r--services/surfaceflinger/FrameRateHelper.h69
-rw-r--r--services/surfaceflinger/Layer.cpp21
-rw-r--r--services/surfaceflinger/Layer.h21
-rw-r--r--services/surfaceflinger/LayerBlur.cpp415
-rw-r--r--services/surfaceflinger/LayerBlur.h106
-rw-r--r--services/surfaceflinger/LayerDim.cpp2
-rw-r--r--services/surfaceflinger/LayerDim.h2
-rw-r--r--services/surfaceflinger/RenderEngine/Description.cpp11
-rw-r--r--services/surfaceflinger/RenderEngine/Description.h5
-rw-r--r--services/surfaceflinger/RenderEngine/GLES11RenderEngine.h2
-rw-r--r--services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp29
-rw-r--r--services/surfaceflinger/RenderEngine/GLES20RenderEngine.h10
-rw-r--r--services/surfaceflinger/RenderEngine/Program.cpp8
-rw-r--r--services/surfaceflinger/RenderEngine/Program.h3
-rw-r--r--services/surfaceflinger/RenderEngine/ProgramCache.cpp53
-rw-r--r--services/surfaceflinger/RenderEngine/ProgramCache.h11
-rw-r--r--services/surfaceflinger/RenderEngine/RenderEngine.h7
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp60
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h19
20 files changed, 838 insertions, 23 deletions
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 276a242..c921329 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -13,6 +13,7 @@ LOCAL_SRC_FILES := \
FrameTracker.cpp \
Layer.cpp \
LayerDim.cpp \
+ LayerBlur.cpp \
MessageQueue.cpp \
MonitoredProducer.cpp \
SurfaceFlinger.cpp \
@@ -117,6 +118,12 @@ ifeq ($(TARGET_USES_QCOM_BSP), true)
LOCAL_CFLAGS += -DQTI_BSP
endif
+ifeq ($(TARGET_HAVE_UI_BLUR),true)
+ LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/ui
+ LOCAL_SHARED_LIBRARIES += libuiblur
+ LOCAL_CFLAGS += -DUI_BLUR
+endif
+
LOCAL_MODULE := libsurfaceflinger
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
diff --git a/services/surfaceflinger/FrameRateHelper.h b/services/surfaceflinger/FrameRateHelper.h
new file mode 100644
index 0000000..1a69fed
--- /dev/null
+++ b/services/surfaceflinger/FrameRateHelper.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ANDROID_SF_FRAME_RATE_HELPER_H
+#define ANDROID_SF_FRAME_RATE_HELPER_H
+
+#include <utils/Timers.h>
+
+namespace android {
+
+class FrameRateHelper {
+public:
+ FrameRateHelper() : mTime(0), mFps(0), mFpsCount(0) {}
+ ~FrameRateHelper() {}
+
+ bool update() {
+ mFpsCount++;
+
+ nsecs_t now = systemTime();
+ if (ns2ms(now - mTime) > 1000) {
+ mFps = mFpsCount;
+ mFpsCount = 0;
+ mTime = now;
+ return true;
+ }
+
+ return false;
+ }
+
+ unsigned int get() const {
+ return mFps;
+ }
+
+private:
+ nsecs_t mTime;
+ unsigned int mFps;
+ unsigned int mFpsCount;
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_FRAME_RATE_HELPER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index bcd5915..1ee7242 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -108,6 +108,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
mCurrentState.active.crop.makeInvalid();
mCurrentState.z = 0;
mCurrentState.alpha = 0xFF;
+ mCurrentState.blur = 0xFF;
mCurrentState.layerStack = 0;
mCurrentState.flags = layerFlags;
mCurrentState.sequence = 0;
@@ -607,21 +608,21 @@ Rect Layer::getPosition(
// drawing...
// ---------------------------------------------------------------------------
-void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) const {
+void Layer::draw(const sp<const DisplayDevice>& hw, const Region& clip) {
onDraw(hw, clip, false);
}
void Layer::draw(const sp<const DisplayDevice>& hw,
- bool useIdentityTransform) const {
+ bool useIdentityTransform) {
onDraw(hw, Region(hw->bounds()), useIdentityTransform);
}
-void Layer::draw(const sp<const DisplayDevice>& hw) const {
+void Layer::draw(const sp<const DisplayDevice>& hw) {
onDraw(hw, Region(hw->bounds()), false);
}
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
- bool useIdentityTransform) const
+ bool useIdentityTransform)
{
ATRACE_CALL();
@@ -1031,6 +1032,14 @@ bool Layer::setLayer(uint32_t z) {
setTransactionFlags(eTransactionNeeded);
return true;
}
+bool Layer::setBlur(uint8_t blur) {
+ if (mCurrentState.blur == blur)
+ return false;
+ mCurrentState.sequence++;
+ mCurrentState.blur = blur;
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
bool Layer::setSize(uint32_t w, uint32_t h) {
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
return false;
@@ -1479,13 +1488,13 @@ void Layer::dump(String8& result, Colorizer& colorizer) const
result.appendFormat( " "
"layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
"isOpaque=%1d, invalidate=%1d, "
- "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
+ "alpha=0x%02x, blur=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n"
" client=%p\n",
s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
s.active.crop.left, s.active.crop.top,
s.active.crop.right, s.active.crop.bottom,
isOpaque(s), contentDirty,
- s.alpha, s.flags,
+ s.alpha, s.blur, s.flags,
s.transform[0][0], s.transform[0][1],
s.transform[1][0], s.transform[1][1],
client.get());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c0c8bf5..e2cb791 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -57,6 +57,7 @@ class Colorizer;
class DisplayDevice;
class GraphicBuffer;
class SurfaceFlinger;
+class LayerBlur;
// ---------------------------------------------------------------------------
@@ -70,6 +71,8 @@ class SurfaceFlinger;
class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {
static int32_t sSequence;
+ friend class LayerBlur;
+
public:
#ifdef QTI_BSP
friend class ExLayer;
@@ -108,6 +111,7 @@ public:
Geometry requested;
uint32_t z;
uint32_t layerStack;
+ uint8_t blur;
uint8_t alpha;
uint8_t flags;
uint8_t reserved[2];
@@ -133,6 +137,10 @@ public:
// modify current state
bool setPosition(float x, float y);
bool setLayer(uint32_t z);
+ bool setBlur(uint8_t blur);
+ virtual bool setBlurMaskLayer(sp<Layer>& /*maskLayer*/) { return false; }
+ virtual bool setBlurMaskSampling(int32_t /*sampling*/) { return false; }
+ virtual bool setBlurMaskAlphaThreshold(float /*alpha*/) { return false; }
bool setSize(uint32_t w, uint32_t h);
bool setAlpha(uint8_t alpha);
bool setMatrix(const layer_state_t::matrix22_t& matrix);
@@ -195,12 +203,17 @@ public:
*/
virtual bool isFixedSize() const;
+ /*
+ * isBlurLayer - true if this is a LayerBlur instance
+ */
+ virtual bool isBlurLayer() const { return false; }
+
protected:
/*
* onDraw - draws the surface.
*/
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
- bool useIdentityTransform) const;
+ bool useIdentityTransform);
public:
// -----------------------------------------------------------------------
@@ -237,9 +250,9 @@ public:
* draw - performs some global clipping optimizations
* and calls onDraw().
*/
- void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
- void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform) const;
- void draw(const sp<const DisplayDevice>& hw) const;
+ void draw(const sp<const DisplayDevice>& hw, const Region& clip);
+ void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform);
+ void draw(const sp<const DisplayDevice>& hw);
/*
* doTransaction - process the transaction. This is a good place to figure
diff --git a/services/surfaceflinger/LayerBlur.cpp b/services/surfaceflinger/LayerBlur.cpp
new file mode 100644
index 0000000..5c9e8ac
--- /dev/null
+++ b/services/surfaceflinger/LayerBlur.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+//#define LOG_NDEBUG 0
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include <GLES/gl.h>
+#include <GLES2/gl2.h>
+
+#include "LayerBlur.h"
+#include "SurfaceFlinger.h"
+#include "DisplayDevice.h"
+#include "RenderEngine/RenderEngine.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+// Automatically disables scissor test and restores it when destroyed
+class ScopedScissorDisabler {
+ bool scissorEnabled;
+public:
+ ScopedScissorDisabler(bool enabled) : scissorEnabled(enabled) {
+ if(scissorEnabled) {
+ glDisable(GL_SCISSOR_TEST);
+ }
+ }
+ ~ScopedScissorDisabler() {
+ if(scissorEnabled) {
+ glEnable(GL_SCISSOR_TEST);
+ }
+ };
+};
+
+static void setupMeshPartial(Mesh& mesh, Rect rcDraw, Rect rcTexture, int texWidth, int texHeight, int viewportHeight) {
+ Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+ position[0] = vec2(rcDraw.left, rcDraw.top);
+ position[1] = vec2(rcDraw.left, rcDraw.bottom);
+ position[2] = vec2(rcDraw.right, rcDraw.bottom);
+ position[3] = vec2(rcDraw.right, rcDraw.top);
+ for(size_t i=0; i<4; ++i) {
+ position[i].y = viewportHeight - position[i].y;
+ }
+
+ Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+ texCoords[0] = vec2(rcTexture.left/(float)texWidth, 1.0f - rcTexture.top/(float)texHeight);
+ texCoords[1] = vec2(rcTexture.left/(float)texWidth, 1.0f - rcTexture.bottom/(float)texHeight);
+ texCoords[2] = vec2(rcTexture.right/(float)texWidth, 1.0f - rcTexture.bottom/(float)texHeight);
+ texCoords[3] = vec2(rcTexture.right/(float)texWidth, 1.0f - rcTexture.top/(float)texHeight);
+}
+
+static void setupMesh(Mesh& mesh, int width, int height, int viewportHeight) {
+ Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
+ position[0] = vec2(0, 0);
+ position[1] = vec2(0, height);
+ position[2] = vec2(width, height);
+ position[3] = vec2(width, 0);
+ for(size_t i=0; i<4; ++i) {
+ position[i].y = viewportHeight - position[i].y;
+ }
+
+ Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
+ texCoords[0] = vec2(0, 1.0f);
+ texCoords[1] = vec2(0, 0);
+ texCoords[2] = vec2(1.0f, 0);
+ texCoords[3] = vec2(1.0f, 1.0f);
+}
+
+
+LayerBlur::LayerBlur(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags)
+ : Layer(flinger, client, name, w, h, flags), mBlurMaskSampling(1), mBlurMaskAlphaThreshold(0.0f)
+ ,mLastFrameSequence(0)
+{
+#ifdef UI_BLUR
+ mBlurToken = qtiblur::initBlurToken();
+#endif
+
+ GLuint texnames[3];
+ mFlinger->getRenderEngine().genTextures(3, texnames);
+ mTextureCapture.init(Texture::TEXTURE_2D, texnames[0]);
+ mTextureBlur.init(Texture::TEXTURE_2D, texnames[1]);
+ mTextureMasking.init(Texture::TEXTURE_2D, texnames[2]);
+}
+
+LayerBlur::~LayerBlur() {
+#ifdef UI_BLUR
+ qtiblur::releaseBlurToken(mBlurToken);
+#endif
+
+ releaseFbo(mFboCapture);
+ releaseFbo(mFboMasking);
+ mFlinger->deleteTextureAsync(mTextureCapture.getTextureName());
+ mFlinger->deleteTextureAsync(mTextureBlur.getTextureName());
+ mFlinger->deleteTextureAsync(mTextureMasking.getTextureName());
+}
+
+void LayerBlur::onDraw(const sp<const DisplayDevice>& hw, const Region& /*clip*/,
+ bool useIdentityTransform)
+{
+ clock_t t1 = clock();
+ const ScopedTrace traceTotal(ATRACE_TAG, "Blur.onDraw");
+
+ const Layer::State& s(getDrawingState());
+
+ if (s.alpha==0) {
+ return;
+ }
+
+ /////
+ // NOTE:
+ //
+ // Scissor test has been turned on by SurfaceFlinger for NON-primary display
+ // We need to turn off the scissor test during our fbo drawing
+ GLboolean isScissorEnabled = false;
+ glGetBooleanv(GL_SCISSOR_TEST, &isScissorEnabled);
+ ScopedScissorDisabler _(isScissorEnabled);
+ //
+ /////
+
+
+ int hwWidth = hw->getWidth();
+ int hwHeight = hw->getHeight();
+
+ RenderEngine& engine(mFlinger->getRenderEngine());
+
+ bool savedProjectionYSwap = engine.getProjectionYSwap();
+ Rect savedProjectionSourceCrop = engine.getProjectionSourceCrop();
+ Transform::orientation_flags savedProjectionRotation = engine.getProjectionRotation();
+ size_t savedViewportWidth = engine.getViewportWidth();
+ size_t savedViewportHeight = engine.getViewportHeight();
+
+
+ if (mLastFrameSequence != mFlinger->mActiveFrameSequence ||
+ mTextureBlur.getWidth() == 0 || mTextureBlur.getHeight() == 0) {
+ // full drawing needed.
+
+
+ // capture
+ if (!captureScreen(hw, mFboCapture, mTextureCapture, hwWidth, hwHeight)) {
+ return;
+ }
+
+ // blur
+ size_t outTexWidth = mTextureBlur.getWidth();
+ size_t outTexHeight = mTextureBlur.getHeight();
+#ifdef UI_BLUR
+ if (!qtiblur::blur(mBlurToken,
+ s.blur,
+ mTextureCapture.getTextureName(),
+ mTextureCapture.getWidth(),
+ mTextureCapture.getHeight(),
+ mTextureBlur.getTextureName(),
+ &outTexWidth,
+ &outTexHeight)) {
+ return;
+ }
+#endif
+
+ // mTextureBlur now has "Blurred image"
+ mTextureBlur.setDimensions(outTexWidth, outTexHeight);
+
+ } else {
+ // We can just re-use mTextureBlur.
+ // SurfaceFlinger or other LayerBlur object called my draw() multiple times
+ // while making one frame.
+ //
+ // Fall through
+ }
+
+ // masking
+ bool masking = false;
+ sp<Layer> maskLayer = mBlurMaskLayer.promote();
+ if (maskLayer != 0) {
+ // The larger sampling, the faster drawing.
+ // The smaller sampling, the prettier out line.
+ int sampling = mBlurMaskSampling >= 1 ? mBlurMaskSampling : 1;
+ //ALOGV("maskLayer available, sampling:%d", sampling);
+ masking = drawMaskLayer(maskLayer, hw, mFboMasking, hwWidth, hwHeight, sampling, mTextureMasking);
+ }
+
+
+ // final draw
+ doDrawFinal(hw,
+ savedViewportWidth, savedViewportHeight,
+ savedProjectionSourceCrop,
+ savedProjectionYSwap,
+ savedProjectionRotation,
+ useIdentityTransform,
+ masking ? &mTextureMasking : 0
+ );
+
+ mLastFrameSequence = mFlinger->mActiveFrameSequence;
+
+ clock_t t2 = clock();
+ ALOGV("onDraw took %d ms", (int)(1000*(t2-t1)/CLOCKS_PER_SEC));
+}
+
+
+bool LayerBlur::captureScreen(const sp<const DisplayDevice>& hw, FBO& fbo, Texture& texture, int width, int height) {
+ ATRACE_CALL();
+ ensureFbo(fbo, width, height, texture.getTextureName());
+ if(fbo.fbo == 0) {
+ ALOGE("captureScreen(). fbo.fbo == 0");
+ return false;
+ }
+
+ GLint savedFramebuffer = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)fbo.fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ texture.getTextureTarget(),
+ texture.getTextureName(), 0);
+
+ mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 1.0f);
+ mFlinger->renderScreenImplLocked(
+ hw,
+ Rect(0,0,width,height),
+ width, height,
+ 0, getDrawingState().z-1,
+ false,
+ false,
+ Transform::ROT_0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer);
+
+ texture.setDimensions(width, height);
+
+ return true;
+}
+
+bool LayerBlur::drawMaskLayer(sp<Layer>& maskLayer, const sp<const DisplayDevice>& hw,
+ FBO& fbo, int width, int height, int sampling, Texture& texture) {
+ // Draw maskLayer into fbo
+ ATRACE_CALL();
+
+ int maskWidth = width/sampling;
+ int maskHeight = height/sampling;
+
+ ensureFbo(fbo, maskWidth, maskHeight, texture.getTextureName());
+ if(fbo.fbo == 0) {
+ ALOGE("drawMaskLayer(). fbo.fbo == 0");
+ return false;
+ }
+
+ GLint savedFramebuffer = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)fbo.fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ texture.getTextureTarget(),
+ texture.getTextureName(), 0);
+
+ mFlinger->getRenderEngine().setViewportAndProjection(
+ maskWidth, maskHeight,
+ Rect(0,0,width,height),
+ height,
+ false,
+ Transform::ROT_0
+ );
+ setupMesh(mMesh, width, height, height);
+ mFlinger->getRenderEngine().clearWithColor(0.0f, 0.0f, 0.0f, 0.0f); // alpha must be ZERO
+ maskLayer->draw(hw);
+ glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer);
+
+ texture.setDimensions(maskWidth, maskHeight);
+
+ return true;
+}
+
+/*
+ * draw final texture into outer framebuffer
+ */
+void LayerBlur::doDrawFinal(const sp<const DisplayDevice>& hw,
+ int savedViewportWidth, int savedViewportHeight,
+ Rect savedProjectionSourceCrop,
+ bool savedProjectionYSwap,
+ Transform::orientation_flags savedRotation,
+ bool useIdentityTransform,
+ Texture* maskTexture
+ ) {
+ ATRACE_CALL();
+
+ int hwWidth = hw->getWidth();
+ int hwHeight = hw->getHeight();
+
+ RenderEngine& engine(mFlinger->getRenderEngine());
+ const Layer::State& s(getDrawingState());
+
+ Transform trToDraw(useIdentityTransform ? hw->getTransform() : hw->getTransform() * s.transform);
+ Transform trToMapTexture(hw->getTransform() * s.transform);
+
+ Rect frameToDraw(trToDraw.transform(Rect(s.active.w, s.active.h)));
+ Rect frameToMapTexture(trToMapTexture.transform(Rect(s.active.w, s.active.h)));
+
+ engine.setViewportAndProjection(
+ savedViewportWidth, savedViewportHeight,
+ savedProjectionSourceCrop,
+ hwHeight,
+ savedProjectionYSwap,
+ savedRotation
+ );
+
+
+ const mat4 identity;
+ float textureMatrix[16];
+ memcpy(textureMatrix, identity.asArray(), sizeof(textureMatrix));
+
+ //mTextureBlur.setDimensions(hwWidth, hwHeight);
+ mTextureBlur.setFiltering(true);
+ mTextureBlur.setMatrix(textureMatrix);
+
+ if (maskTexture != 0) {
+ maskTexture->setFiltering(false);
+ maskTexture->setMatrix(textureMatrix);
+ }
+
+ setupMeshPartial(mMesh, frameToDraw, frameToMapTexture, hwWidth, hwHeight,
+ savedProjectionSourceCrop.height());
+
+ engine.setupLayerTexturing(mTextureBlur);
+ engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
+ if (maskTexture) {
+ engine.setupLayerMasking(*maskTexture, mBlurMaskAlphaThreshold);
+ }
+ engine.drawMesh(mMesh);
+ engine.disableLayerMasking();
+ engine.disableBlending();
+ engine.disableTexturing();
+
+}
+
+bool LayerBlur::isVisible() const {
+ const Layer::State& s(getDrawingState());
+ return !(s.flags & layer_state_t::eLayerHidden) && s.alpha;
+}
+
+bool LayerBlur::setBlurMaskLayer(sp<Layer>& maskLayer) {
+ if (maskLayer == mBlurMaskLayer) {
+ return false;
+ }
+ mBlurMaskLayer = maskLayer;
+ return true;
+}
+
+
+void LayerBlur::initFbo(FBO& fbobj, int width, int height, int textureName) {
+ GLuint fbo=0;
+
+ glGenFramebuffers(1, &fbo);
+ glBindTexture(GL_TEXTURE_2D, textureName);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ GLint savedFramebuffer = 0;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &savedFramebuffer);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, textureName, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, savedFramebuffer);
+
+ fbobj.fbo = fbo;
+ fbobj.width = width;
+ fbobj.height = height;
+}
+
+void LayerBlur::releaseFbo(FBO& fbo) {
+ if(fbo.fbo != 0) {
+ glDeleteFramebuffers(1, (GLuint*)&fbo.fbo);
+ }
+ fbo.fbo = 0;
+ fbo.width = 0;
+ fbo.height = 0;
+}
+
+void LayerBlur::ensureFbo(FBO& fbo, int width, int height, int textureName) {
+ if(fbo.fbo != 0) {
+ if(fbo.width != width || fbo.height != height) {
+ releaseFbo(fbo);
+ }
+ }
+ if(fbo.fbo == 0) {
+ initFbo(fbo, width, height, textureName);
+ }
+}
+
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
diff --git a/services/surfaceflinger/LayerBlur.h b/services/surfaceflinger/LayerBlur.h
new file mode 100644
index 0000000..251423e
--- /dev/null
+++ b/services/surfaceflinger/LayerBlur.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Not a Contribution.
+ *
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_LAYER_BLUR_H
+#define ANDROID_LAYER_BLUR_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "Layer.h"
+
+#ifdef UI_BLUR
+#include "Blur.h" // libuiblur.so
+#endif
+
+// ---------------------------------------------------------------------------
+
+namespace android {
+
+/**
+ * Blur layer object.
+ * Actual blurring logics are capsulated in libuiblur.so
+ */
+class LayerBlur : public Layer
+{
+public:
+ LayerBlur(SurfaceFlinger* flinger, const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags);
+ virtual ~LayerBlur();
+
+ virtual const char* getTypeId() const { return "LayerBlur"; }
+ virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
+ bool useIdentityTransform);
+ virtual bool isOpaque(const Layer::State& /*s*/) const { return false; }
+ virtual bool isSecure() const { return false; }
+ virtual bool isFixedSize() const { return true; }
+ virtual bool isVisible() const;
+
+ virtual bool isBlurLayer() const { return true; }
+ virtual bool setBlurMaskLayer(sp<Layer>& maskLayer);
+ virtual bool setBlurMaskSampling(int32_t sampling) { mBlurMaskSampling = sampling; return true; }
+ virtual bool setBlurMaskAlphaThreshold(float alpha) { mBlurMaskAlphaThreshold = alpha; return true; }
+
+private:
+#ifdef UI_BLUR
+ qtiblur::BLUR_TOKEN mBlurToken;
+#endif
+ wp<Layer> mBlurMaskLayer;
+ int32_t mBlurMaskSampling;
+ float mBlurMaskAlphaThreshold;
+ uint32_t mLastFrameSequence;
+
+ class FBO {
+ public:
+ FBO() : fbo(0), width(0), height(0) {}
+ int fbo;
+ int width;
+ int height;
+ };
+
+ void initFbo(FBO& fbo, int width, int height, int textureName);
+ void releaseFbo(FBO& fbo);
+ void ensureFbo(FBO& fbo, int width, int height, int textureName);
+
+
+ FBO mFboCapture;
+ Texture mTextureCapture;
+
+ Texture mTextureBlur;
+
+ FBO mFboMasking;
+ Texture mTextureMasking;
+
+ bool captureScreen(const sp<const DisplayDevice>& hw,
+ FBO& fbo, Texture& texture, int width, int height);
+ void doDrawFinal(const sp<const DisplayDevice>& hw,
+ int savedViewportWidth, int savedViewportHeight,
+ Rect savedProjectionSourceCrop, bool savedProjectionYSwap,
+ Transform::orientation_flags savedRotation, bool useIdentityTransform,
+ Texture* maskTexture);
+ bool drawMaskLayer(sp<Layer>& maskLayer, const sp<const DisplayDevice>& hw,
+ FBO& fbo, int width, int height, int sampling, Texture& texture);
+
+};
+
+// ---------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_LAYER_BLUR_H
diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp
index b8d549a..5afd291 100644
--- a/services/surfaceflinger/LayerDim.cpp
+++ b/services/surfaceflinger/LayerDim.cpp
@@ -40,7 +40,7 @@ LayerDim::~LayerDim() {
}
void LayerDim::onDraw(const sp<const DisplayDevice>& hw,
- const Region& /* clip */, bool useIdentityTransform) const
+ const Region& /* clip */, bool useIdentityTransform)
{
const State& s(getDrawingState());
if (s.alpha>0) {
diff --git a/services/surfaceflinger/LayerDim.h b/services/surfaceflinger/LayerDim.h
index b66591b..01f71cc 100644
--- a/services/surfaceflinger/LayerDim.h
+++ b/services/surfaceflinger/LayerDim.h
@@ -35,7 +35,7 @@ public:
virtual const char* getTypeId() const { return "LayerDim"; }
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
- bool useIdentityTransform) const;
+ bool useIdentityTransform);
virtual bool isOpaque(const Layer::State&) const { return false; }
virtual bool isSecure() const { return false; }
virtual bool isFixedSize() const { return true; }
diff --git a/services/surfaceflinger/RenderEngine/Description.cpp b/services/surfaceflinger/RenderEngine/Description.cpp
index 0dab872..14607ca 100644
--- a/services/surfaceflinger/RenderEngine/Description.cpp
+++ b/services/surfaceflinger/RenderEngine/Description.cpp
@@ -33,6 +33,8 @@ Description::Description() :
mOpaque = true;
mTextureEnabled = false;
mColorMatrixEnabled = false;
+ mMaskTextureEnabled = false;
+ mMaskAlphaThreshold = 0.0f;
memset(mColor, 0, sizeof(mColor));
}
@@ -92,5 +94,14 @@ const mat4& Description::getColorMatrix() const {
return mColorMatrix;
}
+void Description::setMasking(const Texture& maskTexture, float alphaThreshold) {
+ mMaskTexture = maskTexture;
+ mMaskTextureEnabled = true;
+ mMaskAlphaThreshold = alphaThreshold;
+}
+
+void Description::disableMasking() {
+ mMaskTextureEnabled = false;
+}
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Description.h b/services/surfaceflinger/RenderEngine/Description.h
index 8a3447c..2bfb632 100644
--- a/services/surfaceflinger/RenderEngine/Description.h
+++ b/services/surfaceflinger/RenderEngine/Description.h
@@ -53,6 +53,9 @@ class Description {
bool mColorMatrixEnabled;
mat4 mColorMatrix;
+ Texture mMaskTexture;
+ bool mMaskTextureEnabled;
+ GLclampf mMaskAlphaThreshold;
public:
Description();
@@ -67,6 +70,8 @@ public:
void setProjectionMatrix(const mat4& mtx);
void setColorMatrix(const mat4& mtx);
const mat4& getColorMatrix() const;
+ void setMasking(const Texture& maskTexture, float alphaThreshold);
+ void disableMasking();
private:
bool mUniformsDirty;
diff --git a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
index 77824ce..cb13ee0 100644
--- a/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES11RenderEngine.h
@@ -60,6 +60,8 @@ protected:
virtual void setupFillWithColor(float r, float g, float b, float a) ;
virtual void disableTexturing();
virtual void disableBlending();
+ virtual void setupLayerMasking(const Texture& /*maskTexture*/, float /*alphaThreshold*/) {}
+ virtual void disableLayerMasking() {}
virtual void drawMesh(const Mesh& mesh);
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index a35aa78..6333a41 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -40,7 +40,7 @@ namespace android {
// ---------------------------------------------------------------------------
GLES20RenderEngine::GLES20RenderEngine() :
- mVpWidth(0), mVpHeight(0) {
+ mVpWidth(0), mVpHeight(0), mProjectionRotation(Transform::ROT_0) {
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@@ -115,6 +115,9 @@ void GLES20RenderEngine::setViewportAndProjection(
mState.setProjectionMatrix(m);
mVpWidth = vpw;
mVpHeight = vph;
+ mProjectionSourceCrop = sourceCrop;
+ mProjectionYSwap = yswap;
+ mProjectionRotation = rotation;
}
void GLES20RenderEngine::setupLayerBlending(
@@ -264,6 +267,30 @@ void GLES20RenderEngine::dump(String8& result) {
RenderEngine::dump(result);
}
+void GLES20RenderEngine::setupLayerMasking(const Texture& maskTexture, float alphaThreshold) {
+ glActiveTexture(GL_TEXTURE0 + 1);
+ GLuint target = maskTexture.getTextureTarget();
+ glBindTexture(target, maskTexture.getTextureName());
+ GLenum filter = GL_NEAREST;
+ if (maskTexture.getFiltering()) {
+ filter = GL_LINEAR;
+ }
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
+
+ if (alphaThreshold < 0) alphaThreshold = 0;
+ if (alphaThreshold > 1.0f) alphaThreshold = 1.0f;
+
+ mState.setMasking(maskTexture, alphaThreshold);
+ glActiveTexture(GL_TEXTURE0);
+}
+
+void GLES20RenderEngine::disableLayerMasking() {
+ mState.disableMasking();
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
index 6074a3d..414a999 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.h
@@ -42,6 +42,9 @@ class GLES20RenderEngine : public RenderEngine {
GLint mMaxTextureSize;
GLuint mVpWidth;
GLuint mVpHeight;
+ Rect mProjectionSourceCrop;
+ bool mProjectionYSwap;
+ Transform::orientation_flags mProjectionRotation;
struct Group {
GLuint texture;
@@ -76,11 +79,18 @@ protected:
virtual mat4 setupColorTransform(const mat4& colorTransform);
virtual void disableTexturing();
virtual void disableBlending();
+ virtual void setupLayerMasking(const Texture& maskTexture, float alphaThreshold);
+ virtual void disableLayerMasking();
virtual void drawMesh(const Mesh& mesh);
virtual size_t getMaxTextureSize() const;
virtual size_t getMaxViewportDims() const;
+ virtual bool getProjectionYSwap() { return mProjectionYSwap; }
+ virtual size_t getViewportWidth() const { return mVpWidth; }
+ virtual size_t getViewportHeight() const { return mVpHeight; }
+ virtual Rect getProjectionSourceCrop() const { return mProjectionSourceCrop; }
+ virtual Transform::orientation_flags getProjectionRotation() const { return mProjectionRotation; }
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/Program.cpp b/services/surfaceflinger/RenderEngine/Program.cpp
index 0424e0c..936cb1b 100644
--- a/services/surfaceflinger/RenderEngine/Program.cpp
+++ b/services/surfaceflinger/RenderEngine/Program.cpp
@@ -64,6 +64,8 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c
mSamplerLoc = glGetUniformLocation(programId, "sampler");
mColorLoc = glGetUniformLocation(programId, "color");
mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane");
+ mSamplerMaskLoc = glGetUniformLocation(programId, "samplerMask");
+ mMaskAlphaThresholdLoc = glGetUniformLocation(programId, "maskAlphaThreshold");
// set-up the default values for our uniforms
glUseProgram(programId);
@@ -143,6 +145,12 @@ void Program::setUniforms(const Description& desc) {
}
// these uniforms are always present
glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
+ if (mSamplerMaskLoc >= 0) {
+ glUniform1i(mSamplerMaskLoc, 1);
+ }
+ if (mMaskAlphaThresholdLoc >= 0) {
+ glUniform1f(mMaskAlphaThresholdLoc, desc.mMaskAlphaThreshold);
+ }
}
} /* namespace android */
diff --git a/services/surfaceflinger/RenderEngine/Program.h b/services/surfaceflinger/RenderEngine/Program.h
index 36bd120..08dee59 100644
--- a/services/surfaceflinger/RenderEngine/Program.h
+++ b/services/surfaceflinger/RenderEngine/Program.h
@@ -84,6 +84,9 @@ private:
/* location of the color uniform */
GLint mColorLoc;
+
+ GLint mSamplerMaskLoc;
+ GLint mMaskAlphaThresholdLoc;
};
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index ba11259..33ff7d0 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
@@ -110,9 +112,27 @@ void ProgramCache::primeCache() {
shaderCount++;
}
}
+
+ // Keys that are actually used by blurring.
+ // This is obtained by log msg from useProgram()
+ uint32_t blurringKeys[] = {
+ 0x01000015,
+ 0x01000011,
+ };
+ for (size_t i=0; i<sizeof(blurringKeys)/sizeof(blurringKeys[0]); ++i) {
+ Key shaderKey;
+ shaderKey.set(blurringKeys[i], blurringKeys[i]);
+ Program* program = mCache.valueFor(shaderKey);
+ if (program == NULL) {
+ program = generateProgram(shaderKey);
+ mCache.add(shaderKey, program);
+ shaderCount++;
+ }
+ }
+
nsecs_t timeAfter = systemTime();
float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
- ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs);
+ ALOGD("SF. shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs);
}
ProgramCache::Key ProgramCache::computeKey(const Description& description) {
@@ -129,15 +149,20 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) {
.set(Key::OPACITY_MASK,
description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
.set(Key::COLOR_MATRIX_MASK,
- description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF);
+ description.mColorMatrixEnabled ? Key::COLOR_MATRIX_ON : Key::COLOR_MATRIX_OFF)
+ .set(Key::TEXTURE_MASKING_MASK,
+ !description.mMaskTextureEnabled ? Key::TEXTURE_MASKING_OFF :
+ description.mMaskTexture.getTextureTarget() == GL_TEXTURE_EXTERNAL_OES ? Key::TEXTURE_MASKING_EXT :
+ description.mMaskTexture.getTextureTarget() == GL_TEXTURE_2D ? Key::TEXTURE_MASKING_2D :
+ Key::TEXTURE_MASKING_OFF);
return needs;
}
String8 ProgramCache::generateVertexShader(const Key& needs) {
Formatter vs;
if (needs.isTexturing()) {
- vs << "attribute vec4 texCoords;"
- << "varying vec2 outTexCoords;";
+ vs << "attribute vec4 texCoords;"
+ << "varying vec2 outTexCoords;";
}
vs << "attribute vec4 position;"
<< "uniform mat4 projection;"
@@ -145,7 +170,7 @@ String8 ProgramCache::generateVertexShader(const Key& needs) {
<< "void main(void) {" << indent
<< "gl_Position = projection * position;";
if (needs.isTexturing()) {
- vs << "outTexCoords = (texture * texCoords).st;";
+ vs << "outTexCoords = (texture * texCoords).st;";
}
vs << dedent << "}";
return vs.getString();
@@ -169,6 +194,14 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) {
} else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
fs << "uniform vec4 color;";
}
+ if (needs.getTextureMaskingTarget() == Key::TEXTURE_MASKING_EXT) {
+ fs << "uniform samplerExternalOES samplerMask;";
+ } else if (needs.getTextureMaskingTarget() == Key::TEXTURE_MASKING_2D) {
+ fs << "uniform sampler2D samplerMask;";
+ }
+ if (needs.getTextureMaskingTarget() != Key::TEXTURE_MASKING_OFF) {
+ fs << "uniform float maskAlphaThreshold;";
+ }
if (needs.hasPlaneAlpha()) {
fs << "uniform float alphaPlane;";
}
@@ -177,7 +210,12 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) {
}
fs << "void main(void) {" << indent;
if (needs.isTexturing()) {
- fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
+ if (needs.getTextureMaskingTarget() != Key::TEXTURE_MASKING_OFF) {
+ fs << "if (texture2D(samplerMask, outTexCoords).a <= maskAlphaThreshold) discard;"
+ << "gl_FragColor = texture2D(sampler, outTexCoords);";
+ } else {
+ fs << "gl_FragColor = texture2D(sampler, outTexCoords);";
+ }
} else {
fs << "gl_FragColor = color;";
}
@@ -235,9 +273,6 @@ void ProgramCache::useProgram(const Description& description) {
program = generateProgram(needs);
mCache.add(needs, program);
time += systemTime();
-
- //ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
- // needs.mNeeds, uint32_t(ns2ms(time)), mCache.size());
}
// here we have a suitable program for this description
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 1fa53d3..3824e73 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -69,6 +69,11 @@ public:
COLOR_MATRIX_OFF = 0x00000000,
COLOR_MATRIX_ON = 0x00000020,
COLOR_MATRIX_MASK = 0x00000020,
+
+ TEXTURE_MASKING_OFF = 0x00000000,
+ TEXTURE_MASKING_EXT = 0x00800000,
+ TEXTURE_MASKING_2D = 0x01000000,
+ TEXTURE_MASKING_MASK = 0x01800000,
};
inline Key() : mKey(0) { }
@@ -97,6 +102,12 @@ public:
inline bool hasColorMatrix() const {
return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
}
+ inline bool isTextureMasking() const {
+ return (mKey & TEXTURE_MASKING_MASK) != TEXTURE_MASKING_OFF;
+ }
+ inline int getTextureMaskingTarget() const {
+ return (mKey & TEXTURE_MASKING_MASK);
+ }
// this is the definition of a friend function -- not a method of class Needs
friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index c9a043a..a669fdd 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -110,6 +110,8 @@ public:
virtual void disableTexturing() = 0;
virtual void disableBlending() = 0;
+ virtual void setupLayerMasking(const Texture& maskTexture, float alphaThreshold) = 0;
+ virtual void disableLayerMasking() = 0;
// drawing
virtual void drawMesh(const Mesh& mesh) = 0;
@@ -117,6 +119,11 @@ public:
// queries
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
+ virtual bool getProjectionYSwap() { return 0; }
+ virtual size_t getViewportWidth() const { return 1; }
+ virtual size_t getViewportHeight() const { return 1; }
+ virtual Rect getProjectionSourceCrop() const { return Rect(0, 0, 1, 1); }
+ virtual Transform::orientation_flags getProjectionRotation() const { return Transform::ROT_0; }
EGLConfig getEGLConfig() const;
EGLContext getEGLContext() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index fc99fa0..cea463a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include <stdint.h>
@@ -68,6 +69,7 @@
#include "EventThread.h"
#include "Layer.h"
#include "LayerDim.h"
+#include "LayerBlur.h"
#include "SurfaceFlinger.h"
#include "DisplayHardware/FramebufferSurface.h"
@@ -157,7 +159,8 @@ SurfaceFlinger::SurfaceFlinger()
mHasPoweredOff(false),
mFrameBuckets(),
mTotalTime(0),
- mLastSwapTime(0)
+ mLastSwapTime(0),
+ mActiveFrameSequence(0)
{
ALOGI("SurfaceFlinger is starting");
@@ -1249,6 +1252,8 @@ void SurfaceFlinger::doComposition() {
// repaint the framebuffer (if needed)
doDisplayComposition(hw, dirtyRegion);
+ ++mActiveFrameSequence;
+
hw->dirtyRegion.clear();
hw->flip(hw->swapRegion);
hw->swapRegion.clear();
@@ -1309,6 +1314,7 @@ void SurfaceFlinger::postFramebuffer()
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
logFrameStats();
}
+ ALOGV_IF(mFrameRateHelper.update(), "FPS: %d", mFrameRateHelper.get());
}
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
@@ -2277,6 +2283,41 @@ uint32_t SurfaceFlinger::setClientStateLocked(
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
+ if (what & layer_state_t::eBlurChanged) {
+ ALOGV("eBlurChanged");
+ if (layer->setBlur(uint8_t(255.0f*s.blur+0.5f))) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eBlurMaskSurfaceChanged) {
+ ALOGV("eBlurMaskSurfaceChanged");
+ sp<Layer> maskLayer = 0;
+ if (s.blurMaskSurface != 0) {
+ maskLayer = client->getLayerUser(s.blurMaskSurface);
+ }
+ if (maskLayer == 0) {
+ ALOGV("eBlurMaskSurfaceChanged. maskLayer == 0");
+ } else {
+ ALOGV("eBlurMaskSurfaceChagned. maskLayer.z == %d", maskLayer->getCurrentState().z);
+ if (maskLayer->isBlurLayer()) {
+ ALOGE("Blur layer can not be used as blur mask surface");
+ maskLayer = 0;
+ }
+ }
+ if (layer->setBlurMaskLayer(maskLayer)) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eBlurMaskSamplingChanged) {
+ if (layer->setBlurMaskSampling(s.blurMaskSampling)) {
+ flags |= eTraversalNeeded;
+ }
+ }
+ if (what & layer_state_t::eBlurMaskAlphaThresholdChanged) {
+ if (layer->setBlurMaskAlphaThreshold(s.blurMaskAlphaThreshold)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eSizeChanged) {
if (layer->setSize(s.w, s.h)) {
flags |= eTraversalNeeded;
@@ -2345,6 +2386,11 @@ status_t SurfaceFlinger::createLayer(
name, w, h, flags,
handle, gbp, &layer);
break;
+ case ISurfaceComposerClient::eFXSurfaceBlur:
+ result = createBlurLayer(client,
+ name, w, h, flags,
+ handle, gbp, &layer);
+ break;
default:
result = BAD_VALUE;
break;
@@ -2399,6 +2445,16 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
return NO_ERROR;
}
+status_t SurfaceFlinger::createBlurLayer(const sp<Client>& client,
+ const String8& name, uint32_t w, uint32_t h, uint32_t flags,
+ sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, sp<Layer>* outLayer)
+{
+ *outLayer = new LayerBlur(this, client, name, w, h, flags);
+ *handle = (*outLayer)->getHandle();
+ *gbp = (*outLayer)->getProducer();
+ return NO_ERROR;
+}
+
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
{
// called by the window manager when it wants to remove a Layer
@@ -3407,6 +3463,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
return BAD_VALUE;
}
+ ++mActiveFrameSequence;
+
reqWidth = (!reqWidth) ? hw_w : reqWidth;
reqHeight = (!reqHeight) ? hw_h : reqHeight;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4bbb1f4..2028d67 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -56,6 +56,8 @@
#include "DisplayHardware/HWComposer.h"
#include "Effects/Daltonizer.h"
+#include "FrameRateHelper.h"
+
namespace android {
// ---------------------------------------------------------------------------
@@ -66,6 +68,7 @@ class EventThread;
class IGraphicBufferAlloc;
class Layer;
class LayerDim;
+class LayerBlur;
class Surface;
class RenderEngine;
class EventControlThread;
@@ -144,6 +147,7 @@ private:
friend class Layer;
friend class LayerDim;
friend class MonitoredProducer;
+ friend class LayerBlur;
// This value is specified in number of frames. Log frame stats at most
// every half hour.
@@ -337,6 +341,10 @@ private:
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
+ status_t createBlurLayer(const sp<Client>& client, const String8& name,
+ uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
+ sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
+
// called in response to the window-manager calling
// ISurfaceComposerClient::destroySurface()
status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
@@ -550,6 +558,17 @@ private:
nsecs_t mFrameBuckets[NUM_BUCKETS];
nsecs_t mTotalTime;
nsecs_t mLastSwapTime;
+
+ FrameRateHelper mFrameRateHelper;
+
+ /*
+ * A number that increases on every new frame composition and screen capture.
+ * LayerBlur can speed up it's drawing by caching texture using this variable
+ * if multiple LayerBlur objects draw in one frame composition.
+ * In case of display mirroring, this variable should be increased on every display.
+ */
+ uint32_t mActiveFrameSequence;
+
};
}; // namespace android