diff options
author | Mathias Agopian <mathias@google.com> | 2011-09-08 18:31:55 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2011-09-08 22:43:01 -0700 |
commit | 4bacc9dc674792c745f362962883a19f4a35c88c (patch) | |
tree | 13183bf0ce05fb6c5fb6890a7ba74584e5d81b7d /services/surfaceflinger | |
parent | 2295cc77c72d451e7a1c9ec48f120a8e73651b6d (diff) | |
download | frameworks_base-4bacc9dc674792c745f362962883a19f4a35c88c.zip frameworks_base-4bacc9dc674792c745f362962883a19f4a35c88c.tar.gz frameworks_base-4bacc9dc674792c745f362962883a19f4a35c88c.tar.bz2 |
Fix an issue is SF that caused drawing artifacts when hwc changed mode
we were not redrawing and/or clearing the FB properly when
hwc moved a layer from/to FB to/from OVERLAY.
In these cases we needed to expand the dirty region to include
the layer that changed mode.
Also split composeSurfaces() which was becoming quite large.
Change-Id: Id6fa1acfc4ff694037fddf7efd037a4405732073
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r-- | services/surfaceflinger/LayerBase.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 9 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 127 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 1 |
4 files changed, 85 insertions, 60 deletions
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 603fb60..dfc531e 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -344,6 +344,14 @@ void LayerBase::setPerFrameData(hwc_layer_t* hwcl) { hwcl->handle = NULL; } +void LayerBase::setOverlay(bool inOverlay) { + mInOverlay = inOverlay; +} + +bool LayerBase::isOverlay() const { + return mInOverlay; +} + void LayerBase::setFiltering(bool filtering) { mFiltering = filtering; 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 @@ public: 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 @@ private: // 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..2576576 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -817,20 +817,6 @@ void SurfaceFlinger::handleWorkList() 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); @@ -891,29 +877,26 @@ void SurfaceFlinger::handleRepaint() } // compose all surfaces + setupHardwareComposer(&mDirtyRegion); composeSurfaces(mDirtyRegion); // clear the dirty regions mDirtyRegion.clear(); } -void SurfaceFlinger::composeSurfaces(const Region& dirty) +void SurfaceFlinger::setupHardwareComposer(Region* dirtyInOut) { - 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()); + if (!cur) { + return; } - status_t err = NO_ERROR; const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); size_t count = layers.size(); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); - HWComposer& hwc(hw.getHwComposer()); - hwc_layer_t* const cur(hwc.getLayers()); - - LOGE_IF(cur && hwc.getNumLayers() != count, + LOGE_IF(hwc.getNumLayers() != count, "HAL number of layers (%d) doesn't match surfaceflinger (%d)", hwc.getNumLayers(), count); @@ -927,56 +910,82 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) * 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]); + } + status_t err = hwc.prepare(); + LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); + + if (err == NO_ERROR) { + Region transparentDirty(*dirtyInOut); 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. + const sp<LayerBase>& layer(layers[i]); - layer->setPerFrameData(&cur[i]); - } - err = hwc.prepare(); - LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); + if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) { + transparent.orSelf(layer->visibleRegionScreen); + } - 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); - } - } + bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) && + !(cur[i].flags & HWC_SKIP_LAYER); + + if (!isOverlay && layer->isOverlay()) { + dirtyInOut->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); - } + 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); + 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); } } } +} +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()) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 5f8eb08..72c29b4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -277,6 +277,7 @@ private: void handleWorkList(); void handleRepaint(); void postFramebuffer(); + void setupHardwareComposer(Region* dirtyInOut); void composeSurfaces(const Region& dirty); void repaintEverything(); |