Bug 1415586 - share mask image (WIP)
MozReview-Commit-ID: HBSZjC4zdVO
--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -14,16 +14,17 @@
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/layers/IpcResourceUpdateQueue.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/UpdateImageHelper.h"
#include "gfxEnv.h"
#include "nsDisplayListInvalidation.h"
+#include "SVGObserverUtils.h"
#include "WebRenderCanvasRenderer.h"
#include "LayersLogging.h"
#include "LayerTreeInvalidation.h"
namespace mozilla {
namespace layers {
using namespace gfx;
@@ -58,16 +59,19 @@ WebRenderCommandBuilder::BuildWebRenderC
wr::IpcResourceUpdateQueue& aResourceUpdates,
nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder,
WebRenderScrollData& aScrollData,
wr::LayoutSize& aContentSize)
{
{ // scoping for StackingContextHelper RAII
+ // Reset mask list
+ //mClipCacheManager.mMaskList.clear();
+
StackingContextHelper sc;
mParentCommands.Clear();
aScrollData = WebRenderScrollData(mManager);
MOZ_ASSERT(mLayerScrollData.empty());
mLastCanvasDatas.Clear();
mLastAsr = nullptr;
mScrollingHelper.BeginBuild(mManager, aBuilder);
@@ -650,33 +654,85 @@ WebRenderCommandBuilder::GenerateFallbac
fallbackData->SetBounds(paintBounds);
MOZ_ASSERT(fallbackData->GetKey());
return fallbackData.forget();
}
Maybe<wr::WrImageMask>
-WebRenderCommandBuilder::BuildWrMaskImage(nsDisplayItem* aItem,
+WebRenderCommandBuilder::BuildWrMaskImage(nsDisplayMask* aItem,
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder,
- const LayoutDeviceRect& aBounds)
+ const LayoutDeviceRect& aBounds,
+ MaskImage*& aMaskCache,
+ bool& aCached)
{
- LayoutDeviceRect imageRect;
- RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aResources,
- aSc, aDisplayListBuilder,
- imageRect);
- if (!fallbackData) {
- return Nothing();
+
+ nsIFrame* frame = aItem->Frame();
+
+ //maskimage.opacity = aItem->mHandleOpacity ? frame->StyleEffects()->mOpacity;
+
+ nsIFrame* firstFrame =
+ nsLayoutUtils::FirstContinuationOrIBSplitSibling(frame);
+
+ SVGObserverUtils::EffectProperties effectProperties =
+ SVGObserverUtils::GetEffectProperties(firstFrame);
+ const nsStyleSVGReset *svgReset = firstFrame->StyleSVGReset();
+
+ wr::ImageKey key;
+ bool cached = false;
+ RefPtr<MaskImage> maskimage;
+
+ if (svgReset->mClipPath.GetType() == StyleShapeSourceType::Shape) {
+ maskimage = new MaskImage();
+ //maskimage.opacity = aItem->mHandleOpacity ? frame->StyleEffects()->mOpacity : 1.0;
+ maskimage->opacity = frame->StyleEffects()->mOpacity;
+ maskimage->type = svgReset->mClipPath.GetType();
+ const UniquePtr<StyleBasicShape>& basicShape = svgReset->mClipPath.GetBasicShape();
+ maskimage->basicShape = new StyleBasicShape(StyleBasicShapeType::Polygon);
+ *(maskimage->basicShape) = *basicShape;
+
+ for (auto mask: mClipCacheManager.mMaskList) {
+ if (*mask->basicShape == *maskimage->basicShape) {
+ aMaskCache = mask.get();
+ aCached = true;
+ key = mask->key;
+ cached = true;
+ break;
+ }
+ }
+ }
+
+ if (!cached) {
+ if (XRE_IsContentProcess()) {
+ printf_stderr("@@@not cahced\n");
+ }
+ LayoutDeviceRect imageRect;
+ RefPtr<WebRenderFallbackData> fallbackData = GenerateFallbackData(aItem, aBuilder, aResources,
+ aSc, aDisplayListBuilder,
+ imageRect);
+
+ if (!fallbackData) {
+ return Nothing();
+ }
+
+ key = fallbackData->GetKey().value();
+ if (maskimage) {
+ aMaskCache = maskimage.get();
+ maskimage->key = key;
+ fallbackData->SetMaskCache(maskimage);
+ mClipCacheManager.mMaskList.push_back(maskimage.forget());
+ }
}
wr::WrImageMask imageMask;
- imageMask.image = fallbackData->GetKey().value();
+ imageMask.image = key;
imageMask.rect = aSc.ToRelativeLayoutRect(aBounds);
imageMask.repeat = false;
return Some(imageMask);
}
bool
WebRenderCommandBuilder::PushItemAsImage(nsDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
--- a/gfx/layers/wr/WebRenderCommandBuilder.h
+++ b/gfx/layers/wr/WebRenderCommandBuilder.h
@@ -9,32 +9,53 @@
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/layers/ScrollingLayersHelper.h"
#include "mozilla/layers/WebRenderMessages.h"
#include "mozilla/layers/WebRenderScrollData.h"
#include "mozilla/layers/WebRenderUserData.h"
#include "nsDisplayList.h"
#include "nsIFrame.h"
+#include <list>
namespace mozilla {
namespace layers {
class CanvasLayer;
class ImageClient;
class ImageContainer;
class WebRenderBridgeChild;
class WebRenderCanvasData;
class WebRenderCanvasRendererAsync;
class WebRenderImageData;
class WebRenderFallbackData;
class WebRenderParentCommand;
class WebRenderUserData;
+class MaskImage {
+ NS_INLINE_DECL_REFCOUNTING(MaskImage)
+public:
+ float opacity;
+ StyleShapeSourceType type;
+ StyleBasicShape* basicShape;
+ wr::ImageKey key;
+ wr::WrClipId clipId;
+private:
+ ~MaskImage() {
+ delete basicShape;
+ }
+};
+
+class ClipCacheManager {
+public:
+ std::list<RefPtr<MaskImage>> mMaskList;
+
+};
+
class WebRenderCommandBuilder {
typedef nsTHashtable<nsRefPtrHashKey<WebRenderUserData>> WebRenderUserDataRefTable;
typedef nsTHashtable<nsRefPtrHashKey<WebRenderCanvasData>> CanvasDataSet;
public:
explicit WebRenderCommandBuilder(WebRenderLayerManager* aManager)
: mManager(aManager)
, mLastAsr(nullptr)
@@ -65,22 +86,24 @@ public:
bool PushImage(nsDisplayItem* aItem,
ImageContainer* aContainer,
mozilla::wr::DisplayListBuilder& aBuilder,
mozilla::wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
const LayoutDeviceRect& aRect);
- Maybe<wr::WrImageMask> BuildWrMaskImage(nsDisplayItem* aItem,
+ Maybe<wr::WrImageMask> BuildWrMaskImage(nsDisplayMask* aItem,
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder,
- const LayoutDeviceRect& aBounds);
+ const LayoutDeviceRect& aBounds,
+ MaskImage*& aMaskCache,
+ bool& aCached);
bool PushItemAsImage(nsDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder);
void CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
@@ -184,14 +207,16 @@ private:
// tree don't duplicate scroll metadata that their ancestors already have.
std::vector<const ActiveScrolledRoot*> mAsrStack;
const ActiveScrolledRoot* mLastAsr;
WebRenderUserDataRefTable mWebRenderUserDatas;
// Store of WebRenderCanvasData objects for use in empty transactions
CanvasDataSet mLastCanvasDatas;
+
+ ClipCacheManager mClipCacheManager;
};
} // namespace layers
} // namespace mozilla
#endif /* GFX_WEBRENDERCOMMANDBUILDER_H */
--- a/gfx/layers/wr/WebRenderUserData.cpp
+++ b/gfx/layers/wr/WebRenderUserData.cpp
@@ -234,16 +234,30 @@ WebRenderImageData::CreateImageClientIfN
void
WebRenderImageData::CreateExternalImageIfNeeded()
{
if (!mExternalImageId) {
mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mImageClient));
}
}
+Maybe<wr::ImageKey>
+WebRenderImageData::GetKey() {
+ if (mMaskCache) {
+ return Some(mMaskCache->key);
+ }
+ return mKey;
+}
+
+void WebRenderImageData::SetMaskCache(MaskImage* aMaskImage)
+{
+ mMaskCache = aMaskImage;
+ mKey = Nothing();
+}
+
WebRenderFallbackData::WebRenderFallbackData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem)
: WebRenderImageData(aWRManager, aItem)
, mInvalid(false)
{
}
WebRenderFallbackData::~WebRenderFallbackData()
{
--- a/gfx/layers/wr/WebRenderUserData.h
+++ b/gfx/layers/wr/WebRenderUserData.h
@@ -18,16 +18,17 @@ namespace mozilla {
namespace wr {
class IpcResourceUpdateQueue;
}
namespace layers {
class CanvasLayer;
class ImageClient;
class ImageContainer;
+class MaskImage;
class WebRenderBridgeChild;
class WebRenderCanvasData;
class WebRenderCanvasRendererAsync;
class WebRenderImageData;
class WebRenderFallbackData;
class WebRenderLayerManager;
class WebRenderUserData
@@ -74,17 +75,19 @@ class WebRenderImageData : public WebRen
{
public:
explicit WebRenderImageData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem);
virtual ~WebRenderImageData();
virtual WebRenderImageData* AsImageData() override { return this; }
virtual UserDataType GetType() override { return UserDataType::eImage; }
static UserDataType Type() { return UserDataType::eImage; }
- Maybe<wr::ImageKey> GetKey() { return mKey; }
+ //Maybe<wr::ImageKey> GetKey() { return mKey; }
+ Maybe<wr::ImageKey> GetKey();
+ void SetMaskCache(MaskImage* aMaskImage);
void SetKey(const wr::ImageKey& aKey);
already_AddRefed<ImageClient> GetImageClient();
Maybe<wr::ImageKey> UpdateImageKey(ImageContainer* aContainer,
wr::IpcResourceUpdateQueue& aResources,
bool aFallback = false);
void CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
@@ -105,16 +108,17 @@ protected:
void CreateExternalImageIfNeeded();
wr::MaybeExternalImageId mExternalImageId;
Maybe<wr::ImageKey> mKey;
RefPtr<ImageClient> mImageClient;
Maybe<wr::PipelineId> mPipelineId;
RefPtr<ImageContainer> mContainer;
bool mOwnsKey;
+ RefPtr<MaskImage> mMaskCache;
};
class WebRenderFallbackData : public WebRenderImageData
{
public:
explicit WebRenderFallbackData(WebRenderLayerManager* aWRManager, nsDisplayItem* aItem);
virtual ~WebRenderFallbackData();
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -9611,26 +9611,38 @@ nsDisplayMask::CreateWebRenderCommands(m
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder)
{
bool snap;
float appUnitsPerDevPixel = mFrame->PresContext()->AppUnitsPerDevPixel();
nsRect displayBound = GetBounds(aDisplayListBuilder, &snap);
LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits(displayBound, appUnitsPerDevPixel);
+ MaskImage* maskCache = nullptr;
+ bool cached = false;
+
+
Maybe<wr::WrImageMask> mask = aManager->CommandBuilder().BuildWrMaskImage(this, aBuilder, aResources,
aSc, aDisplayListBuilder,
- bounds);
+ bounds, maskCache, cached);
if (mask) {
- wr::WrClipId clipId = aBuilder.DefineClip(Nothing(), Nothing(),
- aSc.ToRelativeLayoutRect(bounds), nullptr, mask.ptr());
- // Don't record this clip push in aBuilder's internal clip stack, because
- // otherwise any nested ScrollingLayersHelper instances that are created
- // will get confused about which clips are pushed.
- aBuilder.PushClip(clipId, GetClipChain());
+
+ //if (cached && maskCache) {
+ // aBuilder.PushClip(maskCache->clipId, GetClipChain());
+ //} else {
+ wr::WrClipId clipId = aBuilder.DefineClip(Nothing(), Nothing(),
+ aSc.ToRelativeLayoutRect(bounds), nullptr, mask.ptr());
+ // Don't record this clip push in aBuilder's internal clip stack, because
+ // otherwise any nested ScrollingLayersHelper instances that are created
+ // will get confused about which clips are pushed.
+ aBuilder.PushClip(clipId, GetClipChain());
+ //if (!cached && maskCache) {
+ //maskCache->clipId = clipId;
+ //}
+ //}
}
nsDisplaySVGEffects::CreateWebRenderCommands(aBuilder, aResources, aSc, aManager, aDisplayListBuilder);
if (mask) {
aBuilder.PopClip(GetClipChain());
}