diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 603fb607b..dfc531e2f 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 d20f06ac8..ee5042838 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 4a3a8ea6c..25765763d 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 >& 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(); - } - - status_t err = NO_ERROR; - const Vector< sp >& layers(mVisibleLayersSortedByZ); - size_t count = layers.size(); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); HWComposer& hwc(hw.getHwComposer()); hwc_layer_t* const cur(hwc.getLayers()); + if (!cur) { + return; + } - LOGE_IF(cur && hwc.getNumLayers() != count, + const Vector< sp >& 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); @@ -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& 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& 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& layer(layers[i]); - if (layer->isOpaque()) { - transparent.orSelf(layer->visibleRegionScreen); - } - } + if (err == NO_ERROR) { + Region transparentDirty(*dirtyInOut); + for (size_t i=0 ; i& 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()) { + dirtyInOut->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); + 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 >& layers(mVisibleLayersSortedByZ); + size_t count = layers.size(); for (size_t i=0 ; i& 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 5f8eb0868..72c29b414 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();