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
This commit is contained in:
parent
b53d92c3eb
commit
987034b563
@ -50,6 +50,7 @@ public:
|
|||||||
eCursorWindow = 0x00002000,
|
eCursorWindow = 0x00002000,
|
||||||
|
|
||||||
eFXSurfaceNormal = 0x00000000,
|
eFXSurfaceNormal = 0x00000000,
|
||||||
|
eFXSurfaceBlur = 0x00010000,
|
||||||
eFXSurfaceDim = 0x00020000,
|
eFXSurfaceDim = 0x00020000,
|
||||||
eFXSurfaceMask = 0x000F0000,
|
eFXSurfaceMask = 0x000F0000,
|
||||||
};
|
};
|
||||||
|
@ -163,6 +163,11 @@ public:
|
|||||||
const Rect& layerStackRect,
|
const Rect& layerStackRect,
|
||||||
const Rect& displayRect);
|
const Rect& displayRect);
|
||||||
|
|
||||||
|
status_t setBlur(const sp<IBinder>& id, float blur);
|
||||||
|
status_t setBlurMaskSurface(const sp<IBinder>& id, const sp<IBinder>& maskSurfaceId);
|
||||||
|
status_t setBlurMaskSampling(const sp<IBinder>& id, uint32_t blurMaskSampling);
|
||||||
|
status_t setBlurMaskAlphaThreshold(const sp<IBinder>& id, float alpha);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void onFirstRef();
|
virtual void onFirstRef();
|
||||||
Composer& getComposer();
|
Composer& getComposer();
|
||||||
|
@ -77,6 +77,11 @@ public:
|
|||||||
status_t clearLayerFrameStats() const;
|
status_t clearLayerFrameStats() const;
|
||||||
status_t getLayerFrameStats(FrameStats* outStats) const;
|
status_t getLayerFrameStats(FrameStats* outStats) const;
|
||||||
|
|
||||||
|
status_t setBlur(float blur = 0);
|
||||||
|
status_t setBlurMaskSurface(const sp<SurfaceControl>& maskSurface);
|
||||||
|
status_t setBlurMaskSampling(uint32_t blurMaskSampling);
|
||||||
|
status_t setBlurMaskAlphaThreshold(float alpha);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// can't be copied
|
// can't be copied
|
||||||
SurfaceControl& operator = (SurfaceControl& rhs);
|
SurfaceControl& operator = (SurfaceControl& rhs);
|
||||||
|
@ -52,12 +52,16 @@ struct layer_state_t {
|
|||||||
eFlagsChanged = 0x00000040,
|
eFlagsChanged = 0x00000040,
|
||||||
eLayerStackChanged = 0x00000080,
|
eLayerStackChanged = 0x00000080,
|
||||||
eCropChanged = 0x00000100,
|
eCropChanged = 0x00000100,
|
||||||
|
eBlurChanged = 0x00400000,
|
||||||
|
eBlurMaskSurfaceChanged = 0x00800000,
|
||||||
|
eBlurMaskSamplingChanged = 0x01000000,
|
||||||
|
eBlurMaskAlphaThresholdChanged = 0x02000000,
|
||||||
};
|
};
|
||||||
|
|
||||||
layer_state_t()
|
layer_state_t()
|
||||||
: what(0),
|
: what(0),
|
||||||
x(0), y(0), z(0), w(0), h(0), layerStack(0),
|
x(0), y(0), z(0), w(0), h(0), layerStack(0), blur(0),
|
||||||
alpha(0), flags(0), mask(0),
|
blurMaskSampling(0), blurMaskAlphaThreshold(0), alpha(0), flags(0), mask(0),
|
||||||
reserved(0)
|
reserved(0)
|
||||||
{
|
{
|
||||||
matrix.dsdx = matrix.dtdy = 1.0f;
|
matrix.dsdx = matrix.dtdy = 1.0f;
|
||||||
@ -82,6 +86,10 @@ struct layer_state_t {
|
|||||||
uint32_t w;
|
uint32_t w;
|
||||||
uint32_t h;
|
uint32_t h;
|
||||||
uint32_t layerStack;
|
uint32_t layerStack;
|
||||||
|
float blur;
|
||||||
|
sp<IBinder> blurMaskSurface;
|
||||||
|
uint32_t blurMaskSampling;
|
||||||
|
float blurMaskAlphaThreshold;
|
||||||
float alpha;
|
float alpha;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
|
@ -32,6 +32,10 @@ status_t layer_state_t::write(Parcel& output) const
|
|||||||
output.writeUint32(w);
|
output.writeUint32(w);
|
||||||
output.writeUint32(h);
|
output.writeUint32(h);
|
||||||
output.writeUint32(layerStack);
|
output.writeUint32(layerStack);
|
||||||
|
output.writeFloat(blur);
|
||||||
|
output.writeStrongBinder(blurMaskSurface);
|
||||||
|
output.writeUint32(blurMaskSampling);
|
||||||
|
output.writeFloat(blurMaskAlphaThreshold);
|
||||||
output.writeFloat(alpha);
|
output.writeFloat(alpha);
|
||||||
output.writeUint32(flags);
|
output.writeUint32(flags);
|
||||||
output.writeUint32(mask);
|
output.writeUint32(mask);
|
||||||
@ -52,6 +56,10 @@ status_t layer_state_t::read(const Parcel& input)
|
|||||||
w = input.readUint32();
|
w = input.readUint32();
|
||||||
h = input.readUint32();
|
h = input.readUint32();
|
||||||
layerStack = input.readUint32();
|
layerStack = input.readUint32();
|
||||||
|
blur = input.readFloat();
|
||||||
|
blurMaskSurface = input.readStrongBinder();
|
||||||
|
blurMaskSampling = input.readUint32();
|
||||||
|
blurMaskAlphaThreshold = input.readFloat();
|
||||||
alpha = input.readFloat();
|
alpha = input.readFloat();
|
||||||
flags = static_cast<uint8_t>(input.readUint32());
|
flags = static_cast<uint8_t>(input.readUint32());
|
||||||
mask = static_cast<uint8_t>(input.readUint32());
|
mask = static_cast<uint8_t>(input.readUint32());
|
||||||
|
@ -144,6 +144,14 @@ public:
|
|||||||
uint32_t w, uint32_t h);
|
uint32_t w, uint32_t h);
|
||||||
status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
||||||
uint32_t z);
|
uint32_t z);
|
||||||
|
status_t setBlur(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
||||||
|
float blur);
|
||||||
|
status_t setBlurMaskSurface(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
||||||
|
const sp<IBinder>& maskSurfaceId);
|
||||||
|
status_t setBlurMaskSampling(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
||||||
|
uint32_t blurMaskSampling);
|
||||||
|
status_t setBlurMaskAlphaThreshold(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
||||||
|
float alpha);
|
||||||
status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id,
|
||||||
uint32_t flags, uint32_t mask);
|
uint32_t flags, uint32_t mask);
|
||||||
status_t setTransparentRegionHint(
|
status_t setTransparentRegionHint(
|
||||||
@ -303,6 +311,50 @@ status_t Composer::setLayer(const sp<SurfaceComposerClient>& client,
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t Composer::setBlur(const sp<SurfaceComposerClient>& client,
|
||||||
|
const sp<IBinder>& id, float blur) {
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
layer_state_t* s = getLayerStateLocked(client, id);
|
||||||
|
if (!s)
|
||||||
|
return BAD_INDEX;
|
||||||
|
s->what |= layer_state_t::eBlurChanged;
|
||||||
|
s->blur = blur;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Composer::setBlurMaskSurface(const sp<SurfaceComposerClient>& client,
|
||||||
|
const sp<IBinder>& id, const sp<IBinder>& maskSurfaceId) {
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
layer_state_t* s = getLayerStateLocked(client, id);
|
||||||
|
if (!s)
|
||||||
|
return BAD_INDEX;
|
||||||
|
s->what |= layer_state_t::eBlurMaskSurfaceChanged;
|
||||||
|
s->blurMaskSurface = maskSurfaceId;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Composer::setBlurMaskSampling(const sp<SurfaceComposerClient>& client,
|
||||||
|
const sp<IBinder>& id, uint32_t blurMaskSampling) {
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
layer_state_t* s = getLayerStateLocked(client, id);
|
||||||
|
if (!s)
|
||||||
|
return BAD_INDEX;
|
||||||
|
s->what |= layer_state_t::eBlurMaskSamplingChanged;
|
||||||
|
s->blurMaskSampling = blurMaskSampling;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t Composer::setBlurMaskAlphaThreshold(const sp<SurfaceComposerClient>& client,
|
||||||
|
const sp<IBinder>& id, float alpha) {
|
||||||
|
Mutex::Autolock _l(mLock);
|
||||||
|
layer_state_t* s = getLayerStateLocked(client, id);
|
||||||
|
if (!s)
|
||||||
|
return BAD_INDEX;
|
||||||
|
s->what |= layer_state_t::eBlurMaskAlphaThresholdChanged;
|
||||||
|
s->blurMaskAlphaThreshold = alpha;
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
|
status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
|
||||||
const sp<IBinder>& id, uint32_t flags,
|
const sp<IBinder>& id, uint32_t flags,
|
||||||
uint32_t mask) {
|
uint32_t mask) {
|
||||||
@ -574,6 +626,22 @@ status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, uint32_t z) {
|
|||||||
return getComposer().setLayer(this, id, z);
|
return getComposer().setLayer(this, id, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t SurfaceComposerClient::setBlur(const sp<IBinder>& id, float blur) {
|
||||||
|
return getComposer().setBlur(this, id, blur);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SurfaceComposerClient::setBlurMaskSurface(const sp<IBinder>& id, const sp<IBinder>& maskSurfaceId) {
|
||||||
|
return getComposer().setBlurMaskSurface(this, id, maskSurfaceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SurfaceComposerClient::setBlurMaskSampling(const sp<IBinder>& id, uint32_t blurMaskSampling) {
|
||||||
|
return getComposer().setBlurMaskSampling(this, id, blurMaskSampling);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t SurfaceComposerClient::setBlurMaskAlphaThreshold(const sp<IBinder>& id, float alpha) {
|
||||||
|
return getComposer().setBlurMaskAlphaThreshold(this, id, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
|
status_t SurfaceComposerClient::hide(const sp<IBinder>& id) {
|
||||||
return getComposer().setFlags(this, id,
|
return getComposer().setFlags(this, id,
|
||||||
layer_state_t::eLayerHidden,
|
layer_state_t::eLayerHidden,
|
||||||
|
@ -99,6 +99,26 @@ status_t SurfaceControl::setLayer(uint32_t layer) {
|
|||||||
if (err < 0) return err;
|
if (err < 0) return err;
|
||||||
return mClient->setLayer(mHandle, layer);
|
return mClient->setLayer(mHandle, layer);
|
||||||
}
|
}
|
||||||
|
status_t SurfaceControl::setBlur(float blur) {
|
||||||
|
status_t err = validate();
|
||||||
|
if (err < 0) return err;
|
||||||
|
return mClient->setBlur(mHandle, blur);
|
||||||
|
}
|
||||||
|
status_t SurfaceControl::setBlurMaskSurface(const sp<SurfaceControl>& maskSurface) {
|
||||||
|
status_t err = validate();
|
||||||
|
if (err < 0) return err;
|
||||||
|
return mClient->setBlurMaskSurface(mHandle, maskSurface != 0 ? maskSurface->mHandle : 0);
|
||||||
|
}
|
||||||
|
status_t SurfaceControl::setBlurMaskSampling(uint32_t blurMaskSampling) {
|
||||||
|
status_t err = validate();
|
||||||
|
if (err < 0) return err;
|
||||||
|
return mClient->setBlurMaskSampling(mHandle, blurMaskSampling);
|
||||||
|
}
|
||||||
|
status_t SurfaceControl::setBlurMaskAlphaThreshold(float alpha) {
|
||||||
|
status_t err = validate();
|
||||||
|
if (err < 0) return err;
|
||||||
|
return mClient->setBlurMaskAlphaThreshold(mHandle, alpha);
|
||||||
|
}
|
||||||
status_t SurfaceControl::setPosition(float x, float y) {
|
status_t SurfaceControl::setPosition(float x, float y) {
|
||||||
status_t err = validate();
|
status_t err = validate();
|
||||||
if (err < 0) return err;
|
if (err < 0) return err;
|
||||||
|
@ -13,6 +13,7 @@ LOCAL_SRC_FILES := \
|
|||||||
FrameTracker.cpp \
|
FrameTracker.cpp \
|
||||||
Layer.cpp \
|
Layer.cpp \
|
||||||
LayerDim.cpp \
|
LayerDim.cpp \
|
||||||
|
LayerBlur.cpp \
|
||||||
MessageQueue.cpp \
|
MessageQueue.cpp \
|
||||||
MonitoredProducer.cpp \
|
MonitoredProducer.cpp \
|
||||||
SurfaceFlinger.cpp \
|
SurfaceFlinger.cpp \
|
||||||
@ -117,6 +118,12 @@ ifeq ($(TARGET_USES_QCOM_BSP), true)
|
|||||||
LOCAL_CFLAGS += -DQTI_BSP
|
LOCAL_CFLAGS += -DQTI_BSP
|
||||||
endif
|
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_MODULE := libsurfaceflinger
|
||||||
|
|
||||||
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
|
LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code
|
||||||
|
69
services/surfaceflinger/FrameRateHelper.h
Normal file
69
services/surfaceflinger/FrameRateHelper.h
Normal file
@ -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
|
@ -108,6 +108,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
|
|||||||
mCurrentState.active.crop.makeInvalid();
|
mCurrentState.active.crop.makeInvalid();
|
||||||
mCurrentState.z = 0;
|
mCurrentState.z = 0;
|
||||||
mCurrentState.alpha = 0xFF;
|
mCurrentState.alpha = 0xFF;
|
||||||
|
mCurrentState.blur = 0xFF;
|
||||||
mCurrentState.layerStack = 0;
|
mCurrentState.layerStack = 0;
|
||||||
mCurrentState.flags = layerFlags;
|
mCurrentState.flags = layerFlags;
|
||||||
mCurrentState.sequence = 0;
|
mCurrentState.sequence = 0;
|
||||||
@ -607,21 +608,21 @@ Rect Layer::getPosition(
|
|||||||
// drawing...
|
// 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);
|
onDraw(hw, clip, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layer::draw(const sp<const DisplayDevice>& hw,
|
void Layer::draw(const sp<const DisplayDevice>& hw,
|
||||||
bool useIdentityTransform) const {
|
bool useIdentityTransform) {
|
||||||
onDraw(hw, Region(hw->bounds()), 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);
|
onDraw(hw, Region(hw->bounds()), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
|
void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||||
bool useIdentityTransform) const
|
bool useIdentityTransform)
|
||||||
{
|
{
|
||||||
ATRACE_CALL();
|
ATRACE_CALL();
|
||||||
|
|
||||||
@ -1031,6 +1032,14 @@ bool Layer::setLayer(uint32_t z) {
|
|||||||
setTransactionFlags(eTransactionNeeded);
|
setTransactionFlags(eTransactionNeeded);
|
||||||
return true;
|
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) {
|
bool Layer::setSize(uint32_t w, uint32_t h) {
|
||||||
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
|
if (mCurrentState.requested.w == w && mCurrentState.requested.h == h)
|
||||||
return false;
|
return false;
|
||||||
@ -1479,13 +1488,13 @@ void Layer::dump(String8& result, Colorizer& colorizer) const
|
|||||||
result.appendFormat( " "
|
result.appendFormat( " "
|
||||||
"layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
|
"layerStack=%4d, z=%9d, pos=(%g,%g), size=(%4d,%4d), crop=(%4d,%4d,%4d,%4d), "
|
||||||
"isOpaque=%1d, invalidate=%1d, "
|
"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",
|
" client=%p\n",
|
||||||
s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
|
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.left, s.active.crop.top,
|
||||||
s.active.crop.right, s.active.crop.bottom,
|
s.active.crop.right, s.active.crop.bottom,
|
||||||
isOpaque(s), contentDirty,
|
isOpaque(s), contentDirty,
|
||||||
s.alpha, s.flags,
|
s.alpha, s.blur, s.flags,
|
||||||
s.transform[0][0], s.transform[0][1],
|
s.transform[0][0], s.transform[0][1],
|
||||||
s.transform[1][0], s.transform[1][1],
|
s.transform[1][0], s.transform[1][1],
|
||||||
client.get());
|
client.get());
|
||||||
|
@ -57,6 +57,7 @@ class Colorizer;
|
|||||||
class DisplayDevice;
|
class DisplayDevice;
|
||||||
class GraphicBuffer;
|
class GraphicBuffer;
|
||||||
class SurfaceFlinger;
|
class SurfaceFlinger;
|
||||||
|
class LayerBlur;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -70,6 +71,8 @@ class SurfaceFlinger;
|
|||||||
class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {
|
class Layer : public SurfaceFlingerConsumer::ContentsChangedListener {
|
||||||
static int32_t sSequence;
|
static int32_t sSequence;
|
||||||
|
|
||||||
|
friend class LayerBlur;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef QTI_BSP
|
#ifdef QTI_BSP
|
||||||
friend class ExLayer;
|
friend class ExLayer;
|
||||||
@ -108,6 +111,7 @@ public:
|
|||||||
Geometry requested;
|
Geometry requested;
|
||||||
uint32_t z;
|
uint32_t z;
|
||||||
uint32_t layerStack;
|
uint32_t layerStack;
|
||||||
|
uint8_t blur;
|
||||||
uint8_t alpha;
|
uint8_t alpha;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t reserved[2];
|
uint8_t reserved[2];
|
||||||
@ -133,6 +137,10 @@ public:
|
|||||||
// modify current state
|
// modify current state
|
||||||
bool setPosition(float x, float y);
|
bool setPosition(float x, float y);
|
||||||
bool setLayer(uint32_t z);
|
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 setSize(uint32_t w, uint32_t h);
|
||||||
bool setAlpha(uint8_t alpha);
|
bool setAlpha(uint8_t alpha);
|
||||||
bool setMatrix(const layer_state_t::matrix22_t& matrix);
|
bool setMatrix(const layer_state_t::matrix22_t& matrix);
|
||||||
@ -195,12 +203,17 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool isFixedSize() const;
|
virtual bool isFixedSize() const;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* isBlurLayer - true if this is a LayerBlur instance
|
||||||
|
*/
|
||||||
|
virtual bool isBlurLayer() const { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*
|
/*
|
||||||
* onDraw - draws the surface.
|
* onDraw - draws the surface.
|
||||||
*/
|
*/
|
||||||
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
|
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
|
||||||
bool useIdentityTransform) const;
|
bool useIdentityTransform);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// -----------------------------------------------------------------------
|
// -----------------------------------------------------------------------
|
||||||
@ -237,9 +250,9 @@ public:
|
|||||||
* draw - performs some global clipping optimizations
|
* draw - performs some global clipping optimizations
|
||||||
* and calls onDraw().
|
* and calls onDraw().
|
||||||
*/
|
*/
|
||||||
void draw(const sp<const DisplayDevice>& hw, const Region& clip) const;
|
void draw(const sp<const DisplayDevice>& hw, const Region& clip);
|
||||||
void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform) const;
|
void draw(const sp<const DisplayDevice>& hw, bool useIdentityTransform);
|
||||||
void draw(const sp<const DisplayDevice>& hw) const;
|
void draw(const sp<const DisplayDevice>& hw);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* doTransaction - process the transaction. This is a good place to figure
|
* doTransaction - process the transaction. This is a good place to figure
|
||||||
|
415
services/surfaceflinger/LayerBlur.cpp
Normal file
415
services/surfaceflinger/LayerBlur.cpp
Normal file
@ -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
|
106
services/surfaceflinger/LayerBlur.h
Normal file
106
services/surfaceflinger/LayerBlur.h
Normal file
@ -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
|
@ -40,7 +40,7 @@ LayerDim::~LayerDim() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LayerDim::onDraw(const sp<const DisplayDevice>& hw,
|
void LayerDim::onDraw(const sp<const DisplayDevice>& hw,
|
||||||
const Region& /* clip */, bool useIdentityTransform) const
|
const Region& /* clip */, bool useIdentityTransform)
|
||||||
{
|
{
|
||||||
const State& s(getDrawingState());
|
const State& s(getDrawingState());
|
||||||
if (s.alpha>0) {
|
if (s.alpha>0) {
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
|
|
||||||
virtual const char* getTypeId() const { return "LayerDim"; }
|
virtual const char* getTypeId() const { return "LayerDim"; }
|
||||||
virtual void onDraw(const sp<const DisplayDevice>& hw, const Region& clip,
|
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 isOpaque(const Layer::State&) const { return false; }
|
||||||
virtual bool isSecure() const { return false; }
|
virtual bool isSecure() const { return false; }
|
||||||
virtual bool isFixedSize() const { return true; }
|
virtual bool isFixedSize() const { return true; }
|
||||||
|
@ -33,6 +33,8 @@ Description::Description() :
|
|||||||
mOpaque = true;
|
mOpaque = true;
|
||||||
mTextureEnabled = false;
|
mTextureEnabled = false;
|
||||||
mColorMatrixEnabled = false;
|
mColorMatrixEnabled = false;
|
||||||
|
mMaskTextureEnabled = false;
|
||||||
|
mMaskAlphaThreshold = 0.0f;
|
||||||
|
|
||||||
memset(mColor, 0, sizeof(mColor));
|
memset(mColor, 0, sizeof(mColor));
|
||||||
}
|
}
|
||||||
@ -92,5 +94,14 @@ const mat4& Description::getColorMatrix() const {
|
|||||||
return mColorMatrix;
|
return mColorMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Description::setMasking(const Texture& maskTexture, float alphaThreshold) {
|
||||||
|
mMaskTexture = maskTexture;
|
||||||
|
mMaskTextureEnabled = true;
|
||||||
|
mMaskAlphaThreshold = alphaThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Description::disableMasking() {
|
||||||
|
mMaskTextureEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
} /* namespace android */
|
} /* namespace android */
|
||||||
|
@ -53,6 +53,9 @@ class Description {
|
|||||||
|
|
||||||
bool mColorMatrixEnabled;
|
bool mColorMatrixEnabled;
|
||||||
mat4 mColorMatrix;
|
mat4 mColorMatrix;
|
||||||
|
Texture mMaskTexture;
|
||||||
|
bool mMaskTextureEnabled;
|
||||||
|
GLclampf mMaskAlphaThreshold;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Description();
|
Description();
|
||||||
@ -67,6 +70,8 @@ public:
|
|||||||
void setProjectionMatrix(const mat4& mtx);
|
void setProjectionMatrix(const mat4& mtx);
|
||||||
void setColorMatrix(const mat4& mtx);
|
void setColorMatrix(const mat4& mtx);
|
||||||
const mat4& getColorMatrix() const;
|
const mat4& getColorMatrix() const;
|
||||||
|
void setMasking(const Texture& maskTexture, float alphaThreshold);
|
||||||
|
void disableMasking();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mUniformsDirty;
|
bool mUniformsDirty;
|
||||||
|
@ -60,6 +60,8 @@ protected:
|
|||||||
virtual void setupFillWithColor(float r, float g, float b, float a) ;
|
virtual void setupFillWithColor(float r, float g, float b, float a) ;
|
||||||
virtual void disableTexturing();
|
virtual void disableTexturing();
|
||||||
virtual void disableBlending();
|
virtual void disableBlending();
|
||||||
|
virtual void setupLayerMasking(const Texture& /*maskTexture*/, float /*alphaThreshold*/) {}
|
||||||
|
virtual void disableLayerMasking() {}
|
||||||
|
|
||||||
virtual void drawMesh(const Mesh& mesh);
|
virtual void drawMesh(const Mesh& mesh);
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ namespace android {
|
|||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
GLES20RenderEngine::GLES20RenderEngine() :
|
GLES20RenderEngine::GLES20RenderEngine() :
|
||||||
mVpWidth(0), mVpHeight(0) {
|
mVpWidth(0), mVpHeight(0), mProjectionRotation(Transform::ROT_0) {
|
||||||
|
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
|
||||||
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
|
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
|
||||||
@ -115,6 +115,9 @@ void GLES20RenderEngine::setViewportAndProjection(
|
|||||||
mState.setProjectionMatrix(m);
|
mState.setProjectionMatrix(m);
|
||||||
mVpWidth = vpw;
|
mVpWidth = vpw;
|
||||||
mVpHeight = vph;
|
mVpHeight = vph;
|
||||||
|
mProjectionSourceCrop = sourceCrop;
|
||||||
|
mProjectionYSwap = yswap;
|
||||||
|
mProjectionRotation = rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLES20RenderEngine::setupLayerBlending(
|
void GLES20RenderEngine::setupLayerBlending(
|
||||||
@ -264,6 +267,30 @@ void GLES20RenderEngine::dump(String8& result) {
|
|||||||
RenderEngine::dump(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
|
}; // namespace android
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -42,6 +42,9 @@ class GLES20RenderEngine : public RenderEngine {
|
|||||||
GLint mMaxTextureSize;
|
GLint mMaxTextureSize;
|
||||||
GLuint mVpWidth;
|
GLuint mVpWidth;
|
||||||
GLuint mVpHeight;
|
GLuint mVpHeight;
|
||||||
|
Rect mProjectionSourceCrop;
|
||||||
|
bool mProjectionYSwap;
|
||||||
|
Transform::orientation_flags mProjectionRotation;
|
||||||
|
|
||||||
struct Group {
|
struct Group {
|
||||||
GLuint texture;
|
GLuint texture;
|
||||||
@ -76,11 +79,18 @@ protected:
|
|||||||
virtual mat4 setupColorTransform(const mat4& colorTransform);
|
virtual mat4 setupColorTransform(const mat4& colorTransform);
|
||||||
virtual void disableTexturing();
|
virtual void disableTexturing();
|
||||||
virtual void disableBlending();
|
virtual void disableBlending();
|
||||||
|
virtual void setupLayerMasking(const Texture& maskTexture, float alphaThreshold);
|
||||||
|
virtual void disableLayerMasking();
|
||||||
|
|
||||||
virtual void drawMesh(const Mesh& mesh);
|
virtual void drawMesh(const Mesh& mesh);
|
||||||
|
|
||||||
virtual size_t getMaxTextureSize() const;
|
virtual size_t getMaxTextureSize() const;
|
||||||
virtual size_t getMaxViewportDims() 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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
@ -64,6 +64,8 @@ Program::Program(const ProgramCache::Key& /*needs*/, const char* vertex, const c
|
|||||||
mSamplerLoc = glGetUniformLocation(programId, "sampler");
|
mSamplerLoc = glGetUniformLocation(programId, "sampler");
|
||||||
mColorLoc = glGetUniformLocation(programId, "color");
|
mColorLoc = glGetUniformLocation(programId, "color");
|
||||||
mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane");
|
mAlphaPlaneLoc = glGetUniformLocation(programId, "alphaPlane");
|
||||||
|
mSamplerMaskLoc = glGetUniformLocation(programId, "samplerMask");
|
||||||
|
mMaskAlphaThresholdLoc = glGetUniformLocation(programId, "maskAlphaThreshold");
|
||||||
|
|
||||||
// set-up the default values for our uniforms
|
// set-up the default values for our uniforms
|
||||||
glUseProgram(programId);
|
glUseProgram(programId);
|
||||||
@ -143,6 +145,12 @@ void Program::setUniforms(const Description& desc) {
|
|||||||
}
|
}
|
||||||
// these uniforms are always present
|
// these uniforms are always present
|
||||||
glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
|
glUniformMatrix4fv(mProjectionMatrixLoc, 1, GL_FALSE, desc.mProjectionMatrix.asArray());
|
||||||
|
if (mSamplerMaskLoc >= 0) {
|
||||||
|
glUniform1i(mSamplerMaskLoc, 1);
|
||||||
|
}
|
||||||
|
if (mMaskAlphaThresholdLoc >= 0) {
|
||||||
|
glUniform1f(mMaskAlphaThresholdLoc, desc.mMaskAlphaThreshold);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace android */
|
} /* namespace android */
|
||||||
|
@ -84,6 +84,9 @@ private:
|
|||||||
|
|
||||||
/* location of the color uniform */
|
/* location of the color uniform */
|
||||||
GLint mColorLoc;
|
GLint mColorLoc;
|
||||||
|
|
||||||
|
GLint mSamplerMaskLoc;
|
||||||
|
GLint mMaskAlphaThresholdLoc;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
|
|
||||||
#include <GLES2/gl2.h>
|
#include <GLES2/gl2.h>
|
||||||
#include <GLES2/gl2ext.h>
|
#include <GLES2/gl2ext.h>
|
||||||
|
|
||||||
@ -110,9 +112,27 @@ void ProgramCache::primeCache() {
|
|||||||
shaderCount++;
|
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();
|
nsecs_t timeAfter = systemTime();
|
||||||
float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
|
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) {
|
ProgramCache::Key ProgramCache::computeKey(const Description& description) {
|
||||||
@ -129,15 +149,20 @@ ProgramCache::Key ProgramCache::computeKey(const Description& description) {
|
|||||||
.set(Key::OPACITY_MASK,
|
.set(Key::OPACITY_MASK,
|
||||||
description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
|
description.mOpaque ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT)
|
||||||
.set(Key::COLOR_MATRIX_MASK,
|
.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;
|
return needs;
|
||||||
}
|
}
|
||||||
|
|
||||||
String8 ProgramCache::generateVertexShader(const Key& needs) {
|
String8 ProgramCache::generateVertexShader(const Key& needs) {
|
||||||
Formatter vs;
|
Formatter vs;
|
||||||
if (needs.isTexturing()) {
|
if (needs.isTexturing()) {
|
||||||
vs << "attribute vec4 texCoords;"
|
vs << "attribute vec4 texCoords;"
|
||||||
<< "varying vec2 outTexCoords;";
|
<< "varying vec2 outTexCoords;";
|
||||||
}
|
}
|
||||||
vs << "attribute vec4 position;"
|
vs << "attribute vec4 position;"
|
||||||
<< "uniform mat4 projection;"
|
<< "uniform mat4 projection;"
|
||||||
@ -145,7 +170,7 @@ String8 ProgramCache::generateVertexShader(const Key& needs) {
|
|||||||
<< "void main(void) {" << indent
|
<< "void main(void) {" << indent
|
||||||
<< "gl_Position = projection * position;";
|
<< "gl_Position = projection * position;";
|
||||||
if (needs.isTexturing()) {
|
if (needs.isTexturing()) {
|
||||||
vs << "outTexCoords = (texture * texCoords).st;";
|
vs << "outTexCoords = (texture * texCoords).st;";
|
||||||
}
|
}
|
||||||
vs << dedent << "}";
|
vs << dedent << "}";
|
||||||
return vs.getString();
|
return vs.getString();
|
||||||
@ -169,6 +194,14 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) {
|
|||||||
} else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
|
} else if (needs.getTextureTarget() == Key::TEXTURE_OFF) {
|
||||||
fs << "uniform vec4 color;";
|
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()) {
|
if (needs.hasPlaneAlpha()) {
|
||||||
fs << "uniform float alphaPlane;";
|
fs << "uniform float alphaPlane;";
|
||||||
}
|
}
|
||||||
@ -177,7 +210,12 @@ String8 ProgramCache::generateFragmentShader(const Key& needs) {
|
|||||||
}
|
}
|
||||||
fs << "void main(void) {" << indent;
|
fs << "void main(void) {" << indent;
|
||||||
if (needs.isTexturing()) {
|
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 {
|
} else {
|
||||||
fs << "gl_FragColor = color;";
|
fs << "gl_FragColor = color;";
|
||||||
}
|
}
|
||||||
@ -235,9 +273,6 @@ void ProgramCache::useProgram(const Description& description) {
|
|||||||
program = generateProgram(needs);
|
program = generateProgram(needs);
|
||||||
mCache.add(needs, program);
|
mCache.add(needs, program);
|
||||||
time += systemTime();
|
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
|
// here we have a suitable program for this description
|
||||||
|
@ -69,6 +69,11 @@ public:
|
|||||||
COLOR_MATRIX_OFF = 0x00000000,
|
COLOR_MATRIX_OFF = 0x00000000,
|
||||||
COLOR_MATRIX_ON = 0x00000020,
|
COLOR_MATRIX_ON = 0x00000020,
|
||||||
COLOR_MATRIX_MASK = 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) { }
|
inline Key() : mKey(0) { }
|
||||||
@ -97,6 +102,12 @@ public:
|
|||||||
inline bool hasColorMatrix() const {
|
inline bool hasColorMatrix() const {
|
||||||
return (mKey & COLOR_MATRIX_MASK) == COLOR_MATRIX_ON;
|
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
|
// 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) {
|
friend inline int strictly_order_type(const Key& lhs, const Key& rhs) {
|
||||||
|
@ -110,6 +110,8 @@ public:
|
|||||||
|
|
||||||
virtual void disableTexturing() = 0;
|
virtual void disableTexturing() = 0;
|
||||||
virtual void disableBlending() = 0;
|
virtual void disableBlending() = 0;
|
||||||
|
virtual void setupLayerMasking(const Texture& maskTexture, float alphaThreshold) = 0;
|
||||||
|
virtual void disableLayerMasking() = 0;
|
||||||
|
|
||||||
// drawing
|
// drawing
|
||||||
virtual void drawMesh(const Mesh& mesh) = 0;
|
virtual void drawMesh(const Mesh& mesh) = 0;
|
||||||
@ -117,6 +119,11 @@ public:
|
|||||||
// queries
|
// queries
|
||||||
virtual size_t getMaxTextureSize() const = 0;
|
virtual size_t getMaxTextureSize() const = 0;
|
||||||
virtual size_t getMaxViewportDims() 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;
|
EGLConfig getEGLConfig() const;
|
||||||
EGLContext getEGLContext() const;
|
EGLContext getEGLContext() const;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
|
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -68,6 +69,7 @@
|
|||||||
#include "EventThread.h"
|
#include "EventThread.h"
|
||||||
#include "Layer.h"
|
#include "Layer.h"
|
||||||
#include "LayerDim.h"
|
#include "LayerDim.h"
|
||||||
|
#include "LayerBlur.h"
|
||||||
#include "SurfaceFlinger.h"
|
#include "SurfaceFlinger.h"
|
||||||
|
|
||||||
#include "DisplayHardware/FramebufferSurface.h"
|
#include "DisplayHardware/FramebufferSurface.h"
|
||||||
@ -157,7 +159,8 @@ SurfaceFlinger::SurfaceFlinger()
|
|||||||
mHasPoweredOff(false),
|
mHasPoweredOff(false),
|
||||||
mFrameBuckets(),
|
mFrameBuckets(),
|
||||||
mTotalTime(0),
|
mTotalTime(0),
|
||||||
mLastSwapTime(0)
|
mLastSwapTime(0),
|
||||||
|
mActiveFrameSequence(0)
|
||||||
{
|
{
|
||||||
ALOGI("SurfaceFlinger is starting");
|
ALOGI("SurfaceFlinger is starting");
|
||||||
|
|
||||||
@ -1249,6 +1252,8 @@ void SurfaceFlinger::doComposition() {
|
|||||||
// repaint the framebuffer (if needed)
|
// repaint the framebuffer (if needed)
|
||||||
doDisplayComposition(hw, dirtyRegion);
|
doDisplayComposition(hw, dirtyRegion);
|
||||||
|
|
||||||
|
++mActiveFrameSequence;
|
||||||
|
|
||||||
hw->dirtyRegion.clear();
|
hw->dirtyRegion.clear();
|
||||||
hw->flip(hw->swapRegion);
|
hw->flip(hw->swapRegion);
|
||||||
hw->swapRegion.clear();
|
hw->swapRegion.clear();
|
||||||
@ -1309,6 +1314,7 @@ void SurfaceFlinger::postFramebuffer()
|
|||||||
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
|
if (flipCount % LOG_FRAME_STATS_PERIOD == 0) {
|
||||||
logFrameStats();
|
logFrameStats();
|
||||||
}
|
}
|
||||||
|
ALOGV_IF(mFrameRateHelper.update(), "FPS: %d", mFrameRateHelper.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
|
||||||
@ -2277,6 +2283,41 @@ uint32_t SurfaceFlinger::setClientStateLocked(
|
|||||||
flags |= eTransactionNeeded|eTraversalNeeded;
|
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 (what & layer_state_t::eSizeChanged) {
|
||||||
if (layer->setSize(s.w, s.h)) {
|
if (layer->setSize(s.w, s.h)) {
|
||||||
flags |= eTraversalNeeded;
|
flags |= eTraversalNeeded;
|
||||||
@ -2345,6 +2386,11 @@ status_t SurfaceFlinger::createLayer(
|
|||||||
name, w, h, flags,
|
name, w, h, flags,
|
||||||
handle, gbp, &layer);
|
handle, gbp, &layer);
|
||||||
break;
|
break;
|
||||||
|
case ISurfaceComposerClient::eFXSurfaceBlur:
|
||||||
|
result = createBlurLayer(client,
|
||||||
|
name, w, h, flags,
|
||||||
|
handle, gbp, &layer);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
result = BAD_VALUE;
|
result = BAD_VALUE;
|
||||||
break;
|
break;
|
||||||
@ -2399,6 +2445,16 @@ status_t SurfaceFlinger::createDimLayer(const sp<Client>& client,
|
|||||||
return NO_ERROR;
|
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)
|
status_t SurfaceFlinger::onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle)
|
||||||
{
|
{
|
||||||
// called by the window manager when it wants to remove a Layer
|
// called by the window manager when it wants to remove a Layer
|
||||||
@ -3407,6 +3463,8 @@ status_t SurfaceFlinger::captureScreenImplLocked(
|
|||||||
return BAD_VALUE;
|
return BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++mActiveFrameSequence;
|
||||||
|
|
||||||
reqWidth = (!reqWidth) ? hw_w : reqWidth;
|
reqWidth = (!reqWidth) ? hw_w : reqWidth;
|
||||||
reqHeight = (!reqHeight) ? hw_h : reqHeight;
|
reqHeight = (!reqHeight) ? hw_h : reqHeight;
|
||||||
|
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
#include "DisplayHardware/HWComposer.h"
|
#include "DisplayHardware/HWComposer.h"
|
||||||
#include "Effects/Daltonizer.h"
|
#include "Effects/Daltonizer.h"
|
||||||
|
|
||||||
|
#include "FrameRateHelper.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@ -66,6 +68,7 @@ class EventThread;
|
|||||||
class IGraphicBufferAlloc;
|
class IGraphicBufferAlloc;
|
||||||
class Layer;
|
class Layer;
|
||||||
class LayerDim;
|
class LayerDim;
|
||||||
|
class LayerBlur;
|
||||||
class Surface;
|
class Surface;
|
||||||
class RenderEngine;
|
class RenderEngine;
|
||||||
class EventControlThread;
|
class EventControlThread;
|
||||||
@ -144,6 +147,7 @@ private:
|
|||||||
friend class Layer;
|
friend class Layer;
|
||||||
friend class LayerDim;
|
friend class LayerDim;
|
||||||
friend class MonitoredProducer;
|
friend class MonitoredProducer;
|
||||||
|
friend class LayerBlur;
|
||||||
|
|
||||||
// This value is specified in number of frames. Log frame stats at most
|
// This value is specified in number of frames. Log frame stats at most
|
||||||
// every half hour.
|
// every half hour.
|
||||||
@ -337,6 +341,10 @@ private:
|
|||||||
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
|
uint32_t w, uint32_t h, uint32_t flags, sp<IBinder>* outHandle,
|
||||||
sp<IGraphicBufferProducer>* outGbp, sp<Layer>* outLayer);
|
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
|
// called in response to the window-manager calling
|
||||||
// ISurfaceComposerClient::destroySurface()
|
// ISurfaceComposerClient::destroySurface()
|
||||||
status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
|
status_t onLayerRemoved(const sp<Client>& client, const sp<IBinder>& handle);
|
||||||
@ -550,6 +558,17 @@ private:
|
|||||||
nsecs_t mFrameBuckets[NUM_BUCKETS];
|
nsecs_t mFrameBuckets[NUM_BUCKETS];
|
||||||
nsecs_t mTotalTime;
|
nsecs_t mTotalTime;
|
||||||
nsecs_t mLastSwapTime;
|
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
|
}; // namespace android
|
||||||
|
Loading…
Reference in New Issue
Block a user