fune/gfx/layers/wr/WebRenderPaintedLayer.cpp
Ryan Hunt b66f280583 Bug 1329739 - Specify a WrMixBlendMode for WebRenderLayer r=kats
--HG--
extra : amend_source : bfa6ad8ee9cc13ab292958040ccd0f8dded15e5f
extra : histedit_source : c33cb15304d3e5806b90f04f690e000d42a5f933
2017-01-19 17:57:18 -06:00

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