Bug 1722258 - Add FallbackRenderer to replace BasicLayerManager usage. r=miko

Differential Revision: https://phabricator.services.mozilla.com/D120921
This commit is contained in:
Matt Woodrow 2021-07-28 20:58:23 +00:00
Родитель 7cd494afba
Коммит 0c782c8447
11 изменённых файлов: 161 добавлений и 23 удалений

Просмотреть файл

@ -6441,8 +6441,14 @@ void PresShell::Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
bgcolor = NS_ComposeColors(bgcolor, mCanvasBackgroundColor);
if (!layerManager) {
// TODO: Once we support WindowRenderers that aren't a LayerManager,
// then we need to handle this single color case for them.
FallbackRenderer* fallback = renderer->AsFallback();
MOZ_ASSERT(fallback);
if (aFlags & PaintFlags::PaintComposite) {
nsIntRect bounds = presContext->GetVisibleArea().ToOutsidePixels(
presContext->AppUnitsPerDevPixel());
fallback->EndTransactionWithColor(bounds, ToDeviceColor(bgcolor));
}
return;
}

Просмотреть файл

@ -167,4 +167,44 @@ void WindowRenderer::UpdatePartialPrerenderedAnimations(
}
}
void FallbackRenderer::SetTarget(gfxContext* aTarget,
layers::BufferMode aDoubleBuffering) {
mTarget = aTarget;
mBufferMode = aDoubleBuffering;
}
bool FallbackRenderer::BeginTransaction(const nsCString& aURL) {
if (!mTarget) {
return false;
}
return true;
}
void FallbackRenderer::EndTransactionWithColor(const nsIntRect& aRect,
const gfx::DeviceColor& aColor) {
mTarget->GetDrawTarget()->FillRect(Rect(aRect), ColorPattern(aColor));
}
void FallbackRenderer::EndTransactionWithList(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
int32_t aAppUnitsPerDevPixel,
EndTransactionFlags aFlags) {
if (aFlags & EndTransactionFlags::END_NO_COMPOSITE) {
return;
}
DrawTarget* dt = mTarget->GetDrawTarget();
if (mBufferMode == BufferMode::BUFFERED) {
dt->PushLayer(true, 1.0, nullptr, Matrix());
}
aList->Paint(aBuilder, mTarget, aAppUnitsPerDevPixel);
if (mBufferMode == BufferMode::BUFFERED) {
dt->PopLayer();
}
}
} // namespace mozilla

Просмотреть файл

