tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 8a79d4eeeaee24d3b7f3b637f6b042074250089d
parent 3dc42d023d79d2b8ac2d19b63a7059eca92d23ab
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Tue, 30 Dec 2025 13:22:02 +0000

Bug 2007997 - Remove non-blob fallback code-path. r=gfx-reviewers,aosmond

When this was introduced, we used to draw a lot more native widgets.

Nowadays:

 * Outlines never hit this (we use webrender to paint them).
 * The widgets that hit the fallback codepath are rather small
   (checkboxes / radios / macOS buttons and dropdowns).

So let's simplify the code a bit. I wrote this to see if it helped with
bug 2007110 but I still think it's worth landing.

Differential Revision: https://phabricator.services.mozilla.com/D277637

Diffstat:
Dgfx/layers/UpdateImageHelper.h | 82-------------------------------------------------------------------------------
Mgfx/layers/moz.build | 1-
Mgfx/layers/wr/WebRenderCommandBuilder.cpp | 196+++++++++++++++++++++++++++++--------------------------------------------------
Mgfx/layers/wr/WebRenderLayerManager.cpp | 1-
Mlayout/painting/nsDisplayList.h | 20--------------------
5 files changed, 71 insertions(+), 229 deletions(-)

diff --git a/gfx/layers/UpdateImageHelper.h b/gfx/layers/UpdateImageHelper.h @@ -1,82 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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_UPDATEIMAGEHELPER_H -#define GFX_UPDATEIMAGEHELPER_H - -#include "mozilla/layers/CompositorTypes.h" -#include "mozilla/layers/ImageClient.h" -#include "mozilla/layers/TextureClient.h" -#include "mozilla/layers/TextureClientRecycleAllocator.h" -#include "mozilla/layers/TextureWrapperImage.h" -#include "mozilla/gfx/Types.h" - -namespace mozilla { -namespace layers { - -class UpdateImageHelper { - public: - UpdateImageHelper(ImageContainer* aImageContainer, ImageClient* aImageClient, - gfx::IntSize aImageSize, gfx::SurfaceFormat aFormat) - : mImageContainer(aImageContainer), - mImageClient(aImageClient), - mImageSize(aImageSize), - mIsLocked(false) { - mTexture = mImageClient->GetTextureClientRecycler()->CreateOrRecycle( - aFormat, mImageSize, BackendSelector::Content, TextureFlags::DEFAULT); - if (!mTexture) { - return; - } - - mIsLocked = mTexture->Lock(OpenMode::OPEN_WRITE_ONLY); - if (!mIsLocked) { - return; - } - } - - ~UpdateImageHelper() { - if (mIsLocked) { - mTexture->Unlock(); - mIsLocked = false; - } - } - - already_AddRefed<gfx::DrawTarget> GetDrawTarget() { - RefPtr<gfx::DrawTarget> target; - if (mTexture) { - target = mTexture->BorrowDrawTarget(); - } - return target.forget(); - } - - bool UpdateImage() { - if (!mTexture) { - return false; - } - - if (mIsLocked) { - mTexture->Unlock(); - mIsLocked = false; - } - - RefPtr<TextureWrapperImage> image = new TextureWrapperImage( - mTexture, gfx::IntRect(gfx::IntPoint(0, 0), mImageSize)); - mImageContainer->SetCurrentImageInTransaction(image); - return mImageClient->UpdateImage(mImageContainer); - } - - private: - RefPtr<ImageContainer> mImageContainer; - RefPtr<ImageClient> mImageClient; - gfx::IntSize mImageSize; - RefPtr<TextureClient> mTexture; - bool mIsLocked; -}; - -} // namespace layers -} // namespace mozilla - -#endif // GFX_UPDATEIMAGEHELPER_H diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build @@ -219,7 +219,6 @@ EXPORTS.mozilla.layers += [ "TextureWrapperImage.h", "TransactionIdAllocator.h", "TreeTraversal.h", - "UpdateImageHelper.h", "wr/AsyncImagePipelineManager.h", "wr/AsyncImagePipelineOp.h", "wr/ClipManager.h", diff --git a/gfx/layers/wr/WebRenderCommandBuilder.cpp b/gfx/layers/wr/WebRenderCommandBuilder.cpp @@ -28,7 +28,6 @@ #include "mozilla/layers/SharedSurfacesChild.h" #include "mozilla/layers/SourceSurfaceSharedData.h" #include "mozilla/layers/StackingContextHelper.h" -#include "mozilla/layers/UpdateImageHelper.h" #include "mozilla/layers/WebRenderDrawEventRecorder.h" #include "UnitTransforms.h" #include "gfxEnv.h" @@ -361,7 +360,7 @@ struct DIGroup { mFonts.clear(); } - static LayerIntRect ToDeviceSpace(nsRect aBounds, Matrix& aMatrix, + static LayerIntRect ToDeviceSpace(const nsRect& aBounds, Matrix& aMatrix, int32_t aAppUnitsPerDevPixel) { // RoundedOut can convert empty rectangles to non-empty ones // so special case them here @@ -2496,11 +2495,9 @@ WebRenderCommandBuilder::GenerateFallbackData( nsDisplayItem* aItem, wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, nsDisplayListBuilder* aDisplayListBuilder, LayoutDeviceRect& aImageRect) { - bool useBlobImage = aItem->ShouldUseBlobRenderingForFallback(); - Maybe<gfx::DeviceColor> highlight = Nothing(); + Maybe<gfx::DeviceColor> highlight; if (StaticPrefs::gfx_webrender_debug_highlight_painted_layers()) { - highlight = Some(useBlobImage ? gfx::DeviceColor(1.0, 0.0, 0.0, 0.5) - : gfx::DeviceColor(1.0, 1.0, 0.0, 0.5)); + highlight.emplace(gfx::DeviceColor(1.0, 0.0, 0.0, 0.5)); } RefPtr<WebRenderFallbackData> fallbackData = @@ -2585,13 +2582,8 @@ WebRenderCommandBuilder::GenerateFallbackData( return nullptr; } - if (useBlobImage) { - // Display item bounds should be unscaled - aImageRect = visibleRect / layerScale; - } else { - // Display item bounds should be unscaled - aImageRect = dtRect / layerScale; - } + // Display item bounds should be unscaled + aImageRect = visibleRect / layerScale; // We always paint items at 0,0 so the visibleRect that we use inside the blob // is needs to be adjusted by the display item bounds top left. @@ -2640,129 +2632,83 @@ WebRenderCommandBuilder::GenerateFallbackData( : (opacity == wr::OpacityType::Opaque ? gfx::SurfaceFormat::B8G8R8X8 : gfx::SurfaceFormat::B8G8R8A8); - if (useBlobImage) { - MOZ_ASSERT(!opaqueRegion.IsComplex()); - - std::vector<RefPtr<ScaledFont>> fonts; - bool validFonts = true; - RefPtr<WebRenderDrawEventRecorder> recorder = - MakeAndAddRef<WebRenderDrawEventRecorder>( - [&](MemStream& aStream, - std::vector<RefPtr<ScaledFont>>& aScaledFonts) { - size_t count = aScaledFonts.size(); - aStream.write((const char*)&count, sizeof(count)); - for (auto& scaled : aScaledFonts) { - Maybe<wr::FontInstanceKey> key = - mManager->WrBridge()->GetFontKeyForScaledFont(scaled, - aResources); - if (key.isNothing()) { - validFonts = false; - break; - } - BlobFont font = {key.value(), scaled}; - aStream.write((const char*)&font, sizeof(font)); - } - fonts = std::move(aScaledFonts); - }); - RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget( - gfx::BackendType::SKIA, gfx::IntSize(1, 1), format); - RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget( - recorder, dummyDt, (dtRect - dtRect.TopLeft()).ToUnknownRect()); - if (aBuilder.GetInheritedOpacity() != 1.0f) { - dt->PushLayer(false, aBuilder.GetInheritedOpacity(), nullptr, - gfx::Matrix()); - } - PaintItemByDrawTarget(aItem, dt, (dtRect / layerScale).TopLeft(), - /*aVisibleRect: */ dt->GetRect(), - aDisplayListBuilder, scale, highlight); - if (aBuilder.GetInheritedOpacity() != 1.0f) { - dt->PopLayer(); - } - - // the item bounds are relative to the blob origin which is - // dtRect.TopLeft() - recorder->FlushItem((dtRect - dtRect.TopLeft()).ToUnknownRect()); - recorder->Finish(); - - if (!validFonts) { - gfxCriticalNote << "Failed serializing fonts for blob image"; - return nullptr; - } - - Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, - recorder->mOutputStream.mLength); - wr::BlobImageKey key = - wr::BlobImageKey{mManager->WrBridge()->GetNextImageKey()}; - wr::ImageDescriptor descriptor(visibleSize.ToUnknownSize(), 0, - dt->GetFormat(), opacity); - if (!aResources.AddBlobImage( - key, descriptor, bytes, - ViewAs<ImagePixel>(visibleRect, - PixelCastJustification::LayerIsImage))) { - return nullptr; - } - TakeExternalSurfaces(recorder, fallbackData->mExternalSurfaces, - mManager->GetRenderRootStateManager(), aResources); - fallbackData->SetBlobImageKey(key); - fallbackData->SetFonts(fonts); - } else { - WebRenderImageData* imageData = fallbackData->PaintIntoImage(); + MOZ_ASSERT(!opaqueRegion.IsComplex()); - imageData->CreateImageClientIfNeeded(); - RefPtr<ImageClient> imageClient = imageData->GetImageClient(); - RefPtr<ImageContainer> imageContainer = MakeAndAddRef<ImageContainer>( - ImageUsageType::WebRenderFallbackData, ImageContainer::SYNCHRONOUS); - - { - UpdateImageHelper helper(imageContainer, imageClient, - dtRect.Size().ToUnknownSize(), format); - { - RefPtr<gfx::DrawTarget> dt = helper.GetDrawTarget(); - if (!dt) { - return nullptr; - } - if (aBuilder.GetInheritedOpacity() != 1.0f) { - dt->PushLayer(false, aBuilder.GetInheritedOpacity(), nullptr, - gfx::Matrix()); - } - PaintItemByDrawTarget(aItem, dt, - /*aOffset: */ aImageRect.TopLeft(), - /*aVisibleRect: */ dt->GetRect(), - aDisplayListBuilder, scale, highlight); - if (aBuilder.GetInheritedOpacity() != 1.0f) { - dt->PopLayer(); - } - } + std::vector<RefPtr<ScaledFont>> fonts; + bool validFonts = true; + RefPtr<WebRenderDrawEventRecorder> recorder = + MakeAndAddRef<WebRenderDrawEventRecorder>( + [&](MemStream& aStream, + std::vector<RefPtr<ScaledFont>>& aScaledFonts) { + size_t count = aScaledFonts.size(); + aStream.write((const char*)&count, sizeof(count)); + for (auto& scaled : aScaledFonts) { + Maybe<wr::FontInstanceKey> key = + mManager->WrBridge()->GetFontKeyForScaledFont(scaled, + aResources); + if (key.isNothing()) { + validFonts = false; + break; + } + BlobFont font = {key.value(), scaled}; + aStream.write((const char*)&font, sizeof(font)); + } + fonts = std::move(aScaledFonts); + }); + RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget( + gfx::BackendType::SKIA, gfx::IntSize(1, 1), format); + RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget( + recorder, dummyDt, (dtRect - dtRect.TopLeft()).ToUnknownRect()); + if (aBuilder.GetInheritedOpacity() != 1.0f) { + dt->PushLayer(false, aBuilder.GetInheritedOpacity(), nullptr, + gfx::Matrix()); + } + PaintItemByDrawTarget(aItem, dt, (dtRect / layerScale).TopLeft(), + /*aVisibleRect: */ dt->GetRect(), aDisplayListBuilder, + scale, highlight); + if (aBuilder.GetInheritedOpacity() != 1.0f) { + dt->PopLayer(); + } - // Update image if there it's invalidated. - if (!helper.UpdateImage()) { - return nullptr; - } - } + // the item bounds are relative to the blob origin which is + // dtRect.TopLeft() + recorder->FlushItem((dtRect - dtRect.TopLeft()).ToUnknownRect()); + recorder->Finish(); - // 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 (!imageData->UpdateImageKey(imageContainer, aResources, true)) { - return nullptr; - } + if (!validFonts) { + gfxCriticalNote << "Failed serializing fonts for blob image"; + return nullptr; } + Range<uint8_t> bytes((uint8_t*)recorder->mOutputStream.mData, + recorder->mOutputStream.mLength); + wr::BlobImageKey key = + wr::BlobImageKey{mManager->WrBridge()->GetNextImageKey()}; + wr::ImageDescriptor descriptor(visibleSize.ToUnknownSize(), 0, + dt->GetFormat(), opacity); + if (!aResources.AddBlobImage( + key, descriptor, bytes, + ViewAs<ImagePixel>(visibleRect, + PixelCastJustification::LayerIsImage))) { + return nullptr; + } + TakeExternalSurfaces(recorder, fallbackData->mExternalSurfaces, + mManager->GetRenderRootStateManager(), aResources); + fallbackData->SetBlobImageKey(key); + fallbackData->SetFonts(fonts); + fallbackData->mScale = scale; fallbackData->mOpacity = aBuilder.GetInheritedOpacity(); fallbackData->SetInvalid(false); } - if (useBlobImage) { - MOZ_DIAGNOSTIC_ASSERT(mManager->WrBridge()->MatchesNamespace( - fallbackData->GetBlobImageKey().ref()), - "Stale blob key for fallback!"); + MOZ_DIAGNOSTIC_ASSERT(mManager->WrBridge()->MatchesNamespace( + fallbackData->GetBlobImageKey().ref()), + "Stale blob key for fallback!"); - aResources.SetBlobImageVisibleArea( - fallbackData->GetBlobImageKey().value(), - ViewAs<ImagePixel>(visibleRect, PixelCastJustification::LayerIsImage)); - } + aResources.SetBlobImageVisibleArea( + fallbackData->GetBlobImageKey().value(), + ViewAs<ImagePixel>(visibleRect, PixelCastJustification::LayerIsImage)); // Update current bounds to fallback data fallbackData->mBounds = paintBounds; diff --git a/gfx/layers/wr/WebRenderLayerManager.cpp b/gfx/layers/wr/WebRenderLayerManager.cpp @@ -18,7 +18,6 @@ #include "mozilla/layers/TextureClient.h" #include "mozilla/layers/TransactionIdAllocator.h" #include "mozilla/layers/WebRenderBridgeChild.h" -#include "mozilla/layers/UpdateImageHelper.h" #include "mozilla/PerfStats.h" #include "nsDisplayList.h" #include "nsLayoutUtils.h" diff --git a/layout/painting/nsDisplayList.h b/layout/painting/nsDisplayList.h @@ -2787,16 +2787,6 @@ class nsDisplayItem { virtual bool NeedsGeometryUpdates() const { return false; } /** - * When this item is rendered using fallback rendering, whether it should use - * blob rendering (i.e. a recording DrawTarget), as opposed to a pixel-backed - * DrawTarget. - * Some items, such as those calling into the native themed widget machinery, - * are more efficiently painted without blob recording. Those should return - * false here. - */ - virtual bool ShouldUseBlobRenderingForFallback() const { return true; } - - /** * If this has a child list where the children are in the same coordinate * system as this item (i.e., they have the same reference frame), * return the list. @@ -4515,10 +4505,6 @@ class nsDisplayThemedBackground : public nsPaintedDisplayItem { layers::RenderRootStateManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) override; - bool ShouldUseBlobRenderingForFallback() const override { - return !XRE_IsParentProcess(); - } - /** * GetBounds() returns the background painting area. */ @@ -4845,12 +4831,6 @@ class nsDisplayOutline final : public nsPaintedDisplayItem { NS_DISPLAY_DECL_NAME("Outline", TYPE_OUTLINE) - bool ShouldUseBlobRenderingForFallback() const override { - MOZ_ASSERT(IsThemedOutline(), - "The only fallback path we have is for themed outlines"); - return !XRE_IsParentProcess(); - } - bool CreateWebRenderCommands( wr::DisplayListBuilder& aBuilder, wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc,