forked from mirrors/gecko-dev
--HG-- extra : amend_source : bfa6ad8ee9cc13ab292958040ccd0f8dded15e5f extra : histedit_source : c33cb15304d3e5806b90f04f690e000d42a5f933
166 lines
5.9 KiB
C++
166 lines
5.9 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 "WebRenderPaintedLayer.h"
|
|
|
|
#include "LayersLogging.h"
|
|
#include "mozilla/ArrayUtils.h"
|
|
#include "mozilla/layers/WebRenderBridgeChild.h"
|
|
#include "mozilla/webrender/WebRenderTypes.h"
|
|
#include "gfxUtils.h"
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
void
|
|
WebRenderPaintedLayer::PaintThebes()
|
|
{
|
|
PROFILER_LABEL("WebRenderPaintedLayer", "PaintThebes",
|
|
js::ProfileEntry::Category::GRAPHICS);
|
|
|
|
uint32_t flags = RotatedContentBuffer::PAINT_CAN_DRAW_ROTATED;
|
|
|
|
PaintState state =
|
|
mContentClient->BeginPaintBuffer(this, flags);
|
|
mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
|
|
|
|
if (!state.mRegionToDraw.IsEmpty() && !Manager()->GetPaintedLayerCallback()) {
|
|
return;
|
|
}
|
|
|
|
// The area that became invalid and is visible needs to be repainted
|
|
// (this could be the whole visible area if our buffer switched
|
|
// from RGB to RGBA, because we might need to repaint with
|
|
// subpixel AA)
|
|
state.mRegionToInvalidate.And(state.mRegionToInvalidate,
|
|
GetLocalVisibleRegion().ToUnknownRegion());
|
|
|
|
bool didUpdate = false;
|
|
RotatedContentBuffer::DrawIterator iter;
|
|
while (DrawTarget* target = mContentClient->BorrowDrawTargetForPainting(state, &iter)) {
|
|
if (!target || !target->IsValid()) {
|
|
if (target) {
|
|
mContentClient->ReturnDrawTargetToBuffer(target);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
SetAntialiasingFlags(this, target);
|
|
|
|
RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(target);
|
|
MOZ_ASSERT(ctx); // already checked the target above
|
|
Manager()->GetPaintedLayerCallback()(this,
|
|
ctx,
|
|
iter.mDrawRegion,
|
|
iter.mDrawRegion,
|
|
state.mClip,
|
|
state.mRegionToInvalidate,
|
|
Manager()->GetPaintedLayerCallbackData());
|
|
|
|
ctx = nullptr;
|
|
mContentClient->ReturnDrawTargetToBuffer(target);
|
|
didUpdate = true;
|
|
}
|
|
if (didUpdate) {
|
|
Mutated();
|
|
|
|
ContentClientRemote* contentClientRemote = static_cast<ContentClientRemote*>(mContentClient.get());
|
|
|
|
// Hold(this) ensures this layer is kept alive through the current transaction
|
|
// The ContentClient assumes this layer is kept alive (e.g., in CreateBuffer),
|
|
// so deleting this Hold for whatever reason will break things.
|
|
Manager()->Hold(this);
|
|
|
|
contentClientRemote->Updated(state.mRegionToDraw,
|
|
mVisibleRegion.ToUnknownRegion(),
|
|
state.mDidSelfCopy);
|
|
}
|
|
}
|
|
|
|
void
|
|
WebRenderPaintedLayer::RenderLayerWithReadback(ReadbackProcessor *aReadback)
|
|
{
|
|
if (!mContentClient) {
|
|
mContentClient = ContentClient::CreateContentClient(Manager()->WrBridge());
|
|
if (!mContentClient) {
|
|
return;
|
|
}
|
|
mContentClient->Connect();
|
|
MOZ_ASSERT(mContentClient->GetForwarder());
|
|
}
|
|
|
|
nsTArray<ReadbackProcessor::Update> readbackUpdates;
|
|
nsIntRegion readbackRegion;
|
|
if (aReadback && UsedForReadback()) {
|
|
aReadback->GetPaintedLayerUpdates(this, &readbackUpdates);
|
|
}
|
|
|
|
IntPoint origin(mVisibleRegion.GetBounds().x, mVisibleRegion.GetBounds().y);
|
|
mContentClient->BeginPaint();
|
|
PaintThebes();
|
|
mContentClient->EndPaint(&readbackUpdates);
|
|
}
|
|
|
|
void
|
|
WebRenderPaintedLayer::RenderLayer()
|
|
{
|
|
RenderLayerWithReadback(nullptr);
|
|
|
|
if (!mExternalImageId) {
|
|
mExternalImageId = WrBridge()->AllocExternalImageIdForCompositable(mContentClient);
|
|
MOZ_ASSERT(mExternalImageId);
|
|
}
|
|
|
|
LayerIntRegion visibleRegion = GetVisibleRegion();
|
|
LayerIntRect bounds = visibleRegion.GetBounds();
|
|
LayerIntSize size = bounds.Size();
|
|
if (size.IsEmpty()) {
|
|
return;
|
|
}
|
|
|
|
WrScrollFrameStackingContextGenerator scrollFrames(this);
|
|
|
|
// Since we are creating a stacking context below using the visible region of
|
|
// this layer, we need to make sure the image display item has coordinates
|
|
// relative to the visible region.
|
|
Rect rect = RelativeToVisible(IntRectToRect(bounds.ToUnknownRect()));
|
|
Rect clip;
|
|
if (GetClipRect().isSome()) {
|
|
clip = RelativeToTransformedVisible(IntRectToRect(GetClipRect().ref().ToUnknownRect()));
|
|
} else {
|
|
clip = rect;
|
|
}
|
|
|
|
|
|
Maybe<WrImageMask> mask = buildMaskLayer();
|
|
|
|
if (gfxPrefs::LayersDump()) printf_stderr("PaintedLayer %p using rect:%s clip:%s\n", this, Stringify(rect).c_str(), Stringify(clip).c_str());
|
|
|
|
Rect relBounds = TransformedVisibleBoundsRelativeToParent();
|
|
Rect overflow(0, 0, relBounds.width, relBounds.height);
|
|
Matrix4x4 transform;// = GetTransform();
|
|
WrMixBlendMode mixBlendMode = wr::ToWrMixBlendMode(GetMixBlendMode());
|
|
|
|
WrBridge()->AddWebRenderCommand(
|
|
OpDPPushStackingContext(wr::ToWrRect(relBounds),
|
|
wr::ToWrRect(overflow),
|
|
mask,
|
|
GetAnimations(),
|
|
transform,
|
|
mixBlendMode,
|
|
FrameMetrics::NULL_SCROLL_ID));
|
|
|
|
ContentClientRemoteBuffer* contentClientRemote = static_cast<ContentClientRemoteBuffer*>(mContentClient.get());
|
|
visibleRegion.MoveBy(-contentClientRemote->BufferRect().x, -contentClientRemote->BufferRect().y);
|
|
|
|
WrBridge()->AddWebRenderCommand(OpDPPushExternalImageId(visibleRegion, wr::ToWrRect(rect), wr::ToWrRect(clip), Nothing(), WrTextureFilter::Linear, mExternalImageId));
|
|
if (gfxPrefs::LayersDump()) printf_stderr("PaintedLayer %p using %s as bounds/overflow, %s for transform\n", this, Stringify(relBounds).c_str(), Stringify(transform).c_str());
|
|
WrBridge()->AddWebRenderCommand(OpDPPopStackingContext());
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|