@ -24,6 +24,9 @@ class ClientLayerManager;
class FrameUniformityData;
class PersistentBufferProvider;
} // namespace layers
class FallbackRenderer;
class nsDisplayListBuilder;
class nsDisplayList;
class FrameRecorder {
public:
@ -100,6 +103,7 @@ class WindowRenderer : public FrameRecorder {
// Cast to implementation types.
virtual layers::LayerManager* AsLayerManager() { return nullptr; }
virtual layers::WebRenderLayerManager* AsWebRender() { return nullptr; }
virtual FallbackRenderer* AsFallback() { return nullptr; }
// Required functionality
@ -231,6 +235,49 @@ class WindowRenderer : public FrameRecorder {
TimeStamp mAnimationReadyTime;
};
/**
* FallbackRenderer is non-retained renderer that acts as a direct wrapper
* around calling Paint on the provided DisplayList. This is used for cases
* where initializing WebRender is too costly, and we don't need
* retaining/invalidation (like small popup windows).
*
* It doesn't support any sort of EmptyTransaction, and only draws during
* EndTransaction if a composite is requested (no END_NO_COMPOSITE flag
* provided)
*/
class FallbackRenderer : public WindowRenderer {
public:
FallbackRenderer* AsFallback() override { return this; }
void SetTarget(gfxContext* aContext, layers::BufferMode aDoubleBuffering);
bool BeginTransaction(const nsCString& aURL = nsCString()) override;
bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override {
return false;
}
layers::LayersBackend GetBackendType() override {
return layers::LayersBackend::LAYERS_NONE;
}
virtual void GetBackendName(nsAString& name) override {
name.AssignLiteral("Fallback");
}
bool IsCompositingCheap() override { return false; }
void EndTransactionWithColor(const nsIntRect& aRect,
const gfx::DeviceColor& aColor);
void EndTransactionWithList(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
int32_t aAppUnitsPerDevPixel,
EndTransactionFlags aFlags);
RefPtr<gfxContext> mTarget;
layers::BufferMode mBufferMode;
};
} // namespace mozilla
#endif /* MOZILLA_PAINTING_WINDOWRENDERER_H */

Просмотреть файл

@ -2477,13 +2477,20 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(
if (aFlags & PAINT_USE_WIDGET_LAYERS) {
renderer = aBuilder->GetWidgetWindowRenderer(&view);
if (renderer) {
layerManager = renderer->AsLayerManager();
if (layerManager) {
layerManager->SetContainsSVG(false);
}
// The fallback renderer doesn't retain any content, so it's
// not meaningful to use it when drawing to an external context.
if (aCtx && renderer->AsFallback()) {
MOZ_ASSERT(!(aFlags & PAINT_EXISTING_TRANSACTION));
renderer = nullptr;
} else {
layerManager = renderer->AsLayerManager();
if (layerManager) {
layerManager->SetContainsSVG(false);
}
doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
widgetTransaction = true;
doBeginTransaction = !(aFlags & PAINT_EXISTING_TRANSACTION);
widgetTransaction = true;
}
}
}
@ -2618,21 +2625,26 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(
}
if (!sent) {
const auto start = TimeStamp::Now();
if (renderer->AsFallback()) {
renderer->AsFallback()->EndTransactionWithList(
aBuilder, this, presContext->AppUnitsPerDevPixel(), flags);
} else {
const auto start = TimeStamp::Now();
FrameLayerBuilder* layerBuilder =
BuildLayers(aBuilder, layerManager, aFlags, widgetTransaction);
FrameLayerBuilder* layerBuilder =
BuildLayers(aBuilder, layerManager, aFlags, widgetTransaction);
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_LAYERS_TIME, start);
Telemetry::AccumulateTimeDelta(Telemetry::PAINT_BUILD_LAYERS_TIME, start);
if (!layerBuilder) {
layerManager->SetUserData(&gLayerManagerLayerBuilder, nullptr);
return nullptr;
if (!layerBuilder) {
layerManager->SetUserData(&gLayerManagerLayerBuilder, nullptr);
return nullptr;
}
layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer,
aBuilder, flags);
layerBuilder->DidEndTransaction();
}
layerManager->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, aBuilder,
flags);
layerBuilder->DidEndTransaction();
}
if (widgetTransaction ||

Просмотреть файл

@ -4782,6 +4782,11 @@
value: true
mirror: always
- name: gfx.basic_layer_manager.force_enabled
type: RelaxedAtomicBool
value: false
mirror: always
# Whether to enable LayerScope tool and default listening port.
- name: gfx.layerscope.enabled
type: RelaxedAtomicBool

Просмотреть файл

@ -1179,6 +1179,13 @@ bool nsWebBrowser::PaintWindow(nsIWidget* aWidget,
LayoutDeviceIntRegion aRegion) {
WindowRenderer* renderer = aWidget->GetWindowRenderer();
NS_ASSERTION(renderer, "Must be in paint event");
if (FallbackRenderer* fallback = renderer->AsFallback()) {
if (fallback->BeginTransaction()) {
fallback->EndTransactionWithColor(aRegion.GetBounds().ToUnknownRect(),
ToDeviceColor(mBackgroundColor));
}
return true;
}
LayerManager* layerManager = renderer->AsLayerManager();
NS_ASSERTION(layerManager, "Must be in paint event");

Просмотреть файл

@ -592,7 +592,12 @@ WindowRenderer* PuppetWidget::GetWindowRenderer() {
// On the parent process there is no CompositorBridgeChild which confuses
// some layers code, so we use basic layers instead. Note that we create
// a non-retaining layer manager since we don't care about performance.
mWindowRenderer = new BasicLayerManager(BasicLayerManager::BLM_OFFSCREEN);
if (StaticPrefs::gfx_basic_layer_manager_force_enabled()) {
mWindowRenderer =
new BasicLayerManager(BasicLayerManager::BLM_OFFSCREEN);
} else {
mWindowRenderer = new FallbackRenderer;
}
return mWindowRenderer;
}

Просмотреть файл

@ -1348,7 +1348,8 @@ bool nsChildView::PaintWindowInDrawTarget(gfx::DrawTarget* aDT,
targetContext->Clip();
nsAutoRetainCocoaObject kungFuDeathGrip(mView);
if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_NONE ||
GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
nsBaseWidget::AutoLayerManagerSetup setupLayerManager(this, targetContext,
BufferMode::BUFFER_NONE);
return PaintWindow(aRegion);
@ -1399,7 +1400,8 @@ void nsChildView::PaintWindowInContentLayer() {
void nsChildView::HandleMainThreadCATransaction() {
WillPaintWindow();
if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
if (GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_NONE ||
GetWindowRenderer()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
// We're in BasicLayers mode, i.e. main thread software compositing.
// Composite the window into our layer's surface.
PaintWindowInContentLayer();

Просмотреть файл

@ -884,6 +884,11 @@ nsBaseWidget::AutoLayerManagerSetup::AutoLayerManagerSetup(
nsBaseWidget* aWidget, gfxContext* aTarget, BufferMode aDoubleBuffering)
: mWidget(aWidget) {
WindowRenderer* renderer = mWidget->GetWindowRenderer();
if (renderer->AsFallback()) {
mRenderer = renderer->AsFallback();
mRenderer->SetTarget(aTarget, aDoubleBuffering);
return;
}
LayerManager* lm = renderer ? renderer->AsLayerManager() : nullptr;
NS_ASSERTION(
!lm || lm->GetBackendType() == LayersBackend::LAYERS_BASIC,
@ -904,6 +909,9 @@ nsBaseWidget::AutoLayerManagerSetup::~AutoLayerManagerSetup() {
mLayerManager->SetDefaultTargetConfiguration(
mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0);
}
if (mRenderer) {
mRenderer->SetTarget(nullptr, mozilla::layers::BufferMode::BUFFER_NONE);
}
}
bool nsBaseWidget::IsSmallPopup() const {
@ -1525,7 +1533,11 @@ WindowRenderer* nsBaseWidget::GetWindowRenderer() {
}
WindowRenderer* nsBaseWidget::CreateBasicLayerManager() {
return new BasicLayerManager(this);
if (StaticPrefs::gfx_basic_layer_manager_force_enabled()) {
return new BasicLayerManager(this);
} else {
return new FallbackRenderer;
}
}
CompositorBridgeChild* nsBaseWidget::GetRemoteRenderer() {

Просмотреть файл

@ -403,6 +403,7 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference {
private:
nsBaseWidget* mWidget;
RefPtr<BasicLayerManager> mLayerManager;
mozilla::FallbackRenderer* mRenderer = nullptr;
};
friend class AutoLayerManagerSetup;

Просмотреть файл

@ -270,6 +270,7 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) {
#endif // WIDGET_DEBUG_OUTPUT
switch (renderer->GetBackendType()) {
case LayersBackend::LAYERS_NONE:
case LayersBackend::LAYERS_BASIC: {
RefPtr<gfxASurface> targetSurface;