diff options
author | Mathias Agopian <mathias@google.com> | 2011-09-09 01:47:48 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2011-09-09 01:47:48 -0700 |
commit | 0a5abdb3161510d6f0c88fbe75140325620ac366 (patch) | |
tree | b70182917c44f7b469494719c5197196f1fe7d72 /services/surfaceflinger | |
parent | 5bd1b2794b227e25fbd7e4c919bcefc3510e0761 (diff) | |
download | frameworks_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.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 53 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 2 |
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(); |