fune/gfx/layers/wr/WebRenderLayerManager.cpp
Ryan Hunt 017d292cac Bug 1382128 part 2 - Remove WrPoint, WrSize, WrRect, WrMatrix, and WrColor. r=kats
MozReview-Commit-ID: 9koNScu4CyE

--HG--
extra : rebase_source : 68185e949ddf2ae346a5d597d056a7f2d9ea7a28
2017-07-18 18:32:46 -04:00

905 lines
27 KiB
C++

/* -*- 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 "WebRenderLayerManager.h"
#include "gfxPrefs.h"
#include "GeckoProfiler.h"
#include "LayersLogging.h"
#include "mozilla/gfx/DrawEventRecorder.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/UpdateImageHelper.h"
#include "WebRenderCanvasLayer.h"
#include "WebRenderColorLayer.h"
#include "WebRenderContainerLayer.h"
#include "WebRenderImageLayer.h"
#include "WebRenderPaintedLayer.h"
#include "WebRenderPaintedLayerBlob.h"
#include "WebRenderTextLayer.h"
#include "WebRenderDisplayItemLayer.h"
namespace mozilla {
using namespace gfx;
namespace layers {
WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
: mWidget(aWidget)
, mLatestTransactionId(0)
, mNeedsComposite(false)
, mIsFirstPaint(false)
, mEndTransactionWithoutLayers(false)
, mTarget(nullptr)
, mPaintSequenceNumber(0)
{
MOZ_COUNT_CTOR(WebRenderLayerManager);
}
KnowsCompositor*
WebRenderLayerManager::AsKnowsCompositor()
{
return mWrChild;
}
bool
WebRenderLayerManager::Initialize(PCompositorBridgeChild* aCBChild,
wr::PipelineId aLayersId,
TextureFactoryIdentifier* aTextureFactoryIdentifier)
{
MOZ_ASSERT(mWrChild == nullptr);
MOZ_ASSERT(aTextureFactoryIdentifier);
LayoutDeviceIntSize size = mWidget->GetClientSize();
TextureFactoryIdentifier textureFactoryIdentifier;
uint32_t id_namespace;
PWebRenderBridgeChild* bridge = aCBChild->SendPWebRenderBridgeConstructor(aLayersId,
size,
&textureFactoryIdentifier,
&id_namespace);
if (!bridge) {
// This should only fail if we attempt to access a layer we don't have
// permission for, or more likely, the GPU process crashed again during
// reinitialization. We can expect to be notified again to reinitialize
// (which may or may not be using WebRender).
gfxCriticalNote << "Failed to create WebRenderBridgeChild.";
return false;
}
mWrChild = static_cast<WebRenderBridgeChild*>(bridge);
WrBridge()->SendCreate(size.ToUnknownSize());
WrBridge()->IdentifyTextureHost(textureFactoryIdentifier);
WrBridge()->SetNamespace(id_namespace);
*aTextureFactoryIdentifier = textureFactoryIdentifier;
return true;
}
void
WebRenderLayerManager::Destroy()
{
DoDestroy(/* aIsSync */ false);
}
void
WebRenderLayerManager::DoDestroy(bool aIsSync)
{
if (IsDestroyed()) {
return;
}
mWidget->CleanupWebRenderWindowOverlay(WrBridge());
LayerManager::Destroy();
if (WrBridge()) {
DiscardImages();
DiscardCompositorAnimations();
WrBridge()->Destroy(aIsSync);
}
if (mTransactionIdAllocator) {
// Make sure to notify the refresh driver just in case it's waiting on a
// pending transaction. Do this at the top of the event loop so we don't
// cause a paint to occur during compositor shutdown.
RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
uint64_t id = mLatestTransactionId;
RefPtr<Runnable> task = NS_NewRunnableFunction(
"TransactionIdAllocator::NotifyTransactionCompleted",
[allocator, id] () -> void {
allocator->NotifyTransactionCompleted(id);
});
NS_DispatchToMainThread(task.forget());
}
// Forget the widget pointer in case we outlive our owning widget.
mWidget = nullptr;
}
WebRenderLayerManager::~WebRenderLayerManager()
{
Destroy();
MOZ_COUNT_DTOR(WebRenderLayerManager);
}
CompositorBridgeChild*
WebRenderLayerManager::GetCompositorBridgeChild()
{
return WrBridge()->GetCompositorBridgeChild();
}
int32_t
WebRenderLayerManager::GetMaxTextureSize() const
{
return WrBridge()->GetMaxTextureSize();
}
bool
WebRenderLayerManager::BeginTransactionWithTarget(gfxContext* aTarget)
{
mTarget = aTarget;
return BeginTransaction();
}
bool
WebRenderLayerManager::BeginTransaction()
{
// Increment the paint sequence number even if test logging isn't
// enabled in this process; it may be enabled in the parent process,
// and the parent process expects unique sequence numbers.
++mPaintSequenceNumber;
if (gfxPrefs::APZTestLoggingEnabled()) {
mApzTestData.StartNewPaint(mPaintSequenceNumber);
}
return true;
}
bool
WebRenderLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags)
{
if (!mRoot) {
return false;
}
// We might used painted layer images so don't delete them yet.
return EndTransactionInternal(nullptr, nullptr, aFlags);
}
/*static*/ int32_t
PopulateScrollData(WebRenderScrollData& aTarget, Layer* aLayer)
{
MOZ_ASSERT(aLayer);
// We want to allocate a WebRenderLayerScrollData object for this layer,
// but don't keep a pointer to it since it might get memmove'd during the
// recursion below. Instead keep the index and get the pointer later.
size_t index = aTarget.AddNewLayerData();
int32_t descendants = 0;
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
descendants += PopulateScrollData(aTarget, child);
}
aTarget.GetLayerDataMutable(index)->Initialize(aTarget, aLayer, descendants);
return descendants + 1;
}
void
WebRenderLayerManager::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder,
StackingContextHelper& aSc,
wr::DisplayListBuilder& aBuilder)
{
nsDisplayList savedItems;
nsDisplayItem* item;
while ((item = aDisplayList->RemoveBottom()) != nullptr) {
nsDisplayItem::Type itemType = item->GetType();
// If the item is a event regions item, but is empty (has no regions in it)
// then we should just throw it out
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
if (eventRegions->IsEmpty()) {
item->~nsDisplayItem();
continue;
}
}
// Peek ahead to the next item and try merging with it or swapping with it
// if necessary.
nsDisplayItem* aboveItem;
while ((aboveItem = aDisplayList->GetBottom()) != nullptr) {
if (aboveItem->TryMerge(item)) {
aDisplayList->RemoveBottom();
item->~nsDisplayItem();
item = aboveItem;
itemType = item->GetType();
} else {
break;
}
}
nsDisplayList* itemSameCoordinateSystemChildren
= item->GetSameCoordinateSystemChildren();
if (item->ShouldFlattenAway(aDisplayListBuilder)) {
aDisplayList->AppendToBottom(itemSameCoordinateSystemChildren);
item->~nsDisplayItem();
continue;
}
savedItems.AppendToTop(item);
if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
aDisplayListBuilder)) {
PushItemAsImage(item, aBuilder, aSc, aDisplayListBuilder);
}
}
aDisplayList->AppendToTop(&savedItems);
}
void
WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder)
{
MOZ_ASSERT(aDisplayList && aDisplayListBuilder);
mEndTransactionWithoutLayers = true;
DiscardImages();
WrBridge()->RemoveExpiredFontKeys();
EndTransactionInternal(nullptr,
nullptr,
EndTransactionFlags::END_DEFAULT,
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.ToRelativeLayoutRect(aRect);
aBuilder.PushImage(r, r, filter, key.value());
return true;
}
static void
PaintItemByDrawTarget(nsDisplayItem* aItem,
DrawTarget* aDT,
const LayerRect& aImageRect,
const LayerPoint& aOffset,
nsDisplayListBuilder* aDisplayListBuilder)
{
aDT->ClearRect(aImageRect.ToUnknownRect());
RefPtr<gfxContext> context = gfxContext::CreateOrNull(aDT, aOffset.ToUnknownPoint());
MOZ_ASSERT(context);
aItem->Paint(aDisplayListBuilder, context);
if (gfxPrefs::WebRenderHighlightPaintedLayers()) {
aDT->SetTransform(Matrix());
aDT->FillRect(Rect(0, 0, aImageRect.width, aImageRect.height), ColorPattern(Color(1.0, 0.0, 0.0, 0.5)));
}
if (aItem->Frame()->PresContext()->GetPaintFlashing()) {
aDT->SetTransform(Matrix());
float r = float(rand()) / RAND_MAX;
float g = float(rand()) / RAND_MAX;
float b = float(rand()) / RAND_MAX;
aDT->FillRect(Rect(0, 0, aImageRect.width, aImageRect.height), ColorPattern(Color(r, g, b, 0.5)));
}
}
bool
WebRenderLayerManager::PushItemAsImage(nsDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder)
{
RefPtr<WebRenderFallbackData> fallbackData = CreateOrRecycleWebRenderUserData<WebRenderFallbackData>(aItem);
bool snap;
nsRect itemBounds = aItem->GetBounds(aDisplayListBuilder, &snap);
nsRect clippedBounds = itemBounds;
const DisplayItemClip& clip = aItem->GetClip();
if (clip.HasClip()) {
clippedBounds = itemBounds.Intersect(clip.GetClipRect());
}
const int32_t appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
LayerRect bounds = ViewAs<LayerPixel>(
LayoutDeviceRect::FromAppUnits(clippedBounds, appUnitsPerDevPixel),
PixelCastJustification::WebRenderHasUnitResolution);
LayerIntSize imageSize = RoundedToInt(bounds.Size());
LayerRect imageRect;
imageRect.SizeTo(LayerSize(imageSize));
if (imageSize.width == 0 || imageSize.height == 0) {
return true;
}
nsPoint shift = clippedBounds.TopLeft() - itemBounds.TopLeft();
LayerPoint offset = ViewAs<LayerPixel>(
LayoutDevicePoint::FromAppUnits(aItem->ToReferenceFrame() + shift, appUnitsPerDevPixel),
PixelCastJustification::WebRenderHasUnitResolution);
nsRegion invalidRegion;
nsAutoPtr<nsDisplayItemGeometry> geometry = fallbackData->GetGeometry();
if (geometry) {
nsPoint shift = itemBounds.TopLeft() - geometry->mBounds.TopLeft();
geometry->MoveBy(shift);
aItem->ComputeInvalidationRegion(aDisplayListBuilder, geometry, &invalidRegion);
nsRect lastBounds = fallbackData->GetBounds();
lastBounds.MoveBy(shift);
if (!lastBounds.IsEqualInterior(clippedBounds)) {
invalidRegion.OrWith(lastBounds);
invalidRegion.OrWith(clippedBounds);
}
}
if (!geometry || !invalidRegion.IsEmpty()) {
if (gfxPrefs::WebRenderBlobImages()) {
RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>();
RefPtr<gfx::DrawTarget> dummyDt =
gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8X8);
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageSize.ToUnknownSize());
PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
recorder->Finish();
wr::ByteBuffer bytes(recorder->mOutputStream.mLength, (uint8_t*)recorder->mOutputStream.mData);
wr::ImageKey key = WrBridge()->GetNextImageKey();
WrBridge()->SendAddBlobImage(key, imageSize.ToUnknownSize(), imageSize.width * 4, dt->GetFormat(), bytes);
fallbackData->SetKey(key);
} else {
fallbackData->CreateImageClientIfNeeded();
RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
{
UpdateImageHelper helper(imageContainer, imageClient, imageSize.ToUnknownSize());
{
RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
PaintItemByDrawTarget(aItem, dt, imageRect, offset, aDisplayListBuilder);
}
if (!helper.UpdateImage()) {
return false;
}
}
// Force update the key in fallback data since we repaint the image in this path.
// If not force update, fallbackData may reuse the original key because it
// doesn't know UpdateImageHelper already updated the image container.
if (!fallbackData->UpdateImageKey(imageContainer, true)) {
return false;
}
}
geometry = aItem->AllocateGeometry(aDisplayListBuilder);
}
// Update current bounds to fallback data
fallbackData->SetGeometry(Move(geometry));
fallbackData->SetBounds(clippedBounds);
MOZ_ASSERT(fallbackData->GetKey());
wr::LayoutRect dest = aSc.ToRelativeLayoutRect(imageRect + offset);
aBuilder.PushImage(dest,
dest,
wr::ImageRendering::Auto,
fallbackData->GetKey().value());
return true;
}
void
WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
mEndTransactionWithoutLayers = false;
DiscardImages();
WrBridge()->RemoveExpiredFontKeys();
EndTransactionInternal(aCallback, aCallbackData, aFlags);
}
bool
WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags,
nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder)
{
AutoProfilerTracing tracing("Paint", "RenderLayers");
mPaintedLayerCallback = aCallback;
mPaintedLayerCallbackData = aCallbackData;
mTransactionIncomplete = false;
if (gfxPrefs::LayersDump()) {
this->Dump();
}
// Since we don't do repeat transactions right now, just set the time
mAnimationReadyTime = TimeStamp::Now();
LayoutDeviceIntSize size = mWidget->GetClientSize();
if (!WrBridge()->DPBegin(size.ToUnknownSize())) {
return false;
}
DiscardCompositorAnimations();
wr::LayoutSize contentSize { (float)size.width, (float)size.height };
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
if (mEndTransactionWithoutLayers) {
// aDisplayList being null here means this is an empty transaction following a layers-free
// transaction, so we reuse the previously built displaylist.
if (aDisplayList && aDisplayListBuilder) {
StackingContextHelper sc;
mParentCommands.Clear();
CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
builder.Finalize(contentSize, mBuiltDisplayList);
}
builder.PushBuiltDisplayList(mBuiltDisplayList);
WrBridge()->AddWebRenderParentCommands(mParentCommands);
} else {
mRoot->StartPendingAnimations(mAnimationReadyTime);
StackingContextHelper sc;
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
}
mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
WrBridge()->ClearReadLocks();
// We can't finish this transaction so return. This usually
// happens in an empty transaction where we can't repaint a painted layer.
// In this case, leave the transaction open and let a full transaction happen.
if (mTransactionIncomplete) {
DiscardLocalImages();
WrBridge()->ProcessWebRenderParentCommands();
return false;
}
WebRenderScrollData scrollData;
if (AsyncPanZoomEnabled()) {
scrollData.SetFocusTarget(mFocusTarget);
mFocusTarget = FocusTarget();
if (mIsFirstPaint) {
scrollData.SetIsFirstPaint();
mIsFirstPaint = false;
}
scrollData.SetPaintSequenceNumber(mPaintSequenceNumber);
if (mRoot) {
PopulateScrollData(scrollData, mRoot.get());
}
}
bool sync = mTarget != nullptr;
mLatestTransactionId = mTransactionIdAllocator->GetTransactionId(/*aThrottle*/ true);
{
AutoProfilerTracing
tracing("Paint", sync ? "ForwardDPTransactionSync":"ForwardDPTransaction");
WrBridge()->DPEnd(builder, size.ToUnknownSize(), sync, mLatestTransactionId, scrollData);
}
MakeSnapshotIfRequired(size);
mNeedsComposite = false;
ClearDisplayItemLayers();
// this may result in Layers being deleted, which results in
// PLayer::Send__delete__() and DeallocShmem()
mKeepAlive.Clear();
ClearMutatedLayers();
return true;
}
void
WebRenderLayerManager::SetFocusTarget(const FocusTarget& aFocusTarget)
{
mFocusTarget = aFocusTarget;
}
bool
WebRenderLayerManager::AsyncPanZoomEnabled() const
{
return mWidget->AsyncPanZoomEnabled();
}
void
WebRenderLayerManager::MakeSnapshotIfRequired(LayoutDeviceIntSize aSize)
{
if (!mTarget || aSize.IsEmpty()) {
return;
}
// XXX Add other TextureData supports.
// Only BufferTexture is supported now.
// TODO: fixup for proper surface format.
RefPtr<TextureClient> texture =
TextureClient::CreateForRawBufferAccess(WrBridge(),
SurfaceFormat::B8G8R8A8,
aSize.ToUnknownSize(),
BackendType::SKIA,
TextureFlags::SNAPSHOT);
if (!texture) {
return;
}
texture->InitIPDLActor(WrBridge());
if (!texture->GetIPDLActor()) {
return;
}
IntRect bounds = ToOutsideIntRect(mTarget->GetClipExtents());
if (!WrBridge()->SendDPGetSnapshot(texture->GetIPDLActor())) {
return;
}
TextureClientAutoLock autoLock(texture, OpenMode::OPEN_READ_ONLY);
if (!autoLock.Succeeded()) {
return;
}
RefPtr<DrawTarget> drawTarget = texture->BorrowDrawTarget();
if (!drawTarget || !drawTarget->IsValid()) {
return;
}
RefPtr<SourceSurface> snapshot = drawTarget->Snapshot();
/*
static int count = 0;
char filename[100];
snprintf(filename, 100, "output%d.png", count++);
printf_stderr("Writing to :%s\n", filename);
gfxUtils::WriteAsPNG(snapshot, filename);
*/
Rect dst(bounds.x, bounds.y, bounds.width, bounds.height);
Rect src(0, 0, bounds.width, bounds.height);
// The data we get from webrender is upside down. So flip and translate up so the image is rightside up.
// Webrender always does a full screen readback.
SurfacePattern pattern(snapshot, ExtendMode::CLAMP,
Matrix::Scaling(1.0, -1.0).PostTranslate(0.0, aSize.height));
DrawTarget* dt = mTarget->GetDrawTarget();
MOZ_RELEASE_ASSERT(dt);
dt->FillRect(dst, pattern);
mTarget = nullptr;
}
void
WebRenderLayerManager::AddImageKeyForDiscard(wr::ImageKey key)
{
mImageKeys.push_back(key);
}
void
WebRenderLayerManager::DiscardImages()
{
if (WrBridge()->IPCOpen()) {
for (auto key : mImageKeys) {
WrBridge()->SendDeleteImage(key);
}
}
mImageKeys.clear();
}
void
WebRenderLayerManager::AddCompositorAnimationsIdForDiscard(uint64_t aId)
{
mDiscardedCompositorAnimationsIds.AppendElement(aId);
}
void
WebRenderLayerManager::DiscardCompositorAnimations()
{
if (WrBridge()->IPCOpen() && !mDiscardedCompositorAnimationsIds.IsEmpty()) {
WrBridge()->
SendDeleteCompositorAnimations(mDiscardedCompositorAnimationsIds);
}
mDiscardedCompositorAnimationsIds.Clear();
}
void
WebRenderLayerManager::DiscardLocalImages()
{
// Removes images but doesn't tell the parent side about them
// This is useful in empty / failed transactions where we created
// image keys but didn't tell the parent about them yet.
mImageKeys.clear();
}
void
WebRenderLayerManager::Mutated(Layer* aLayer)
{
LayerManager::Mutated(aLayer);
AddMutatedLayer(aLayer);
}
void
WebRenderLayerManager::MutatedSimple(Layer* aLayer)
{
LayerManager::Mutated(aLayer);
AddMutatedLayer(aLayer);
}
void
WebRenderLayerManager::AddMutatedLayer(Layer* aLayer)
{
mMutatedLayers.AppendElement(aLayer);
}
void
WebRenderLayerManager::ClearMutatedLayers()
{
mMutatedLayers.Clear();
}
bool
WebRenderLayerManager::IsMutatedLayer(Layer* aLayer)
{
return mMutatedLayers.Contains(aLayer);
}
void
WebRenderLayerManager::Hold(Layer* aLayer)
{
mKeepAlive.AppendElement(aLayer);
}
void
WebRenderLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)
{
if (WrBridge()->IPCOpen()) {
WrBridge()->SendSetLayerObserverEpoch(aLayerObserverEpoch);
}
}
void
WebRenderLayerManager::DidComposite(uint64_t aTransactionId,
const mozilla::TimeStamp& aCompositeStart,
const mozilla::TimeStamp& aCompositeEnd)
{
MOZ_ASSERT(mWidget);
// |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
// layers transaction.
if (aTransactionId) {
nsIWidgetListener *listener = mWidget->GetWidgetListener();
if (listener) {
listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
}
listener = mWidget->GetAttachedWidgetListener();
if (listener) {
listener->DidCompositeWindow(aTransactionId, aCompositeStart, aCompositeEnd);
}
mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);
}
// These observers fire whether or not we were in a transaction.
for (size_t i = 0; i < mDidCompositeObservers.Length(); i++) {
mDidCompositeObservers[i]->DidComposite();
}
}
void
WebRenderLayerManager::ClearLayer(Layer* aLayer)
{
aLayer->ClearCachedResources();
if (aLayer->GetMaskLayer()) {
aLayer->GetMaskLayer()->ClearCachedResources();
}
for (Layer* child = aLayer->GetFirstChild(); child;
child = child->GetNextSibling()) {
ClearLayer(child);
}
}
void
WebRenderLayerManager::ClearCachedResources(Layer* aSubtree)
{
WrBridge()->BeginClearCachedResources();
if (aSubtree) {
ClearLayer(aSubtree);
} else if (mRoot) {
ClearLayer(mRoot);
}
WrBridge()->EndClearCachedResources();
}
void
WebRenderLayerManager::UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier& aNewIdentifier,
uint64_t aDeviceResetSeqNo)
{
WrBridge()->IdentifyTextureHost(aNewIdentifier);
}
TextureFactoryIdentifier
WebRenderLayerManager::GetTextureFactoryIdentifier()
{
return WrBridge()->GetTextureFactoryIdentifier();
}
void
WebRenderLayerManager::AddDidCompositeObserver(DidCompositeObserver* aObserver)
{
if (!mDidCompositeObservers.Contains(aObserver)) {
mDidCompositeObservers.AppendElement(aObserver);
}
}
void
WebRenderLayerManager::RemoveDidCompositeObserver(DidCompositeObserver* aObserver)
{
mDidCompositeObservers.RemoveElement(aObserver);
}
void
WebRenderLayerManager::FlushRendering()
{
CompositorBridgeChild* cBridge = GetCompositorBridgeChild();
if (!cBridge) {
return;
}
MOZ_ASSERT(mWidget);
if (mWidget->SynchronouslyRepaintOnResize() || gfxPrefs::LayersForceSynchronousResize()) {
cBridge->SendFlushRendering();
} else {
cBridge->SendFlushRenderingAsync();
}
}
void
WebRenderLayerManager::WaitOnTransactionProcessed()
{
CompositorBridgeChild* bridge = GetCompositorBridgeChild();
if (bridge) {
bridge->SendWaitOnTransactionProcessed();
}
}
void
WebRenderLayerManager::SendInvalidRegion(const nsIntRegion& aRegion)
{
// XXX Webrender does not support invalid region yet.
}
void
WebRenderLayerManager::ScheduleComposite()
{
WrBridge()->SendForceComposite();
}
void
WebRenderLayerManager::SetRoot(Layer* aLayer)
{
mRoot = aLayer;
}
already_AddRefed<PaintedLayer>
WebRenderLayerManager::CreatePaintedLayer()
{
if (gfxPrefs::WebRenderBlobImages()) {
return MakeAndAddRef<WebRenderPaintedLayerBlob>(this);
} else {
return MakeAndAddRef<WebRenderPaintedLayer>(this);
}
}
already_AddRefed<ContainerLayer>
WebRenderLayerManager::CreateContainerLayer()
{
return MakeAndAddRef<WebRenderContainerLayer>(this);
}
already_AddRefed<ImageLayer>
WebRenderLayerManager::CreateImageLayer()
{
return MakeAndAddRef<WebRenderImageLayer>(this);
}
already_AddRefed<CanvasLayer>
WebRenderLayerManager::CreateCanvasLayer()
{
return MakeAndAddRef<WebRenderCanvasLayer>(this);
}
already_AddRefed<ReadbackLayer>
WebRenderLayerManager::CreateReadbackLayer()
{
return nullptr;
}
already_AddRefed<ColorLayer>
WebRenderLayerManager::CreateColorLayer()
{
return MakeAndAddRef<WebRenderColorLayer>(this);
}
already_AddRefed<RefLayer>
WebRenderLayerManager::CreateRefLayer()
{
return MakeAndAddRef<WebRenderRefLayer>(this);
}
already_AddRefed<TextLayer>
WebRenderLayerManager::CreateTextLayer()
{
return MakeAndAddRef<WebRenderTextLayer>(this);
}
already_AddRefed<BorderLayer>
WebRenderLayerManager::CreateBorderLayer()
{
return nullptr;
}
already_AddRefed<DisplayItemLayer>
WebRenderLayerManager::CreateDisplayItemLayer()
{
return MakeAndAddRef<WebRenderDisplayItemLayer>(this);
}
} // namespace layers
} // namespace mozilla