--- a/gfx/layers/wr/WebRenderCommandBuilder.cpp
+++ b/gfx/layers/wr/WebRenderCommandBuilder.cpp
@@ -334,116 +334,137 @@ WebRenderCommandBuilder::PushImage(nsDis
auto r = aSc.ToRelativeLayoutRect(aRect);
gfx::SamplingFilter sampleFilter = nsLayoutUtils::GetSamplingFilterForFrame(aItem->Frame());
aBuilder.PushImage(r, r, !aItem->BackfaceIsHidden(), wr::ToImageRendering(sampleFilter), key.value());
return true;
}
-static void
+static bool
PaintByLayer(nsDisplayItem* aItem,
nsDisplayListBuilder* aDisplayListBuilder,
RefPtr<BasicLayerManager>& aManager,
gfxContext* aContext,
const std::function<void()>& aPaintFunc)
{
if (aManager == nullptr) {
aManager = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
}
+ UniquePtr<LayerProperties> props;
+ if (aManager->GetRoot()) {
+ props = Move(LayerProperties::CloneFrom(aManager->GetRoot()));
+ }
FrameLayerBuilder* layerBuilder = new FrameLayerBuilder();
layerBuilder->Init(aDisplayListBuilder, aManager, nullptr, true);
layerBuilder->DidBeginRetainedLayerTransaction(aManager);
aManager->BeginTransactionWithTarget(aContext);
+ bool isInvalidated = false;
ContainerLayerParameters param;
- RefPtr<Layer> layer = aItem->BuildLayer(aDisplayListBuilder, aManager, param);
- if (layer) {
- UniquePtr<LayerProperties> props;
- props = Move(LayerProperties::CloneFrom(aManager->GetRoot()));
+ RefPtr<Layer> root = aItem->BuildLayer(aDisplayListBuilder, aManager, param);
- aManager->SetRoot(layer);
+ if (root) {
+ aManager->SetRoot(root);
layerBuilder->WillEndTransaction();
aPaintFunc();
+
+ // Check if there is any invalidation region.
+ nsIntRegion invalid;
+ if (props) {
+ props->ComputeDifferences(root, invalid, nullptr);
+ if (!invalid.IsEmpty()) {
+ isInvalidated = true;
+ }
+ } else {
+ isInvalidated = true;
+ }
}
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint()) {
fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem->Name(), aItem->Frame());
std::stringstream stream;
aManager->Dump(stream, "", gfxEnv::DumpPaintToFile());
fprint_stderr(gfxUtils::sDumpPaintFile, stream); // not a typo, fprint_stderr declared in LayersLogging.h
}
#endif
if (aManager->InTransaction()) {
aManager->AbortTransaction();
}
aManager->SetTarget(nullptr);
+
+ return isInvalidated;
}
-static void
+static bool
PaintItemByDrawTarget(nsDisplayItem* aItem,
gfx::DrawTarget* aDT,
const LayerRect& aImageRect,
const LayoutDevicePoint& aOffset,
nsDisplayListBuilder* aDisplayListBuilder,
RefPtr<BasicLayerManager>& aManager,
WebRenderLayerManager* aWrManager,
const gfx::Size& aScale)
{
MOZ_ASSERT(aDT);
+ bool isInvalidated = false;
aDT->ClearRect(aImageRect.ToUnknownRect());
RefPtr<gfxContext> context = gfxContext::CreateOrNull(aDT);
MOZ_ASSERT(context);
context->SetMatrix(context->CurrentMatrix().PreScale(aScale.width, aScale.height).PreTranslate(-aOffset.x, -aOffset.y));
switch (aItem->GetType()) {
case DisplayItemType::TYPE_MASK:
static_cast<nsDisplayMask*>(aItem)->PaintMask(aDisplayListBuilder, context);
+ isInvalidated = true;
break;
case DisplayItemType::TYPE_SVG_WRAPPER:
{
- PaintByLayer(aItem, aDisplayListBuilder, aManager, context, [&]() {
+ isInvalidated = PaintByLayer(aItem, aDisplayListBuilder, aManager, context, [&]() {
aManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, aDisplayListBuilder);
});
break;
}
case DisplayItemType::TYPE_FILTER:
{
- PaintByLayer(aItem, aDisplayListBuilder, aManager, context, [&]() {
+ isInvalidated = PaintByLayer(aItem, aDisplayListBuilder, aManager, context, [&]() {
static_cast<nsDisplayFilter*>(aItem)->PaintAsLayer(aDisplayListBuilder,
context, aManager);
});
break;
}
default:
aItem->Paint(aDisplayListBuilder, context);
+ isInvalidated = true;
break;
}
if (gfxPrefs::WebRenderHighlightPaintedLayers()) {
aDT->SetTransform(gfx::Matrix());
aDT->FillRect(gfx::Rect(0, 0, aImageRect.Width(), aImageRect.Height()), gfx::ColorPattern(gfx::Color(1.0, 0.0, 0.0, 0.5)));
}
- if (aItem->Frame()->PresContext()->GetPaintFlashing()) {
+ if (aItem->Frame()->PresContext()->GetPaintFlashing() && isInvalidated) {
aDT->SetTransform(gfx::Matrix());
float r = float(rand()) / RAND_MAX;
float g = float(rand()) / RAND_MAX;
float b = float(rand()) / RAND_MAX;
aDT->FillRect(gfx::Rect(0, 0, aImageRect.Width(), aImageRect.Height()), gfx::ColorPattern(gfx::Color(r, g, b, 0.5)));
}
+
+ return isInvalidated;
}
already_AddRefed<WebRenderFallbackData>
WebRenderCommandBuilder::GenerateFallbackData(nsDisplayItem* aItem,
wr::DisplayListBuilder& aBuilder,
wr::IpcResourceUpdateQueue& aResources,
const StackingContextHelper& aSc,
nsDisplayListBuilder* aDisplayListBuilder,
@@ -529,53 +550,74 @@ WebRenderCommandBuilder::GenerateFallbac
for (auto unscaled : aUnscaledFonts) {
wr::FontKey key = mManager->WrBridge()->GetFontKeyForUnscaledFont(unscaled);
aStream.write((const char*)&key, sizeof(key));
}
});
RefPtr<gfx::DrawTarget> dummyDt =
gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, gfx::IntSize(1, 1), format);
RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt, paintSize.ToUnknownSize());
- PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder,
- fallbackData->mBasicLayerManager, mManager, scale);
+ bool isInvalidated = PaintItemByDrawTarget(aItem, dt, paintRect, offset, aDisplayListBuilder,
+ fallbackData->mBasicLayerManager, mManager, scale);
recorder->FlushItem(IntRect());
recorder->Finish();
- Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
- wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
- wr::ImageDescriptor descriptor(paintSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
- if (!aResources.AddBlobImage(key, descriptor, bytes)) {
- return nullptr;
+ if (isInvalidated) {
+ Range<uint8_t> bytes((uint8_t *)recorder->mOutputStream.mData, recorder->mOutputStream.mLength);
+ wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
+ wr::ImageDescriptor descriptor(paintSize.ToUnknownSize(), 0, dt->GetFormat(), isOpaque);
+ if (!aResources.AddBlobImage(key, descriptor, bytes)) {
+ return nullptr;
+ }
+ fallbackData->SetKey(key);
+ } else {
+ // If there is no invalidation region and we don't have a image key,
+ // it means we don't need to push image for the item.
+ if (!fallbackData->GetKey().isSome()) {
+ return nullptr;
+ }
}
- fallbackData->SetKey(key);
+
+
} else {
fallbackData->CreateImageClientIfNeeded();
RefPtr<ImageClient> imageClient = fallbackData->GetImageClient();
RefPtr<ImageContainer> imageContainer = LayerManager::CreateImageContainer();
+ bool isInvalidated = false;
{
UpdateImageHelper helper(imageContainer, imageClient, paintSize.ToUnknownSize(), format);
{
RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget();
if (!dt) {
return nullptr;
}
- PaintItemByDrawTarget(aItem, dt, paintRect, offset,
- aDisplayListBuilder,
- fallbackData->mBasicLayerManager, mManager, scale);
+ isInvalidated = PaintItemByDrawTarget(aItem, dt, paintRect, offset,
+ aDisplayListBuilder,
+ fallbackData->mBasicLayerManager, mManager, scale);
}
- if (!helper.UpdateImage()) {
- return nullptr;
+
+ if (isInvalidated) {
+ // Update image if there it's invalidated.
+ if (!helper.UpdateImage()) {
+ return nullptr;
+ }
+ } else {
+ // If there is no invalidation region and we don't have a image key,
+ // it means we don't need to push image for the item.
+ if (!fallbackData->GetKey().isSome()) {
+ return nullptr;
+ }
}
}
// 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, aResources, true)) {
+ if (isInvalidated && !fallbackData->UpdateImageKey(imageContainer, aResources, true)) {
return nullptr;
}
}
geometry = aItem->AllocateGeometry(aDisplayListBuilder);
fallbackData->SetScale(scale);
fallbackData->SetInvalid(false);
}