diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index 977bc953d9ec..8bdbd855343f 100644 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -198,7 +198,13 @@ ContainerRender(ContainerT* aContainer, continue; } - layerToRender->RenderLayer(childOffset, clipRect); + if (layerToRender->HasLayerBeenComposited()) { + // Composer2D will compose this layer so skip GPU composition + // this time & reset composition flag for next composition phase + layerToRender->SetLayerComposited(false); + } else { + layerToRender->RenderLayer(childOffset, clipRect); + } // invariant: our GL context should be current here, I don't think we can // assert it though } diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index 524228ab515e..a496d9b27814 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -726,6 +726,7 @@ LayerComposite::LayerComposite(LayerManagerComposite *aManager) , mUseShadowClipRect(false) , mShadowTransformSetByAnimation(false) , mDestroyed(false) + , mLayerComposited(false) { } LayerComposite::~LayerComposite() diff --git a/gfx/layers/composite/LayerManagerComposite.h b/gfx/layers/composite/LayerManagerComposite.h index d3dc14a0e9c9..fa32b5ac35df 100644 --- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -381,12 +381,18 @@ public: mShadowTransformSetByAnimation = aSetByAnimation; } + void SetLayerComposited(bool value) + { + mLayerComposited = value; + } + // These getters can be used anytime. float GetShadowOpacity() { return mShadowOpacity; } const nsIntRect* GetShadowClipRect() { return mUseShadowClipRect ? &mShadowClipRect : nullptr; } const nsIntRegion& GetShadowVisibleRegion() { return mShadowVisibleRegion; } const gfx3DMatrix& GetShadowTransform() { return mShadowTransform; } bool GetShadowTransformSetByAnimation() { return mShadowTransformSetByAnimation; } + bool HasLayerBeenComposited() { return mLayerComposited; } protected: gfx3DMatrix mShadowTransform; @@ -398,6 +404,7 @@ protected: bool mUseShadowClipRect; bool mShadowTransformSetByAnimation; bool mDestroyed; + bool mLayerComposited; }; diff --git a/widget/gonk/HwcComposer2D.cpp b/widget/gonk/HwcComposer2D.cpp index f46cd0347a2c..8f861b2bfb0f 100644 --- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -434,6 +434,7 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer, hwcLayer.transform = colorLayer->GetColor().Packed(); } + mHwcLayerMap.AppendElement(static_cast(aLayer->ImplData())); mList->numHwLayers++; return true; } @@ -461,13 +462,29 @@ HwcComposer2D::TryHwComposition() Prepare(fbsurface->lastHandle, -1); + bool fullHwcComposite = true; for (int j = 0; j < idx; j++) { if (mList->hwLayers[j].compositionType == HWC_FRAMEBUFFER) { + // After prepare, if there is an HWC_FRAMEBUFFER layer, + // it means full HWC Composition is not possible this time LOGD("GPU or Partial HWC Composition"); - return false; + fullHwcComposite = false; + break; } } + if (!fullHwcComposite) { + for (int k=0; k < idx; k++) { + if (mList->hwLayers[k].compositionType == HWC_OVERLAY) { + // HWC will compose HWC_OVERLAY layers in partial + // HWC Composition, so set layer composition flag + // on mapped LayerComposite to skip GPU composition + mHwcLayerMap[k]->SetLayerComposited(true); + } + } + return false; + } + // Full HWC Composition Commit(); @@ -554,28 +571,26 @@ HwcComposer2D::Commit() int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays); - for (int i = 0; i <= MAX_HWC_LAYERS; i++) { - if (mPrevRelFd[i] <= 0) { - break; + if (!mPrevReleaseFds.IsEmpty()) { + // Wait for previous retire Fence to signal. + // Denotes contents on display have been replaced. + // For buffer-sync, framework should not over-write + // prev buffers until we close prev releaseFenceFds + sp fence = new Fence(mPrevReleaseFds[0]); + if (fence->wait(1000) == -ETIME) { + LOGE("Wait timed-out for retireFenceFd %d", mPrevReleaseFds[0]); } - if (!i) { - // Wait for previous retire Fence to signal. - // Denotes contents on display have been replaced. - // For buffer-sync, framework should not over-write - // prev buffers until we close prev releaseFenceFds - sp fence = new Fence(mPrevRelFd[i]); - if (fence->wait(1000) == -ETIME) { - LOGE("Wait timed-out for retireFenceFd %d", mPrevRelFd[i]); - } + + for (int i = 0; i < mPrevReleaseFds.Length(); i++) { + close(mPrevReleaseFds[i]); } - close(mPrevRelFd[i]); - mPrevRelFd[i] = -1; + mPrevReleaseFds.Clear(); } - mPrevRelFd[0] = mList->retireFenceFd; - for (uint32_t j = 0; j < (mList->numHwLayers - 1); j++) { + mPrevReleaseFds.AppendElement(mList->retireFenceFd); + for (uint32_t j=0; j < (mList->numHwLayers - 1); j++) { if (mList->hwLayers[j].compositionType == HWC_OVERLAY) { - mPrevRelFd[j + 1] = mList->hwLayers[j].releaseFenceFd; + mPrevReleaseFds.AppendElement(mList->hwLayers[j].releaseFenceFd); mList->hwLayers[j].releaseFenceFd = -1; } } @@ -609,12 +624,14 @@ HwcComposer2D::TryRender(Layer* aRoot, MOZ_ASSERT(Initialized()); if (mList) { mList->numHwLayers = 0; + mHwcLayerMap.Clear(); } // XXX: The clear() below means all rect vectors will be have to be // reallocated. We may want to avoid this if possible mVisibleRegions.clear(); + MOZ_ASSERT(mHwcLayerMap.IsEmpty()); if (!PrepareLayerList(aRoot, mScreenRect, gfxMatrix(), diff --git a/widget/gonk/HwcComposer2D.h b/widget/gonk/HwcComposer2D.h index 625024e53fab..532ad5d00660 100644 --- a/widget/gonk/HwcComposer2D.h +++ b/widget/gonk/HwcComposer2D.h @@ -24,8 +24,6 @@ #include -#define MAX_HWC_LAYERS 15 - namespace mozilla { namespace layers { @@ -83,7 +81,8 @@ private: //Holds all the dynamically allocated RectVectors needed //to render the current frame std::list mVisibleRegions; - int mPrevRelFd[MAX_HWC_LAYERS + 1]; + nsTArray mPrevReleaseFds; + nsTArray mHwcLayerMap; }; } // namespace mozilla