summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2011-09-09 01:47:48 -0700
committerMathias Agopian <mathias@google.com>2011-09-09 01:47:48 -0700
commit0a5abdb3161510d6f0c88fbe75140325620ac366 (patch)
treeb70182917c44f7b469494719c5197196f1fe7d72 /services/surfaceflinger
parent5bd1b2794b227e25fbd7e4c919bcefc3510e0761 (diff)
downloadframeworks_base-0a5abdb3161510d6f0c88fbe75140325620ac366.zip
frameworks_base-0a5abdb3161510d6f0c88fbe75140325620ac366.tar.gz
frameworks_base-0a5abdb3161510d6f0c88fbe75140325620ac366.tar.bz2
Fix another problem with refreshing the screen when switching to/from overlay
the previous fix was incorrect. See comment in setupHardwareComposer for full explanations. Change-Id: Ib24a9af000b8f95cf7319f9272d34997064ceb6d
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/LayerBase.cpp2
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp53
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h2
3 files changed, 36 insertions, 21 deletions
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index a63dcd3..e5ce814 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -43,7 +43,7 @@ LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
: 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),
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 768f8e0..df13640 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -876,21 +876,24 @@ void SurfaceFlinger::handleRepaint()
}
}
- // compose all surfaces
- setupHardwareComposer(&mDirtyRegion);
+ Region expandDirty = setupHardwareComposer(mDirtyRegion);
+ mDirtyRegion.orSelf(expandDirty);
+ mInvalidRegion.orSelf(mDirtyRegion);
composeSurfaces(mDirtyRegion);
// clear the dirty regions
mDirtyRegion.clear();
}
-void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut)
+Region SurfaceFlinger::setupHardwareComposer(const Region& dirty)
{
+ Region dirtyOut(dirty);
+
const DisplayHardware& hw(graphicPlane(0).displayHardware());
HWComposer& hwc(hw.getHwComposer());
hwc_layer_t* const cur(hwc.getLayers());
if (!cur) {
- return;
+ return dirtyOut;
}
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
@@ -909,7 +912,6 @@ void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut)
* update the per-frame h/w composer data for each layer
* and build the transparent region of the FB
*/
- Region transparent;
for (size_t i=0 ; i<count ; i++) {
const sp<LayerBase>& layer(layers[i]);
layer->setPerFrameData(&cur[i]);
@@ -918,13 +920,25 @@ void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut)
LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
if (err == NO_ERROR) {
- Region transparentDirty(*dirtyInOut);
+ Region transparent;
for (size_t i=0 ; i<count ; i++) {
- // Calculate the new transparent region and dirty region
- // - the transparent region needs to always include the layers
- // that moved from FB to OVERLAY, regardless of the dirty region
- // - the dirty region needs to be expanded to include layers
- // that moved from OVERLAY to FB.
+ // 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()) {
@@ -934,21 +948,21 @@ void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut)
bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) &&
!(cur[i].flags & HWC_SKIP_LAYER);
- if (!isOverlay && layer->isOverlay()) {
- dirtyInOut->orSelf(layer->visibleRegionScreen);
+ 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);
}
-
- if (isOverlay && !layer->isOverlay()) {
- transparentDirty.orSelf(layer->visibleRegionScreen);
- }
-
layer->setOverlay(isOverlay);
}
+
/*
* clear the area of the FB that need to be transparent
*/
- transparent.andSelf(transparentDirty);
+ // 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();
@@ -962,6 +976,7 @@ void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut)
}
}
}
+ return dirtyOut;
}
void SurfaceFlinger::composeSurfaces(const Region& dirty)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 72c29b4..126ca39 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -277,7 +277,7 @@ private:
void handleWorkList();
void handleRepaint();
void postFramebuffer();
- void setupHardwareComposer(Region* dirtyInOut);
+ Region setupHardwareComposer(const Region& dirty);
void composeSurfaces(const Region& dirty);
void repaintEverything();