Merge "Add default videos for background replacement."
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 0ff1cce..c9567d5 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -22,6 +22,7 @@
#include <utils/Errors.h>
#include <utils/String8.h>
+#include <utils/Vector.h>
#include <hardware/hardware.h>
@@ -29,6 +30,7 @@
#include <EGL/egl.h>
+#include "LayerBase.h"
#include "HWComposer.h"
#include "SurfaceFlinger.h"
@@ -133,7 +135,8 @@
return mList ? mList->hwLayers : 0;
}
-void HWComposer::dump(String8& result, char* buffer, size_t SIZE) const {
+void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
+ const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
if (mHwc && mList) {
result.append("Hardware Composer state:\n");
@@ -143,11 +146,12 @@
for (size_t i=0 ; i<mList->numHwLayers ; i++) {
const hwc_layer_t& l(mList->hwLayers[i]);
- snprintf(buffer, SIZE, " %8s | %08x | %08x | %02x | %04x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d]\n",
+ snprintf(buffer, SIZE, " %8s | %08x | %08x | %02x | %04x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n",
l.compositionType ? "OVERLAY" : "FB",
l.hints, l.flags, l.transform, l.blending,
l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom,
- l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom);
+ l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom,
+ visibleLayersSortedByZ[i]->getName().string());
result.append(buffer);
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 77c1a4b..8758a80 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -25,12 +25,14 @@
#include <hardware/hwcomposer.h>
#include <utils/StrongPointer.h>
+#include <utils/Vector.h>
namespace android {
// ---------------------------------------------------------------------------
class String8;
class SurfaceFlinger;
+class LayerBase;
class HWComposer
{
@@ -63,7 +65,8 @@
hwc_layer_t* getLayers() const;
// for debugging
- void dump(String8& out, char* scratch, size_t SIZE) const;
+ void dump(String8& out, char* scratch, size_t SIZE,
+ const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
private:
struct cb_context {
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 603fb60..e5ce814 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -43,7 +43,7 @@
: dpy(display), contentDirty(false),
sequence(uint32_t(android_atomic_inc(&sSequence))),
mFlinger(flinger), mFiltering(false),
- mNeedsFiltering(false),
+ mNeedsFiltering(false), mInOverlay(false),
mOrientation(0),
mTransactionFlags(0),
mPremultipliedAlpha(true), mName("unnamed"), mDebug(false),
@@ -344,6 +344,14 @@
hwcl->handle = NULL;
}
+void LayerBase::setOverlay(bool inOverlay) {
+ mInOverlay = inOverlay;
+}
+
+bool LayerBase::isOverlay() const {
+ return mInOverlay;
+}
+
void LayerBase::setFiltering(bool filtering)
{
mFiltering = filtering;
@@ -472,12 +480,13 @@
{
const Layer::State& s(drawingState());
snprintf(buffer, SIZE,
- "+ %s %p\n"
+ "+ %s %p (%s)\n"
" "
"z=%9d, pos=(%g,%g), size=(%4d,%4d), "
"isOpaque=%1d, needsDithering=%1d, invalidate=%1d, "
"alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
- getTypeId(), this, s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
+ getTypeId(), this, getName().string(),
+ s.z, s.transform.tx(), s.transform.ty(), s.w, s.h,
isOpaque(), needsDithering(), contentDirty,
s.alpha, s.flags,
s.transform[0][0], s.transform[0][1],
@@ -553,9 +562,7 @@
sp<Client> client(mClientRef.promote());
snprintf(buffer, SIZE,
- " name=%s\n"
" client=%p, identity=%u\n",
- getName().string(),
client.get(), getIdentity());
result.append(buffer);
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index d20f06a..ee50428 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -109,8 +109,10 @@
virtual const char* getTypeId() const { return "LayerBase"; }
virtual void setGeometry(hwc_layer_t* hwcl);
-
virtual void setPerFrameData(hwc_layer_t* hwcl);
+ void setOverlay(bool inOverlay);
+ bool isOverlay() const;
+
/**
* draw - performs some global clipping optimizations
@@ -242,6 +244,11 @@
// Whether filtering is needed b/c of the drawingstate
bool mNeedsFiltering;
+ // this layer is currently handled by the hwc. this is
+ // updated at composition time, always frmo the composition
+ // thread.
+ bool mInOverlay;
+
protected:
// cached during validateVisibility()
int32_t mOrientation;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4a3a8ea..df13640 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -817,20 +817,6 @@
mHwWorkListDirty = false;
HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
if (hwc.initCheck() == NO_ERROR) {
-
- const DisplayHardware& hw(graphicPlane(0).displayHardware());
- uint32_t flags = hw.getFlags();
- if ((flags & DisplayHardware::SWAP_RECTANGLE) ||
- (flags & DisplayHardware::BUFFER_PRESERVED))
- {
- // we need to redraw everything (the whole screen)
- // NOTE: we could be more subtle here and redraw only
- // the area which will end-up in an overlay. But since this
- // shouldn't happen often, we invalidate everything.
- mDirtyRegion.set(hw.bounds());
- mInvalidRegion = mDirtyRegion;
- }
-
const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
const size_t count = currentLayers.size();
hwc.createWorkList(count);
@@ -890,30 +876,30 @@
}
}
- // compose all surfaces
+ Region expandDirty = setupHardwareComposer(mDirtyRegion);
+ mDirtyRegion.orSelf(expandDirty);
+ mInvalidRegion.orSelf(mDirtyRegion);
composeSurfaces(mDirtyRegion);
// clear the dirty regions
mDirtyRegion.clear();
}
-void SurfaceFlinger::composeSurfaces(const Region& dirty)
+Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
{
- if (UNLIKELY(!mWormholeRegion.isEmpty())) {
- // should never happen unless the window manager has a bug
- // draw something...
- drawWormhole();
- }
-
- status_t err = NO_ERROR;
- const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
- size_t count = layers.size();
+ Region dirtyOut(dirty);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
hwc_layer_t* const cur(hwc.getLayers());
+ if (!cur) {
+ return dirtyOut;
+ }
- LOGE_IF(cur && hwc.getNumLayers() != count,
+ const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ size_t count = layers.size();
+
+ LOGE_IF(hwc.getNumLayers() != count,
"HAL number of layers (%d) doesn't match surfaceflinger (%d)",
hwc.getNumLayers(), count);
@@ -926,57 +912,95 @@
* update the per-frame h/w composer data for each layer
* and build the transparent region of the FB
*/
- Region transparent;
- if (cur) {
- for (size_t i=0 ; i<count ; i++) {
- const sp<LayerBase>& layer(layers[i]);
- layer->setPerFrameData(&cur[i]);
- }
- err = hwc.prepare();
- LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+ for (size_t i=0 ; i<count ; i++) {
+ const sp<LayerBase>& layer(layers[i]);
+ layer->setPerFrameData(&cur[i]);
+ }
+ status_t err = hwc.prepare();
+ LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
- if (err == NO_ERROR) {
- for (size_t i=0 ; i<count ; i++) {
- if (cur[i].hints & HWC_HINT_CLEAR_FB) {
- const sp<LayerBase>& layer(layers[i]);
- if (layer->isOpaque()) {
- transparent.orSelf(layer->visibleRegionScreen);
- }
- }
+ if (err == NO_ERROR) {
+ Region transparent;
+ for (size_t i=0 ; i<count ; i++) {
+ // what's happening here is tricky.
+ // we want to clear all the layers with the CLEAR_FB flags
+ // that are opaque.
+ // however, since some GPU have are efficient at preserving
+ // the backbuffer, we want to take advantage of that so we do the
+ // clear only in the dirty region (other areas will be preserved
+ // on those GPUs).
+ // NOTE: on non backbuffer preserving GPU, the dirty region
+ // has already been expanded as needed, so the code is correct
+ // there too.
+ // However, the content of the framebuffer cannot be trusted when
+ // we switch to/from FB/OVERLAY, in which case we need to
+ // expand the dirty region to those areas too.
+ //
+ // Also we want to make sure to not clear areas that belong to
+ // layers above that won't redraw (we would just erasing them),
+ // that is, we can't erase anything outside the dirty region.
+
+ const sp<LayerBase>& layer(layers[i]);
+ if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) {
+ transparent.orSelf(layer->visibleRegionScreen);
}
- /*
- * clear the area of the FB that need to be transparent
- */
- transparent.andSelf(dirty);
- if (!transparent.isEmpty()) {
- glClearColor(0,0,0,0);
- Region::const_iterator it = transparent.begin();
- Region::const_iterator const end = transparent.end();
- const int32_t height = hw.getHeight();
- while (it != end) {
- const Rect& r(*it++);
- const GLint sy = height - (r.top + r.height());
- glScissor(r.left, sy, r.width(), r.height());
- glClear(GL_COLOR_BUFFER_BIT);
- }
+ bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) &&
+ !(cur[i].flags & HWC_SKIP_LAYER);
+
+ if (isOverlay != layer->isOverlay()) {
+ // we transitioned to/from overlay, so add this layer
+ // to the dirty region so the framebuffer can be either
+ // cleared or redrawn.
+ dirtyOut.orSelf(layer->visibleRegionScreen);
+ }
+ layer->setOverlay(isOverlay);
+ }
+
+
+ /*
+ * clear the area of the FB that need to be transparent
+ */
+ // don't erase stuff outside the dirty region
+ transparent.andSelf(dirtyOut);
+ if (!transparent.isEmpty()) {
+ glClearColor(0,0,0,0);
+ Region::const_iterator it = transparent.begin();
+ Region::const_iterator const end = transparent.end();
+ const int32_t height = hw.getHeight();
+ while (it != end) {
+ const Rect& r(*it++);
+ const GLint sy = height - (r.top + r.height());
+ glScissor(r.left, sy, r.width(), r.height());
+ glClear(GL_COLOR_BUFFER_BIT);
}
}
}
+ return dirtyOut;
+}
+void SurfaceFlinger::composeSurfaces(const Region& dirty)
+{
+ if (UNLIKELY(!mWormholeRegion.isEmpty())) {
+ // should never happen unless the window manager has a bug
+ // draw something...
+ drawWormhole();
+ }
+
+ const DisplayHardware& hw(graphicPlane(0).displayHardware());
+ HWComposer& hwc(hw.getHwComposer());
+ hwc_layer_t* const cur(hwc.getLayers());
/*
* and then, render the layers targeted at the framebuffer
*/
+ const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+ size_t count = layers.size();
for (size_t i=0 ; i<count ; i++) {
- if (cur) {
- if ((cur[i].compositionType != HWC_FRAMEBUFFER) &&
+ if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER) &&
!(cur[i].flags & HWC_SKIP_LAYER)) {
- // skip layers handled by the HAL
- continue;
- }
+ continue;
}
-
const sp<LayerBase>& layer(layers[i]);
const Region clip(dirty.intersect(layer->visibleRegionScreen));
if (!clip.isEmpty()) {
@@ -1597,7 +1621,7 @@
hwc.initCheck()==NO_ERROR ? "present" : "not present",
(mDebugDisableHWC || mDebugRegion) ? "disabled" : "enabled");
result.append(buffer);
- hwc.dump(result, buffer, SIZE);
+ hwc.dump(result, buffer, SIZE, mVisibleLayersSortedByZ);
/*
* Dump gralloc state
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 5f8eb08..126ca39 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -277,6 +277,7 @@
void handleWorkList();
void handleRepaint();
void postFramebuffer();
+ Region setupHardwareComposer(const Region& dirty);
void composeSurfaces(const Region& dirty);
void repaintEverything();