diff options
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r-- | services/surfaceflinger/DisplayHardware/DisplayHardware.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.cpp | 53 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayHardware/HWComposer.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/LayerBase.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 114 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 4 |
7 files changed, 120 insertions, 63 deletions
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h index 40a6f1e..f02c954 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h +++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h @@ -84,9 +84,10 @@ public: status_t compositionComplete() const; - Rect bounds() const { + Rect getBounds() const { return Rect(mWidth, mHeight); } + inline Rect bounds() const { return getBounds(); } // only for debugging int getCurrentBufferIndex() const; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index c9567d5..e707bdc 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -40,6 +40,7 @@ namespace android { HWComposer::HWComposer(const sp<SurfaceFlinger>& flinger) : mFlinger(flinger), mModule(0), mHwc(0), mList(0), mCapacity(0), + mNumOVLayers(0), mNumFBLayers(0), mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE) { int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule); @@ -98,9 +99,40 @@ status_t HWComposer::createWorkList(size_t numLayers) { status_t HWComposer::prepare() const { int err = mHwc->prepare(mHwc, mList); + if (err == NO_ERROR) { + size_t numOVLayers = 0; + size_t numFBLayers = 0; + size_t count = mList->numHwLayers; + for (size_t i=0 ; i<count ; i++) { + hwc_layer& l(mList->hwLayers[i]); + if (l.flags & HWC_SKIP_LAYER) { + l.compositionType = HWC_FRAMEBUFFER; + } + switch (l.compositionType) { + case HWC_OVERLAY: + numOVLayers++; + break; + case HWC_FRAMEBUFFER: + numFBLayers++; + break; + } + } + mNumOVLayers = numOVLayers; + mNumFBLayers = numFBLayers; + } return (status_t)err; } +size_t HWComposer::getLayerCount(int type) const { + switch (type) { + case HWC_OVERLAY: + return mNumOVLayers; + case HWC_FRAMEBUFFER: + return mNumFBLayers; + } + return 0; +} + status_t HWComposer::commit() const { int err = mHwc->set(mHwc, mDpy, mSur, mList); if (mList) { @@ -143,18 +175,29 @@ void HWComposer::dump(String8& result, char* buffer, size_t SIZE, snprintf(buffer, SIZE, " numHwLayers=%u, flags=%08x\n", mList->numHwLayers, mList->flags); result.append(buffer); - + result.append( + " type | hints | flags | tr | blend | format | source rectangle | crop rectangle name \n" + "-----------+----------+----------+----+-------+----------+---------------------------+--------------------------------\n"); + // " ________ | ________ | ________ | __ | _____ | ________ | [_____,_____,_____,_____] | [_____,_____,_____,_____] 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] %s\n", + const sp<LayerBase> layer(visibleLayersSortedByZ[i]); + int32_t format = -1; + if (layer->getLayer() != NULL) { + const sp<GraphicBuffer>& buffer(layer->getLayer()->getActiveBuffer()); + if (buffer != NULL) { + format = buffer->getPixelFormat(); + } + } + snprintf(buffer, SIZE, + " %8s | %08x | %08x | %02x | %05x | %08x | [%5d,%5d,%5d,%5d] | [%5d,%5d,%5d,%5d] %s\n", l.compositionType ? "OVERLAY" : "FB", - l.hints, l.flags, l.transform, l.blending, + l.hints, l.flags, l.transform, l.blending, format, l.sourceCrop.left, l.sourceCrop.top, l.sourceCrop.right, l.sourceCrop.bottom, l.displayFrame.left, l.displayFrame.top, l.displayFrame.right, l.displayFrame.bottom, - visibleLayersSortedByZ[i]->getName().string()); + layer->getName().string()); result.append(buffer); } - } if (mHwc && mHwc->common.version >= 1 && mHwc->dump) { mHwc->dump(mHwc, buffer, SIZE); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 8758a80..aa8ebe1 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -64,6 +64,9 @@ public: size_t getNumLayers() const; hwc_layer_t* getLayers() const; + // updated in preapre() + size_t getLayerCount(int type) const; + // for debugging void dump(String8& out, char* scratch, size_t SIZE, const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const; @@ -81,6 +84,8 @@ private: hwc_composer_device_t* mHwc; hwc_layer_list_t* mList; size_t mCapacity; + mutable size_t mNumOVLayers; + mutable size_t mNumFBLayers; hwc_display_t mDpy; hwc_surface_t mSur; cb_context mCBContext; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d06a35f..ff389ae 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -73,12 +73,14 @@ public: virtual bool isSecure() const { return mSecure; } virtual bool isProtected() const; virtual void onRemoved(); + virtual sp<Layer> getLayer() const { return const_cast<Layer*>(this); } // LayerBaseClient interface virtual wp<IBinder> getSurfaceTextureBinder() const; // only for debugging inline const sp<FreezeLock>& getFreezeLock() const { return mFreezeLock; } + inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; } protected: virtual void onFirstRef(); diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h index ee50428..a14b397 100644 --- a/services/surfaceflinger/LayerBase.h +++ b/services/surfaceflinger/LayerBase.h @@ -46,6 +46,7 @@ class Client; class DisplayHardware; class GraphicBuffer; class GraphicPlane; +class Layer; class LayerBaseClient; class SurfaceFlinger; @@ -105,6 +106,7 @@ public: void invalidate(); virtual sp<LayerBaseClient> getLayerBaseClient() const { return 0; } + virtual sp<Layer> getLayer() const { return 0; } virtual const char* getTypeId() const { return "LayerBase"; } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index df13640..0ef03bb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -469,14 +469,14 @@ bool SurfaceFlinger::threadLoop() void SurfaceFlinger::postFramebuffer() { - if (!mInvalidRegion.isEmpty()) { + if (!mSwapRegion.isEmpty()) { const DisplayHardware& hw(graphicPlane(0).displayHardware()); const nsecs_t now = systemTime(); mDebugInSwapBuffers = now; - hw.flip(mInvalidRegion); + hw.flip(mSwapRegion); mLastSwapBufferTime = systemTime() - now; mDebugInSwapBuffers = 0; - mInvalidRegion.clear(); + mSwapRegion.clear(); } } @@ -834,7 +834,7 @@ void SurfaceFlinger::handleWorkList() void SurfaceFlinger::handleRepaint() { // compute the invalid region - mInvalidRegion.orSelf(mDirtyRegion); + mSwapRegion.orSelf(mDirtyRegion); if (UNLIKELY(mDebugRegion)) { debugFlashRegions(); @@ -855,7 +855,7 @@ void SurfaceFlinger::handleRepaint() if (flags & DisplayHardware::SWAP_RECTANGLE) { // TODO: we really should be able to pass a region to // SWAP_RECTANGLE so that we don't have to redraw all this. - mDirtyRegion.set(mInvalidRegion.bounds()); + mDirtyRegion.set(mSwapRegion.bounds()); } else { // in the BUFFER_PRESERVED case, obviously, we can update only // what's needed and nothing more. @@ -868,32 +868,29 @@ void SurfaceFlinger::handleRepaint() // (pushed to the framebuffer). // This is needed because PARTIAL_UPDATES only takes one // rectangle instead of a region (see DisplayHardware::flip()) - mDirtyRegion.set(mInvalidRegion.bounds()); + mDirtyRegion.set(mSwapRegion.bounds()); } else { // we need to redraw everything (the whole screen) mDirtyRegion.set(hw.bounds()); - mInvalidRegion = mDirtyRegion; + mSwapRegion = mDirtyRegion; } } - Region expandDirty = setupHardwareComposer(mDirtyRegion); - mDirtyRegion.orSelf(expandDirty); - mInvalidRegion.orSelf(mDirtyRegion); + setupHardwareComposer(mDirtyRegion); composeSurfaces(mDirtyRegion); - // clear the dirty regions + // update the swap region and clear the dirty region + mSwapRegion.orSelf(mDirtyRegion); mDirtyRegion.clear(); } -Region SurfaceFlinger::setupHardwareComposer(const Region& dirty) +void SurfaceFlinger::setupHardwareComposer(Region& dirtyInOut) { - Region dirtyOut(dirty); - const DisplayHardware& hw(graphicPlane(0).displayHardware()); HWComposer& hwc(hw.getHwComposer()); hwc_layer_t* const cur(hwc.getLayers()); if (!cur) { - return dirtyOut; + return; } const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); @@ -916,53 +913,62 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty) const sp<LayerBase>& layer(layers[i]); layer->setPerFrameData(&cur[i]); } + const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER); status_t err = hwc.prepare(); LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err)); 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); - } + // 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 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. + // + // Note also that there is a special case when switching from + // "no layers in FB" to "some layers in FB", where we need to redraw + // the entire FB, since some areas might contain uninitialized + // data. + // + // 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. - bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER) && - !(cur[i].flags & HWC_SKIP_LAYER); + Region transparent; - 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 (!fbLayerCount && hwc.getLayerCount(HWC_FRAMEBUFFER)) { + transparent.set(hw.getBounds()); + dirtyInOut = transparent; + } else { + for (size_t i=0 ; i<count ; i++) { + const sp<LayerBase>& layer(layers[i]); + if ((cur[i].hints & HWC_HINT_CLEAR_FB) && layer->isOpaque()) { + transparent.orSelf(layer->visibleRegionScreen); + } + bool isOverlay = (cur[i].compositionType != HWC_FRAMEBUFFER); + 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. + dirtyInOut.orSelf(layer->visibleRegionScreen); + } + layer->setOverlay(isOverlay); } - layer->setOverlay(isOverlay); + // don't erase stuff outside the dirty region + transparent.andSelf(dirtyInOut); } - /* * 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(); @@ -976,7 +982,6 @@ Region SurfaceFlinger::setupHardwareComposer(const Region& dirty) } } } - return dirtyOut; } void SurfaceFlinger::composeSurfaces(const Region& dirty) @@ -997,8 +1002,7 @@ void SurfaceFlinger::composeSurfaces(const Region& dirty) const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ); size_t count = layers.size(); for (size_t i=0 ; i<count ; i++) { - if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER) && - !(cur[i].flags & HWC_SKIP_LAYER)) { + if (cur && (cur[i].compositionType != HWC_FRAMEBUFFER)) { continue; } const sp<LayerBase>& layer(layers[i]); @@ -1014,7 +1018,7 @@ void SurfaceFlinger::debugFlashRegions() const DisplayHardware& hw(graphicPlane(0).displayHardware()); const uint32_t flags = hw.getFlags(); const int32_t height = hw.getHeight(); - if (mInvalidRegion.isEmpty()) { + if (mSwapRegion.isEmpty()) { return; } @@ -1051,7 +1055,7 @@ void SurfaceFlinger::debugFlashRegions() glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } - hw.flip(mInvalidRegion); + hw.flip(mSwapRegion); if (mDebugRegion > 1) usleep(mDebugRegion * 1000); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 126ca39..d7f005f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -277,7 +277,7 @@ private: void handleWorkList(); void handleRepaint(); void postFramebuffer(); - Region setupHardwareComposer(const Region& dirty); + void setupHardwareComposer(Region& dirtyInOut); void composeSurfaces(const Region& dirty); void repaintEverything(); @@ -358,7 +358,7 @@ private: State mDrawingState; Region mDirtyRegion; Region mDirtyRegionRemovedLayer; - Region mInvalidRegion; + Region mSwapRegion; Region mWormholeRegion; bool mVisibleRegionsDirty; bool mHwWorkListDirty; |