Bug 1049296 - Handle Sideband stream compositing in HwcComposer2D r=mwu,nical

This commit is contained in:
Sotaro Ikeda
2016-01-18 20:52:32 -08:00
parent cb3fde01f7
commit 2e0421527a
8 changed files with 126 additions and 14 deletions

View File

@@ -119,6 +119,7 @@ namespace layers {
struct Effect; struct Effect;
struct EffectChain; struct EffectChain;
class Image; class Image;
class ImageHostOverlay;
class Layer; class Layer;
class TextureSource; class TextureSource;
class DataTextureSource; class DataTextureSource;
@@ -453,6 +454,12 @@ public:
// these methods properly. // these methods properly.
virtual nsIWidget* GetWidget() const { return nullptr; } 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 * Debug-build assertion that can be called to ensure code is running on the
* compositor thread. * compositor thread.

View File

@@ -441,6 +441,9 @@ ImageHost::SetCompositor(Compositor* aCompositor)
img.mFrontBuffer->SetCompositor(aCompositor); img.mFrontBuffer->SetCompositor(aCompositor);
} }
} }
if (mImageHostOverlay) {
mImageHostOverlay->SetCompositor(aCompositor);
}
CompositableHost::SetCompositor(aCompositor); CompositableHost::SetCompositor(aCompositor);
} }
@@ -586,6 +589,9 @@ ImageHostOverlay::ImageHostOverlay()
ImageHostOverlay::~ImageHostOverlay() ImageHostOverlay::~ImageHostOverlay()
{ {
if (mCompositor) {
mCompositor->RemoveImageHostOverlay(this);
}
MOZ_COUNT_DTOR(ImageHostOverlay); MOZ_COUNT_DTOR(ImageHostOverlay);
} }
@@ -601,6 +607,18 @@ ImageHostOverlay::IsValid(OverlaySource aOverlay)
return false; return false;
} }
void
ImageHostOverlay::SetCompositor(Compositor* aCompositor)
{
if (mCompositor && (mCompositor != aCompositor)) {
mCompositor->RemoveImageHostOverlay(this);
}
if (aCompositor) {
aCompositor->AddImageHostOverlay(this);
}
mCompositor = aCompositor;
}
void void
ImageHostOverlay::Composite(Compositor* aCompositor, ImageHostOverlay::Composite(Compositor* aCompositor,
uint32_t aFlashCounter, uint32_t aFlashCounter,
@@ -612,6 +630,8 @@ ImageHostOverlay::Composite(Compositor* aCompositor,
const gfx::Rect& aClipRect, const gfx::Rect& aClipRect,
const nsIntRegion* aVisibleRegion) const nsIntRegion* aVisibleRegion)
{ {
MOZ_ASSERT(mCompositor == aCompositor);
if (mOverlay.handle().type() == OverlayHandle::Tnull_t) { if (mOverlay.handle().type() == OverlayHandle::Tnull_t) {
return; return;
} }

View File

@@ -158,6 +158,8 @@ public:
static bool IsValid(OverlaySource aOverlay); static bool IsValid(OverlaySource aOverlay);
void SetCompositor(Compositor* aCompositor);
virtual void Composite(Compositor* aCompositor, virtual void Composite(Compositor* aCompositor,
uint32_t aFlashCounter, uint32_t aFlashCounter,
LayerComposite* aLayer, LayerComposite* aLayer,
@@ -173,6 +175,7 @@ public:
virtual gfx::IntSize GetImageSize() const; virtual gfx::IntSize GetImageSize() const;
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix); virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
protected: protected:
RefPtr<Compositor> mCompositor;
gfx::IntRect mPictureRect; gfx::IntRect mPictureRect;
OverlaySource mOverlay; OverlaySource mOverlay;
}; };

View File

@@ -809,7 +809,9 @@ LayerManagerComposite::Render(const nsIntRegion& aInvalidRegion)
if (!mTarget && !haveLayerEffects && if (!mTarget && !haveLayerEffects &&
gfxPrefs::Composer2DCompositionEnabled() && gfxPrefs::Composer2DCompositionEnabled() &&
composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot, composer2D && composer2D->HasHwc() && composer2D->TryRenderWithHwc(mRoot,
mCompositor->GetWidget(), mGeometryChanged)) mCompositor->GetWidget(),
mGeometryChanged,
mCompositor->HasImageHostOverlays()))
{ {
LayerScope::SetHWComposed(); LayerScope::SetHWComposed();
if (mFPS) { if (mFPS) {

View File

@@ -49,8 +49,10 @@ public:
* Currently, when TryRender() returns true, the entire framebuffer * Currently, when TryRender() returns true, the entire framebuffer
* must have been rendered. * must have been rendered.
*/ */
virtual bool TryRenderWithHwc(Layer* aRoot, nsIWidget* aWidget, virtual bool TryRenderWithHwc(Layer* aRoot,
bool aGeometryChanged) = 0; nsIWidget* aWidget,
bool aGeometryChanged,
bool aHasImageHostOverlays) = 0;
/** /**
* Return true if Composer2D does composition. Return false if Composer2D * Return true if Composer2D does composition. Return false if Composer2D

View File

@@ -34,6 +34,10 @@
#include "nscore.h" // for NS_IMETHOD #include "nscore.h" // for NS_IMETHOD
#include "gfxVR.h" #include "gfxVR.h"
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
#include "nsTHashtable.h" // for nsTHashtable
#endif
class nsIWidget; class nsIWidget;
namespace mozilla { namespace mozilla {
@@ -48,6 +52,11 @@ class TextureSource;
struct Effect; struct Effect;
struct EffectChain; struct EffectChain;
class GLBlitTextureImageHelper; class GLBlitTextureImageHelper;
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
class ImageHostOverlay;
#endif
/** /**
* Interface for pools of temporary gl textures for the compositor. * Interface for pools of temporary gl textures for the compositor.
* The textures are fully owned by the pool, so the latter is responsible * The textures are fully owned by the pool, so the latter is responsible
@@ -268,6 +277,29 @@ public:
virtual nsIWidget* GetWidget() const override { return mWidget; } 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; } GLContext* gl() const { return mGLContext; }
/** /**
* Clear the program state. This must be called * Clear the program state. This must be called
@@ -447,6 +479,11 @@ private:
gfx::Rect mRenderBound; gfx::Rect mRenderBound;
CompositorOGLVRObjects mVR; CompositorOGLVRObjects mVR;
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
nsTHashtable<nsPtrHashKey<ImageHostOverlay> > mImageHostOverlays;
#endif
}; };
} // namespace layers } // namespace layers

View File

@@ -123,7 +123,8 @@ HwcComposer2D::HwcComposer2D()
mRBSwapSupport = mHal->Query(HwcHALBase::QueryType::RB_SWAP); mRBSwapSupport = mHal->Query(HwcHALBase::QueryType::RB_SWAP);
} }
HwcComposer2D::~HwcComposer2D() { HwcComposer2D::~HwcComposer2D()
{
free(mList); free(mList);
} }
@@ -270,7 +271,8 @@ HwcComposer2D::ReallocLayerList()
bool bool
HwcComposer2D::PrepareLayerList(Layer* aLayer, HwcComposer2D::PrepareLayerList(Layer* aLayer,
const nsIntRect& aClip, const nsIntRect& aClip,
const Matrix& aParentTransform) const Matrix& aParentTransform,
bool aFindSidebandStreams)
{ {
// NB: we fall off this path whenever there are container layers // NB: we fall off this path whenever there are container layers
// that require intermediate surfaces. That means all the // that require intermediate surfaces. That means all the
@@ -289,12 +291,12 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
return true; 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()); LOGD("%s Layer has planar semitransparency which is unsupported by hwcomposer", aLayer->Name());
return false; return false;
} }
if (aLayer->GetMaskLayer()) { if (aLayer->GetMaskLayer() && !aFindSidebandStreams) {
LOGD("%s Layer has MaskLayer which is unsupported by hwcomposer", aLayer->Name()); LOGD("%s Layer has MaskLayer which is unsupported by hwcomposer", aLayer->Name());
return false; return false;
} }
@@ -335,7 +337,7 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
} }
if (ContainerLayer* container = aLayer->AsContainerLayer()) { if (ContainerLayer* container = aLayer->AsContainerLayer()) {
if (container->UseIntermediateSurface()) { if (container->UseIntermediateSurface() && !aFindSidebandStreams) {
LOGD("Container layer needs intermediate surface"); LOGD("Container layer needs intermediate surface");
return false; return false;
} }
@@ -343,7 +345,8 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
container->SortChildrenBy3DZOrder(children); container->SortChildrenBy3DZOrder(children);
for (uint32_t i = 0; i < children.Length(); i++) { 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 false;
} }
} }
@@ -645,6 +648,12 @@ HwcComposer2D::PrepareLayerList(Layer* aLayer,
hwcLayer.transform = colorLayer->GetColor().ToABGR(); 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())); mHwcLayerMap.AppendElement(static_cast<LayerComposite*>(aLayer->ImplData()));
mList->numHwLayers++; mList->numHwLayers++;
return true; return true;
@@ -702,6 +711,9 @@ HwcComposer2D::TryHwComposition(nsScreenGonk* aScreen)
case HWC_BLIT: case HWC_BLIT:
blitComposite = true; blitComposite = true;
break; break;
#if ANDROID_VERSION >= 21
case HWC_SIDEBAND:
#endif
case HWC_OVERLAY: { case HWC_OVERLAY: {
// HWC will compose HWC_OVERLAY layers in partial // HWC will compose HWC_OVERLAY layers in partial
// Overlay Composition, set layer composition flag // Overlay Composition, set layer composition flag
@@ -780,6 +792,15 @@ HwcComposer2D::Render(nsIWidget* aWidget)
mList->hwLayers[0].acquireFenceFd = -1; mList->hwLayers[0].acquireFenceFd = -1;
mList->hwLayers[0].releaseFenceFd = -1; mList->hwLayers[0].releaseFenceFd = -1;
mList->hwLayers[0].displayFrame = {0, 0, mScreenRect.width, mScreenRect.height}; 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); Prepare(dispSurface->lastHandle, dispSurface->GetPrevDispAcquireFd(), screen);
} }
@@ -868,7 +889,8 @@ HwcComposer2D::Render(nsIWidget* aWidget)
bool bool
HwcComposer2D::TryRenderWithHwc(Layer* aRoot, HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
nsIWidget* aWidget, nsIWidget* aWidget,
bool aGeometryChanged) bool aGeometryChanged,
bool aHasImageHostOverlays)
{ {
if (!mHal->HasHwc()) { if (!mHal->HasHwc()) {
return false; return false;
@@ -893,12 +915,28 @@ HwcComposer2D::TryRenderWithHwc(Layer* aRoot,
mScreenRect = screen->GetNaturalBounds().ToUnknownRect(); mScreenRect = screen->GetNaturalBounds().ToUnknownRect();
MOZ_ASSERT(mHwcLayerMap.IsEmpty()); MOZ_ASSERT(mHwcLayerMap.IsEmpty());
mCachedSidebandLayers.Clear();
if (!PrepareLayerList(aRoot, if (!PrepareLayerList(aRoot,
mScreenRect, mScreenRect,
gfx::Matrix())) gfx::Matrix(),
/* aFindSidebandStreams */ false))
{ {
mHwcLayerMap.Clear(); 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; return false;
} }

View File

@@ -74,7 +74,8 @@ public:
// by this composer so nothing was rendered at all // by this composer so nothing was rendered at all
virtual bool TryRenderWithHwc(layers::Layer* aRoot, virtual bool TryRenderWithHwc(layers::Layer* aRoot,
nsIWidget* aWidget, nsIWidget* aWidget,
bool aGeometryChanged) override; bool aGeometryChanged,
bool aHasImageHostOverlays) override;
virtual bool Render(nsIWidget* aWidget) override; virtual bool Render(nsIWidget* aWidget) override;
@@ -94,7 +95,8 @@ private:
bool TryHwComposition(nsScreenGonk* aScreen); bool TryHwComposition(nsScreenGonk* aScreen);
bool ReallocLayerList(); bool ReallocLayerList();
bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip, bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
const gfx::Matrix& aParentTransform); const gfx::Matrix& aParentTransform,
bool aFindSidebandStreams);
void SendtoLayerScope(); void SendtoLayerScope();
UniquePtr<HwcHALBase> mHal; UniquePtr<HwcHALBase> mHal;
@@ -108,6 +110,7 @@ private:
std::list<HwcUtils::RectVector> mVisibleRegions; std::list<HwcUtils::RectVector> mVisibleRegions;
layers::FenceHandle mPrevRetireFence; layers::FenceHandle mPrevRetireFence;
layers::FenceHandle mPrevDisplayFence; layers::FenceHandle mPrevDisplayFence;
nsTArray<HwcLayer> mCachedSidebandLayers;
nsTArray<layers::LayerComposite*> mHwcLayerMap; nsTArray<layers::LayerComposite*> mHwcLayerMap;
bool mPrepared; bool mPrepared;
bool mHasHWVsync; bool mHasHWVsync;