mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-26 14:46:02 +00:00
Bug 1376855 - Introduce WebRenderUserData and WebRenderImageData. r=kats
Layers are retained between transaction and we store some data in the layers. Thus, if we no longer use layers, we need find another storage to place those data. I use frame's property to retain WebRenderUserData between transaction. MozReview-Commit-ID: Ku5VGBXa3w6 --HG-- extra : rebase_source : 636653f78d1d6c310726a1a2c944141dc691decc
This commit is contained in:
parent
a43aba7200
commit
77424afaa9
@ -238,6 +238,7 @@ EXPORTS.mozilla.layers += [
|
||||
'wr/WebRenderScrollData.h',
|
||||
'wr/WebRenderScrollDataWrapper.h',
|
||||
'wr/WebRenderTextureHost.h',
|
||||
'wr/WebRenderUserData.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_X11']:
|
||||
@ -467,6 +468,7 @@ UNIFIED_SOURCES += [
|
||||
'wr/WebRenderPaintedLayerBlob.cpp',
|
||||
'wr/WebRenderScrollData.cpp',
|
||||
'wr/WebRenderTextLayer.cpp',
|
||||
'wr/WebRenderUserData.cpp',
|
||||
# XXX here are some unified build error.
|
||||
#'wr/WebRenderTextureHost.cpp'
|
||||
]
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "WebRenderPaintedLayerBlob.h"
|
||||
#include "WebRenderTextLayer.h"
|
||||
#include "WebRenderDisplayItemLayer.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -244,6 +243,66 @@ WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
|
||||
aDisplayListBuilder);
|
||||
}
|
||||
|
||||
Maybe<wr::ImageKey>
|
||||
WebRenderLayerManager::CreateImageKey(nsDisplayItem* aItem,
|
||||
ImageContainer* aContainer,
|
||||
mozilla::wr::DisplayListBuilder& aBuilder,
|
||||
const StackingContextHelper& aSc,
|
||||
gfx::IntSize& aSize)
|
||||
{
|
||||
RefPtr<WebRenderImageData> imageData = CreateOrRecycleWebRenderUserData<WebRenderImageData>(aItem);
|
||||
MOZ_ASSERT(imageData);
|
||||
|
||||
if (aContainer->IsAsync()) {
|
||||
bool snap;
|
||||
nsRect bounds = aItem->GetBounds(nullptr, &snap);
|
||||
int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
|
||||
LayerRect rect = ViewAs<LayerPixel>(
|
||||
LayoutDeviceRect::FromAppUnits(bounds, appUnitsPerDevPixel),
|
||||
PixelCastJustification::WebRenderHasUnitResolution);
|
||||
LayerRect scBounds(0, 0, rect.width, rect.height);
|
||||
imageData->CreateAsyncImageWebRenderCommands(aBuilder,
|
||||
aContainer,
|
||||
aSc,
|
||||
rect,
|
||||
scBounds,
|
||||
gfx::Matrix4x4(),
|
||||
Nothing(),
|
||||
wr::ImageRendering::Auto,
|
||||
wr::MixBlendMode::Normal);
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
AutoLockImage autoLock(aContainer);
|
||||
if (!autoLock.HasImage()) {
|
||||
return Nothing();
|
||||
}
|
||||
mozilla::layers::Image* image = autoLock.GetImage();
|
||||
aSize = image->GetSize();
|
||||
|
||||
return imageData->UpdateImageKey(aContainer);
|
||||
}
|
||||
|
||||
bool
|
||||
WebRenderLayerManager::PushImage(nsDisplayItem* aItem,
|
||||
ImageContainer* aContainer,
|
||||
mozilla::wr::DisplayListBuilder& aBuilder,
|
||||
const StackingContextHelper& aSc,
|
||||
const LayerRect& aRect)
|
||||
{
|
||||
gfx::IntSize size;
|
||||
Maybe<wr::ImageKey> key = CreateImageKey(aItem, aContainer, aBuilder, aSc, size);
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
wr::ImageRendering filter = wr::ImageRendering::Auto;
|
||||
auto r = aSc.ToRelativeWrRect(aRect);
|
||||
aBuilder.PushImage(r, r, filter, key.value());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
|
@ -12,11 +12,12 @@
|
||||
#include "mozilla/layers/FocusTarget.h"
|
||||
#include "mozilla/layers/StackingContextHelper.h"
|
||||
#include "mozilla/layers/TransactionIdAllocator.h"
|
||||
#include "mozilla/layers/WebRenderUserData.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
#include "mozilla/webrender/WebRenderTypes.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
class nsIWidget;
|
||||
class nsDisplayList;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
@ -52,6 +53,16 @@ public:
|
||||
virtual bool BeginTransactionWithTarget(gfxContext* aTarget) override;
|
||||
virtual bool BeginTransaction() override;
|
||||
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override;
|
||||
Maybe<wr::ImageKey> CreateImageKey(nsDisplayItem* aItem,
|
||||
ImageContainer* aContainer,
|
||||
mozilla::wr::DisplayListBuilder& aBuilder,
|
||||
const StackingContextHelper& aSc,
|
||||
gfx::IntSize& aSize);
|
||||
bool PushImage(nsDisplayItem* aItem,
|
||||
ImageContainer* aContainer,
|
||||
mozilla::wr::DisplayListBuilder& aBuilder,
|
||||
const StackingContextHelper& aSc,
|
||||
const LayerRect& aRect);
|
||||
void CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
|
||||
nsDisplayListBuilder* aDisplayListBuilder,
|
||||
StackingContextHelper& aSc,
|
||||
@ -152,6 +163,34 @@ public:
|
||||
const APZTestData& GetAPZTestData() const
|
||||
{ return mApzTestData; }
|
||||
|
||||
// Those are data that we kept between transactions. We used to cache some
|
||||
// data in the layer. But in layers free mode, we don't have layer which
|
||||
// means we need some other place to cached the data between transaction.
|
||||
// We store the data in frame's property.
|
||||
template<class T> already_AddRefed<T>
|
||||
CreateOrRecycleWebRenderUserData(nsDisplayItem* aItem)
|
||||
{
|
||||
MOZ_ASSERT(aItem);
|
||||
nsIFrame* frame = aItem->Frame();
|
||||
|
||||
if (!frame->HasProperty(nsIFrame::WebRenderUserDataProperty())) {
|
||||
frame->AddProperty(nsIFrame::WebRenderUserDataProperty(),
|
||||
new nsIFrame::WebRenderUserDataTable());
|
||||
}
|
||||
|
||||
nsIFrame::WebRenderUserDataTable* userDataTable =
|
||||
frame->GetProperty(nsIFrame::WebRenderUserDataProperty());
|
||||
RefPtr<WebRenderUserData>& data = userDataTable->GetOrInsert(aItem->GetPerFrameKey());
|
||||
if (!data || (data->GetType() != T::Type())) {
|
||||
data = new T(this);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(data);
|
||||
MOZ_ASSERT(data->GetType() == T::Type());
|
||||
RefPtr<T> res = static_cast<T*>(data.get());
|
||||
return res.forget();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Take a snapshot of the parent context, and copy
|
||||
|
144
gfx/layers/wr/WebRenderUserData.cpp
Normal file
144
gfx/layers/wr/WebRenderUserData.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebRenderUserData.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
WebRenderBridgeChild*
|
||||
WebRenderUserData::WrBridge() const
|
||||
{
|
||||
return mWRManager->WrBridge();
|
||||
}
|
||||
|
||||
WebRenderImageData::WebRenderImageData(WebRenderLayerManager* aWRManager)
|
||||
: WebRenderUserData(aWRManager)
|
||||
{
|
||||
}
|
||||
|
||||
WebRenderImageData::~WebRenderImageData()
|
||||
{
|
||||
if (mKey) {
|
||||
mWRManager->AddImageKeyForDiscard(mKey.value());
|
||||
}
|
||||
|
||||
if (mExternalImageId) {
|
||||
WrBridge()->DeallocExternalImageId(mExternalImageId.ref());
|
||||
}
|
||||
|
||||
if (mPipelineId) {
|
||||
WrBridge()->RemovePipelineIdForAsyncCompositable(mPipelineId.ref());
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<wr::ImageKey>
|
||||
WebRenderImageData::UpdateImageKey(ImageContainer* aContainer)
|
||||
{
|
||||
CreateImageClientIfNeeded();
|
||||
CreateExternalImageIfNeeded();
|
||||
|
||||
if (!mImageClient || !mExternalImageId) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mImageClient->AsImageClientSingle());
|
||||
MOZ_ASSERT(aContainer);
|
||||
|
||||
ImageClientSingle* imageClient = mImageClient->AsImageClientSingle();
|
||||
uint32_t oldCounter = imageClient->GetLastUpdateGenerationCounter();
|
||||
|
||||
bool ret = imageClient->UpdateImage(aContainer, /* unused */0);
|
||||
if (!ret || imageClient->IsEmpty()) {
|
||||
// Delete old key
|
||||
if (mKey) {
|
||||
mWRManager->AddImageKeyForDiscard(mKey.value());
|
||||
mKey = Nothing();
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// Reuse old key if generation is not updated.
|
||||
if (oldCounter == imageClient->GetLastUpdateGenerationCounter() && mKey) {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
// Delete old key, we are generating a new key.
|
||||
if (mKey) {
|
||||
mWRManager->AddImageKeyForDiscard(mKey.value());
|
||||
}
|
||||
|
||||
WrImageKey key = WrBridge()->GetNextImageKey();
|
||||
mWRManager->WrBridge()->AddWebRenderParentCommand(OpAddExternalImage(mExternalImageId.value(), key));
|
||||
mKey = Some(key);
|
||||
|
||||
return mKey;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderImageData::CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
|
||||
ImageContainer* aContainer,
|
||||
const StackingContextHelper& aSc,
|
||||
const LayerRect& aBounds,
|
||||
const LayerRect& aSCBounds,
|
||||
const Matrix4x4& aSCTransform,
|
||||
const MaybeIntSize& aScaleToSize,
|
||||
const WrImageRendering& aFilter,
|
||||
const WrMixBlendMode& aMixBlendMode)
|
||||
{
|
||||
MOZ_ASSERT(aContainer->IsAsync());
|
||||
if (!mPipelineId) {
|
||||
// Alloc async image pipeline id.
|
||||
mPipelineId = Some(WrBridge()->GetCompositorBridgeChild()->GetNextPipelineId());
|
||||
WrBridge()->AddPipelineIdForAsyncCompositable(mPipelineId.ref(),
|
||||
aContainer->GetAsyncContainerHandle());
|
||||
}
|
||||
MOZ_ASSERT(!mImageClient);
|
||||
MOZ_ASSERT(!mExternalImageId);
|
||||
|
||||
// Push IFrame for async image pipeline.
|
||||
//
|
||||
// We don't push a stacking context for this async image pipeline here.
|
||||
// Instead, we do it inside the iframe that hosts the image. As a result,
|
||||
// a bunch of the calculations normally done as part of that stacking
|
||||
// context need to be done manually and pushed over to the parent side,
|
||||
// where it will be done when we build the display list for the iframe.
|
||||
// That happens in WebRenderCompositableHolder.
|
||||
WrRect r = aSc.ToRelativeWrRect(aBounds);
|
||||
aBuilder.PushIFrame(r, r, mPipelineId.ref());
|
||||
|
||||
WrBridge()->AddWebRenderParentCommand(OpUpdateAsyncImagePipeline(mPipelineId.value(),
|
||||
aSCBounds,
|
||||
aSCTransform,
|
||||
aScaleToSize,
|
||||
aFilter,
|
||||
aMixBlendMode));
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderImageData::CreateImageClientIfNeeded()
|
||||
{
|
||||
if (!mImageClient) {
|
||||
mImageClient = ImageClient::CreateImageClient(CompositableType::IMAGE,
|
||||
WrBridge(),
|
||||
TextureFlags::DEFAULT);
|
||||
if (!mImageClient) {
|
||||
return;
|
||||
}
|
||||
|
||||
mImageClient->Connect();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderImageData::CreateExternalImageIfNeeded()
|
||||
{
|
||||
if (!mExternalImageId) {
|
||||
mExternalImageId = Some(WrBridge()->AllocExternalImageIdForCompositable(mImageClient));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
81
gfx/layers/wr/WebRenderUserData.h
Normal file
81
gfx/layers/wr/WebRenderUserData.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_WEBRENDERUSERDATA_H
|
||||
#define GFX_WEBRENDERUSERDATA_H
|
||||
|
||||
#include "mozilla/layers/StackingContextHelper.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class ImageClient;
|
||||
class ImageContainer;
|
||||
class WebRenderBridgeChild;
|
||||
class WebRenderImageData;
|
||||
class WebRenderLayerManager;
|
||||
|
||||
class WebRenderUserData
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(WebRenderUserData)
|
||||
|
||||
explicit WebRenderUserData(WebRenderLayerManager* aWRManager)
|
||||
: mWRManager(aWRManager)
|
||||
{ }
|
||||
|
||||
virtual WebRenderImageData* AsImageData() { return nullptr; }
|
||||
|
||||
enum class UserDataType {
|
||||
eImage,
|
||||
};
|
||||
|
||||
virtual UserDataType GetType() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~WebRenderUserData() {}
|
||||
|
||||
WebRenderBridgeChild* WrBridge() const;
|
||||
|
||||
WebRenderLayerManager* mWRManager;
|
||||
};
|
||||
|
||||
class WebRenderImageData : public WebRenderUserData
|
||||
{
|
||||
public:
|
||||
explicit WebRenderImageData(WebRenderLayerManager* aWRManager);
|
||||
virtual ~WebRenderImageData();
|
||||
|
||||
virtual WebRenderImageData* AsImageData() override { return this; }
|
||||
virtual UserDataType GetType() override { return UserDataType::eImage; }
|
||||
static UserDataType Type() { return UserDataType::eImage; }
|
||||
|
||||
Maybe<wr::ImageKey> UpdateImageKey(ImageContainer* aContainer);
|
||||
|
||||
void CreateAsyncImageWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
|
||||
ImageContainer* aContainer,
|
||||
const StackingContextHelper& aSc,
|
||||
const LayerRect& aBounds,
|
||||
const LayerRect& aSCBounds,
|
||||
const gfx::Matrix4x4& aSCTransform,
|
||||
const gfx::MaybeIntSize& aScaleToSize,
|
||||
const WrImageRendering& aFilter,
|
||||
const WrMixBlendMode& aMixBlendMode);
|
||||
|
||||
protected:
|
||||
void CreateImageClientIfNeeded();
|
||||
void CreateExternalImageIfNeeded();
|
||||
|
||||
wr::MaybeExternalImageId mExternalImageId;
|
||||
Maybe<wr::ImageKey> mKey;
|
||||
RefPtr<ImageClient> mImageClient;
|
||||
Maybe<wr::PipelineId> mPipelineId;
|
||||
RefPtr<ImageContainer> mContainer;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GFX_WEBRENDERUSERDATA_H */
|
@ -32,6 +32,7 @@
|
||||
#include "nsDirection.h"
|
||||
#include "nsFrameList.h"
|
||||
#include "nsFrameState.h"
|
||||
#include "mozilla/layers/WebRenderUserData.h"
|
||||
#include "mozilla/ReflowOutput.h"
|
||||
#include "nsITheme.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
@ -1131,6 +1132,9 @@ public:
|
||||
typedef AutoTArray<nsIContent*, 2> ContentArray;
|
||||
static void DestroyContentArray(ContentArray* aArray);
|
||||
|
||||
typedef mozilla::layers::WebRenderUserData WebRenderUserData;
|
||||
typedef nsRefPtrHashtable<nsUint32HashKey, WebRenderUserData> WebRenderUserDataTable;
|
||||
|
||||
#define NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(prop, type, dtor) \
|
||||
static const mozilla::FramePropertyDescriptor<type>* prop() { \
|
||||
/* Use of constexpr caused startup crashes with MSVC2015u1 PGO. */ \
|
||||
@ -1228,6 +1232,7 @@ public:
|
||||
NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(BidiDataProperty, mozilla::FrameBidiData)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY_WITHOUT_DTOR(PlaceholderFrameProperty, nsPlaceholderFrame)
|
||||
NS_DECLARE_FRAME_PROPERTY_DELETABLE(WebRenderUserDataProperty, WebRenderUserDataTable)
|
||||
|
||||
mozilla::FrameBidiData GetBidiData() const
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user