author | Sotaro Ikeda <sotaro.ikeda.g@gmail.com> |
Mon, 18 Jan 2016 20:52:32 -0800 | |
changeset 280424 | 9672f0dc4b626d6573f8ab3481a03c3a54f25c6e |
parent 280423 | 6f5872d14fa47ae7a0c1b411f987e4e5a4096b85 |
child 280425 | 4724e966fc73c605cc4865cfb208d5e98c9319d8 |
push id | 70446 |
push user | sikeda@mozilla.com |
push date | Tue, 19 Jan 2016 04:52:55 +0000 |
treeherder | mozilla-inbound@9672f0dc4b62 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mwu, nical |
bugs | 1049296 |
milestone | 46.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -114,16 +114,17 @@ class Matrix; class DrawTarget; } // namespace gfx namespace layers { struct Effect; struct EffectChain; class Image; +class ImageHostOverlay; class Layer; class TextureSource; class DataTextureSource; class CompositingRenderTarget; class PCompositorParent; class LayerManagerComposite; enum SurfaceInitMode @@ -448,16 +449,22 @@ public: * composite. Returns false if rendering should be aborted. */ virtual bool Ready() { return true; } // XXX I expect we will want to move mWidget into this class and implement // these methods properly. virtual nsIWidget* GetWidget() const { return nullptr; } + virtual bool HasImageHostOverlays() { return false; } + + virtual void AddImageHostOverlay(ImageHostOverlay* aOverlay) {} + + virtual void RemoveImageHostOverlay(ImageHostOverlay* aOverlay) {} + /** * Debug-build assertion that can be called to ensure code is running on the * compositor thread. */ static void AssertOnCompositorThread(); size_t GetFillRatio() { float fillRatio = 0;
--- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -436,16 +436,19 @@ ImageHost::Composite(LayerComposite* aLa void ImageHost::SetCompositor(Compositor* aCompositor) { if (mCompositor != aCompositor) { for (auto& img : mImages) { img.mFrontBuffer->SetCompositor(aCompositor); } } + if (mImageHostOverlay) { + mImageHostOverlay->SetCompositor(aCompositor); + } CompositableHost::SetCompositor(aCompositor); } void ImageHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) { aStream << aPrefix; aStream << nsPrintfCString("ImageHost (0x%p)", this).get(); @@ -581,42 +584,59 @@ ImageHost::SetImageContainer(ImageContai ImageHostOverlay::ImageHostOverlay() { MOZ_COUNT_CTOR(ImageHostOverlay); } ImageHostOverlay::~ImageHostOverlay() { + if (mCompositor) { + mCompositor->RemoveImageHostOverlay(this); + } MOZ_COUNT_DTOR(ImageHostOverlay); } /* static */ bool ImageHostOverlay::IsValid(OverlaySource aOverlay) { if ((aOverlay.handle().type() == OverlayHandle::Tint32_t) && aOverlay.handle().get_int32_t() != INVALID_OVERLAY) { return true; } else if (aOverlay.handle().type() == OverlayHandle::TGonkNativeHandle) { return true; } return false; } void +ImageHostOverlay::SetCompositor(Compositor* aCompositor) +{ + if (mCompositor && (mCompositor != aCompositor)) { + mCompositor->RemoveImageHostOverlay(this); + } + if (aCompositor) { + aCompositor->AddImageHostOverlay(this); + } + mCompositor = aCompositor; +} + +void ImageHostOverlay::Composite(Compositor* aCompositor, uint32_t aFlashCounter, LayerComposite* aLayer, EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion) { + MOZ_ASSERT(mCompositor == aCompositor); + if (mOverlay.handle().type() == OverlayHandle::Tnull_t) { return; } Color hollow(0.0f, 0.0f, 0.0f, 0.0f); aEffectChain.mPrimaryEffect = new EffectSolidColor(hollow); aEffectChain.mSecondaryEffects[EffectTypes::BLEND_MODE] = new EffectBlendMode(CompositionOp::OP_SOURCE);
--- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -153,31 +153,34 @@ protected: virtual ~ImageHostOverlay(); public: NS_INLINE_DECL_REFCOUNTING(ImageHostOverlay) ImageHostOverlay(); static bool IsValid(OverlaySource aOverlay); + void SetCompositor(Compositor* aCompositor); + virtual void Composite(Compositor* aCompositor, uint32_t aFlashCounter, LayerComposite* aLayer, EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion); virtual LayerRenderState GetRenderState(); virtual void UseOverlaySource(OverlaySource aOverlay, const gfx::IntRect& aPictureRect); virtual gfx::IntSize GetImageSize() const; virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); protected: + RefPtr<Compositor> mCompositor; gfx::IntRect mPictureRect; OverlaySource mOverlay; }; } // namespace layers } // namespace mozilla #endif
--- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -804,17 +804,19 @@ LayerManagerComposite::Render(const nsIn /** Our more efficient but less powerful alter ego, if one is available. */ RefPtr<Composer2D> composer2D; composer2D = mCompositor->GetWidget()->GetComposer2D(); // We can't use composert2D if we have layer effects if (!mTarget && !haveLayerEffects && gfxPrefs::Composer2DCompositionEnabled() && composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot, - mCompositor->GetWidget(), mGeometryChanged)) + mCompositor->GetWidget(), + mGeometryChanged, + mCompositor->HasImageHostOverlays())) { LayerScope::SetHWComposed(); if (mFPS) { double fps = mFPS->mCompositionFps.AddFrameAndGetFps(TimeStamp::Now()); if (gfxPrefs::LayersDrawFPS()) { printf_stderr("HWComposer: FPS is %g\n", fps); } }
--- a/gfx/layers/opengl/Composer2D.h +++ b/gfx/layers/opengl/Composer2D.h @@ -44,18 +44,20 @@ public: /** * Return true if |aRoot| met the implementation's criteria for fast * composition and the render was successful. Return false to fall * back on the GPU. * * Currently, when TryRender() returns true, the entire framebuffer * must have been rendered. */ - virtual bool TryRenderWithHwc(Layer* aRoot, nsIWidget* aWidget, - bool aGeometryChanged) = 0; + virtual bool TryRenderWithHwc(Layer* aRoot, + nsIWidget* aWidget, + bool aGeometryChanged, + bool aHasImageHostOverlays) = 0; /** * Return true if Composer2D does composition. Return false if Composer2D * failed the composition. */ virtual bool Render(nsIWidget* aWidget) = 0; /**
--- a/gfx/layers/opengl/CompositorOGL.h +++ b/gfx/layers/opengl/CompositorOGL.h @@ -29,30 +29,39 @@ #include "nsDebug.h" // for NS_ASSERTION, NS_WARNING #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc #include "nsTArray.h" // for nsAutoTArray, nsTArray, etc #include "nsThreadUtils.h" // for nsRunnable #include "nsXULAppAPI.h" // for XRE_GetProcessType #include "nscore.h" // for NS_IMETHOD #include "gfxVR.h" +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 +#include "nsTHashtable.h" // for nsTHashtable +#endif + class nsIWidget; namespace mozilla { namespace layers { class CompositingRenderTarget; class CompositingRenderTargetOGL; class DataTextureSource; class GLManagerCompositor; class TextureSource; struct Effect; struct EffectChain; class GLBlitTextureImageHelper; + +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 +class ImageHostOverlay; +#endif + /** * Interface for pools of temporary gl textures for the compositor. * The textures are fully owned by the pool, so the latter is responsible * calling fDeleteTextures accordingly. * Users of GetTexture receive a texture that is only valid for the duration * of the current frame. * This is primarily intended for direct texturing APIs that need to attach * shared objects (such as an EGLImage) to a gl texture. @@ -263,16 +272,39 @@ public: return LayersBackend::LAYERS_OPENGL; } virtual void Pause() override; virtual bool Resume() override; virtual nsIWidget* GetWidget() const override { return mWidget; } + virtual bool HasImageHostOverlays() override + { +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 + return mImageHostOverlays.Count() > 0; +#else + return false; +#endif + } + + virtual void AddImageHostOverlay(ImageHostOverlay* aOverlay) override + { +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 + mImageHostOverlays.PutEntry(aOverlay); +#endif + } + + virtual void RemoveImageHostOverlay(ImageHostOverlay* aOverlay) override + { +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 + mImageHostOverlays.RemoveEntry(aOverlay); +#endif + } + GLContext* gl() const { return mGLContext; } /** * Clear the program state. This must be called * before operating on the GLContext directly. */ void ResetProgram(); gfx::SurfaceFormat GetFBOFormat() const { return gfx::SurfaceFormat::R8G8B8A8; @@ -442,14 +474,19 @@ private: */ gfx::IntSize mViewportSize; ShaderProgramOGL *mCurrentProgram; gfx::Rect mRenderBound; CompositorOGLVRObjects mVR; + +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21 + nsTHashtable<nsPtrHashKey<ImageHostOverlay> > mImageHostOverlays; +#endif + }; } // namespace layers } // namespace mozilla #endif /* MOZILLA_GFX_COMPOSITOROGL_H */
--- a/widget/gonk/HwcComposer2D.cpp +++ b/widget/gonk/HwcComposer2D.cpp @@ -118,17 +118,18 @@ HwcComposer2D::HwcComposer2D() win->query(win, NATIVE_WINDOW_WIDTH, &screenSize.width); win->query(win, NATIVE_WINDOW_HEIGHT, &screenSize.height); mScreenRect = gfx::IntRect(gfx::IntPoint(0, 0), screenSize); mColorFill = mHal->Query(HwcHALBase::QueryType::COLOR_FILL); mRBSwapSupport = mHal->Query(HwcHALBase::QueryType::RB_SWAP); } -HwcComposer2D::~HwcComposer2D() { +HwcComposer2D::~HwcComposer2D() +{ free(mList); } HwcComposer2D* HwcComposer2D::GetInstance() { if (!sInstance) { #ifdef HWC_DEBUG @@ -265,17 +266,18 @@ HwcComposer2D::ReallocLayerList() mList = listrealloc; mMaxLayerCount += LAYER_COUNT_INCREMENTS; return true; } bool HwcComposer2D::PrepareLayerList(Layer* aLayer, const nsIntRect& aClip, - const Matrix& aParentTransform) + const Matrix& aParentTransform, + bool aFindSidebandStreams) { // NB: we fall off this path whenever there are container layers // that require intermediate surfaces. That means all the // GetEffective*() coordinates are relative to the framebuffer. bool fillColor = false; const nsIntRegion visibleRegion = aLayer->GetEffectiveVisibleRegion().ToUnknownRegion(); @@ -284,22 +286,22 @@ HwcComposer2D::PrepareLayerList(Layer* a } uint8_t opacity = std::min(0xFF, (int)(aLayer->GetEffectiveOpacity() * 256.0)); if (opacity == 0) { LOGD("%s Layer has zero opacity; skipping", aLayer->Name()); return true; } - if (!mHal->SupportTransparency() && opacity < 0xFF) { + if (!mHal->SupportTransparency() && opacity < 0xFF && !aFindSidebandStreams) { LOGD("%s Layer has planar semitransparency which is unsupported by hwcomposer", aLayer->Name()); return false; } - if (aLayer->GetMaskLayer()) { + if (aLayer->GetMaskLayer() && !aFindSidebandStreams) { LOGD("%s Layer has MaskLayer which is unsupported by hwcomposer", aLayer->Name()); return false; } nsIntRect clip; nsIntRect layerClip = aLayer->GetEffectiveClipRect().valueOr(ParentLayerIntRect()).ToUnknownRect(); nsIntRect* layerClipPtr = aLayer->GetEffectiveClipRect() ? &layerClip : nullptr; if (!HwcUtils::CalculateClipRect(aParentTransform, @@ -330,25 +332,26 @@ HwcComposer2D::PrepareLayerList(Layer* a Matrix layerBufferTransform; if (!aLayer->GetEffectiveTransformForBuffer().Is2D(&layerBufferTransform) || !layerBufferTransform.PreservesAxisAlignedRectangles()) { LOGD("Layer EffectiveTransformForBuffer has a 3D transform or a non-square angle rotation"); return false; } if (ContainerLayer* container = aLayer->AsContainerLayer()) { - if (container->UseIntermediateSurface()) { + if (container->UseIntermediateSurface() && !aFindSidebandStreams) { LOGD("Container layer needs intermediate surface"); return false; } nsAutoTArray<Layer*, 12> children; container->SortChildrenBy3DZOrder(children); for (uint32_t i = 0; i < children.Length(); i++) { - if (!PrepareLayerList(children[i], clip, layerTransform)) { + if (!PrepareLayerList(children[i], clip, layerTransform, aFindSidebandStreams) && + !aFindSidebandStreams) { return false; } } return true; } LayerRenderState state = aLayer->GetRenderState(); @@ -640,16 +643,22 @@ HwcComposer2D::PrepareLayerList(Layer* a ColorLayer* colorLayer = aLayer->AsColorLayer(); if (colorLayer->GetColor().a < 1.0) { LOGD("Color layer has semitransparency which is unsupported"); return false; } hwcLayer.transform = colorLayer->GetColor().ToABGR(); } +#if ANDROID_VERSION >= 21 + if (aFindSidebandStreams && hwcLayer.compositionType == HWC_SIDEBAND) { + mCachedSidebandLayers.AppendElement(hwcLayer); + } +#endif + mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData())); mList->numHwLayers++; return true; } #if ANDROID_VERSION >= 17 bool @@ -697,16 +706,19 @@ HwcComposer2D::TryHwComposition(nsScreen for (int k=0; k < idx; k++) { switch (mList->hwLayers[k].compositionType) { case HWC_FRAMEBUFFER: gpuComposite = true; break; case HWC_BLIT: blitComposite = true; break; +#if ANDROID_VERSION >= 21 + case HWC_SIDEBAND: +#endif case HWC_OVERLAY: { // HWC will compose HWC_OVERLAY layers in partial // Overlay Composition, set layer composition flag // on mapped LayerComposite to skip GPU composition mHwcLayerMap[k]->SetLayerComposited(true); uint8_t opacity = std::min(0xFF, (int)(mHwcLayerMap[k]->GetLayer()->GetEffectiveOpacity() * 256.0)); if ((mList->hwLayers[k].hints & HWC_HINT_CLEAR_FB) && @@ -775,16 +787,25 @@ HwcComposer2D::Render(nsIWidget* aWidget mList->numHwLayers = 2; mList->hwLayers[0].hints = 0; mList->hwLayers[0].compositionType = HWC_FRAMEBUFFER; mList->hwLayers[0].flags = HWC_SKIP_LAYER; mList->hwLayers[0].backgroundColor = {0}; mList->hwLayers[0].acquireFenceFd = -1; mList->hwLayers[0].releaseFenceFd = -1; mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height}; + +#if ANDROID_VERSION >= 21 + // Prepare layers for sideband streams + const uint32_t len = mCachedSidebandLayers.Length(); + for (uint32_t i = 0; i < len; ++i) { + ++mList->numHwLayers; + mList->hwLayers[i+1] = mCachedSidebandLayers[i]; + } +#endif Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd(), screen); } // GPU or partial HWC Composition return Commit(screen); } void @@ -863,17 +884,18 @@ HwcComposer2D::Render(nsIWidget* aWidget nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen(); return GetGonkDisplay()->SwapBuffers(screen->GetEGLDisplay(), screen->GetEGLSurface()); } #endif bool HwcComposer2D::TryRenderWithHwc(Layer* aRoot, nsIWidget* aWidget, - bool aGeometryChanged) + bool aGeometryChanged, + bool aHasImageHostOverlays) { if (!mHal->HasHwc()) { return false; } nsScreenGonk* screen = static_cast<nsWindow*>(aWidget)->GetScreen(); if (mList) { @@ -888,22 +910,38 @@ HwcComposer2D::TryRenderWithHwc(Layer* a } // XXX: The clear() below means all rect vectors will be have to be // reallocated. We may want to avoid this if possible mVisibleRegions.clear(); mScreenRect = screen->GetNaturalBounds().ToUnknownRect(); MOZ_ASSERT(mHwcLayerMap.IsEmpty()); + mCachedSidebandLayers.Clear(); if (!PrepareLayerList(aRoot, mScreenRect, - gfx::Matrix())) + gfx::Matrix(), + /* aFindSidebandStreams */ false)) { mHwcLayerMap.Clear(); - LOGD("Render aborted. Nothing was drawn to the screen"); + LOGD("Render aborted. Fallback to GPU Composition"); + if (aHasImageHostOverlays) { + LOGD("Prepare layers of SidebandStreams"); + // Failed to create a layer list for hwc. But we need the list + // only for handling sideband streams. Traverse layer tree without + // some early returns to make sure we can find all the layers. + // It is the best wrong thing that we can do. + PrepareLayerList(aRoot, + mScreenRect, + gfx::Matrix(), + /* aFindSidebandStreams */ true); + // Reset mPrepared to false, since we already fell back to + // gpu composition. + mPrepared = false; + } return false; } // Send data to LayerScope for debugging SendtoLayerScope(); if (!TryHwComposition(screen)) { LOGD("Full HWC Composition failed. Fallback to GPU Composition or partial OVERLAY Composition");
--- a/widget/gonk/HwcComposer2D.h +++ b/widget/gonk/HwcComposer2D.h @@ -69,17 +69,18 @@ public: static HwcComposer2D* GetInstance(); // Returns TRUE if the container has been succesfully rendered // Returns FALSE if the container cannot be fully rendered // by this composer so nothing was rendered at all virtual bool TryRenderWithHwc(layers::Layer* aRoot, nsIWidget* aWidget, - bool aGeometryChanged) override; + bool aGeometryChanged, + bool aHasImageHostOverlays) override; virtual bool Render(nsIWidget* aWidget) override; virtual bool HasHwc() override { return mHal->HasHwc(); } bool EnableVsync(bool aEnable); bool RegisterHwcEventCallback(); void Vsync(int aDisplay, int64_t aTimestamp); @@ -89,30 +90,32 @@ public: private: void Reset(); void Prepare(buffer_handle_t dispHandle, int fence, nsScreenGonk* screen); bool Commit(nsScreenGonk* aScreen); bool TryHwComposition(nsScreenGonk* aScreen); bool ReallocLayerList(); bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip, - const gfx::Matrix& aParentTransform); + const gfx::Matrix& aParentTransform, + bool aFindSidebandStreams); void SendtoLayerScope(); UniquePtr<HwcHALBase> mHal; HwcList* mList; nsIntRect mScreenRect; int mMaxLayerCount; bool mColorFill; bool mRBSwapSupport; //Holds all the dynamically allocated RectVectors needed //to render the current frame std::list<HwcUtils::RectVector> mVisibleRegions; layers::FenceHandle mPrevRetireFence; layers::FenceHandle mPrevDisplayFence; + nsTArray<HwcLayer> mCachedSidebandLayers; nsTArray<layers::LayerComposite*> mHwcLayerMap; bool mPrepared; bool mHasHWVsync; layers::CompositorParent* mCompositorParent; Mutex mLock; }; } // namespace mozilla