Bug 1372118 - Part1. Have a path to create WebRender commands without layers. r=jrmuizel, r=kats, r=mattwoodrow

MozReview-Commit-ID: 7iOW9rEtwur
This commit is contained in:
Ethan Lin 2017-06-30 17:23:20 -07:00
Родитель 178043d1da
Коммит de600bafd7
6 изменённых файлов: 149 добавлений и 8 удалений

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

@ -20,6 +20,7 @@
#include "WebRenderPaintedLayerBlob.h"
#include "WebRenderTextLayer.h"
#include "WebRenderDisplayItemLayer.h"
#include "nsDisplayList.h"
namespace mozilla {
@ -32,6 +33,7 @@ WebRenderLayerManager::WebRenderLayerManager(nsIWidget* aWidget)
, mLatestTransactionId(0)
, mNeedsComposite(false)
, mIsFirstPaint(false)
, mEndTransactionWithoutLayers(false)
, mTarget(nullptr)
, mPaintSequenceNumber(0)
{
@ -173,11 +175,81 @@ PopulateScrollData(WebRenderScrollData& aTarget, Layer* aLayer)
return descendants + 1;
}
void
WebRenderLayerManager::CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder,
StackingContextHelper& aSc,
wr::DisplayListBuilder& aBuilder)
{
nsDisplayList savedItems;
nsDisplayItem* item;
while ((item = aDisplayList->RemoveBottom()) != nullptr) {
nsDisplayItem::Type itemType = item->GetType();
// If the item is a event regions item, but is empty (has no regions in it)
// then we should just throw it out
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
if (eventRegions->IsEmpty()) {
item->~nsDisplayItem();
continue;
}
}
// Peek ahead to the next item and try merging with it or swapping with it
// if necessary.
nsDisplayItem* aboveItem;
while ((aboveItem = aDisplayList->GetBottom()) != nullptr) {
if (aboveItem->TryMerge(item)) {
aDisplayList->RemoveBottom();
item->~nsDisplayItem();
item = aboveItem;
itemType = item->GetType();
} else {
break;
}
}
nsDisplayList* itemSameCoordinateSystemChildren
= item->GetSameCoordinateSystemChildren();
if (item->ShouldFlattenAway(aDisplayListBuilder)) {
aDisplayList->AppendToBottom(itemSameCoordinateSystemChildren);
item->~nsDisplayItem();
continue;
}
savedItems.AppendToTop(item);
if (!item->CreateWebRenderCommands(aBuilder, aSc, mParentCommands, this,
aDisplayListBuilder)) {
// TODO: fallback
}
}
aDisplayList->AppendToTop(&savedItems);
}
void
WebRenderLayerManager::EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder)
{
MOZ_ASSERT(aDisplayList && aDisplayListBuilder);
mEndTransactionWithoutLayers = true;
DiscardImages();
WrBridge()->RemoveExpiredFontKeys();
EndTransactionInternal(nullptr,
nullptr,
EndTransactionFlags::END_DEFAULT,
aDisplayList,
aDisplayListBuilder);
}
void
WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
{
mEndTransactionWithoutLayers = false;
DiscardImages();
WrBridge()->RemoveExpiredFontKeys();
EndTransactionInternal(aCallback, aCallbackData, aFlags);
@ -186,7 +258,9 @@ WebRenderLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
bool
WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags)
EndTransactionFlags aFlags,
nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder)
{
AutoProfilerTracing tracing("Paint", "RenderLayers");
mPaintedLayerCallback = aCallback;
@ -205,12 +279,29 @@ WebRenderLayerManager::EndTransactionInternal(DrawPaintedLayerCallback aCallback
return false;
}
DiscardCompositorAnimations();
mRoot->StartPendingAnimations(mAnimationReadyTime);
StackingContextHelper sc;
WrSize contentSize { (float)size.width, (float)size.height };
wr::DisplayListBuilder builder(WrBridge()->GetPipeline(), contentSize);
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
if (mEndTransactionWithoutLayers) {
// aDisplayList being null here means this is an empty transaction following a layers-free
// transaction, so we reuse the previously built displaylist.
if (aDisplayList && aDisplayListBuilder) {
StackingContextHelper sc;
mParentCommands.Clear();
CreateWebRenderCommandsFromDisplayList(aDisplayList, aDisplayListBuilder, sc, builder);
builder.Finalize(contentSize, mBuiltDisplayList);
}
builder.PushBuiltDisplayList(mBuiltDisplayList);
WrBridge()->AddWebRenderParentCommands(mParentCommands);
} else {
mRoot->StartPendingAnimations(mAnimationReadyTime);
StackingContextHelper sc;
WebRenderLayer::ToWebRenderLayer(mRoot)->RenderLayer(builder, sc);
}
mWidget->AddWindowOverlayWebRenderCommands(WrBridge(), builder);
WrBridge()->ClearReadLocks();

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

@ -10,10 +10,13 @@
#include "mozilla/MozPromise.h"
#include "mozilla/layers/APZTestData.h"
#include "mozilla/layers/FocusTarget.h"
#include "mozilla/layers/StackingContextHelper.h"
#include "mozilla/layers/TransactionIdAllocator.h"
#include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/webrender/WebRenderTypes.h"
class nsIWidget;
class nsDisplayList;
namespace mozilla {
namespace layers {
@ -22,6 +25,7 @@ class CompositorBridgeChild;
class KnowsCompositor;
class PCompositorBridgeChild;
class WebRenderBridgeChild;
class WebRenderParentCommand;
class WebRenderLayerManager final : public LayerManager
{
@ -48,6 +52,13 @@ public:
virtual bool BeginTransactionWithTarget(gfxContext* aTarget) override;
virtual bool BeginTransaction() override;
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) override;
void CreateWebRenderCommandsFromDisplayList(nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder,
StackingContextHelper& aSc,
wr::DisplayListBuilder& aBuilder);
void EndTransactionWithoutLayer(nsDisplayList* aDisplayList,
nsDisplayListBuilder* aDisplayListBuilder);
bool IsLayersFreeTransaction() { return mEndTransactionWithoutLayers; }
virtual void EndTransaction(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags = END_DEFAULT) override;
@ -152,8 +163,9 @@ private:
bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
void* aCallbackData,
EndTransactionFlags aFlags);
EndTransactionFlags aFlags,
nsDisplayList* aDisplayList = nullptr,
nsDisplayListBuilder* aDisplayListBuilder = nullptr);
private:
nsIWidget* MOZ_NON_OWNING_REF mWidget;
@ -174,6 +186,11 @@ private:
LayerRefArray mKeepAlive;
// These fields are used to save a copy of the display list for
// empty transactions in layers-free mode.
wr::BuiltDisplayList mBuiltDisplayList;
nsTArray<WebRenderParentCommand> mParentCommands;
// Layers that have been mutated. If we have an empty transaction
// then a display item layer will no longer be valid
// if it was a mutated layers.
@ -185,6 +202,7 @@ private:
bool mNeedsComposite;
bool mIsFirstPaint;
FocusTarget mFocusTarget;
bool mEndTransactionWithoutLayers;
// When we're doing a transaction in order to draw to a non-default
// target, the layers transaction is only performed in order to send

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

@ -473,6 +473,7 @@ private:
DECL_GFX_PREF(Once, "gfx.vsync.compositor.unobserve-count", CompositorUnobserveCount, int32_t, 10);
DECL_OVERRIDE_PREF(Live, "gfx.webrender.omta.enabled", WebRenderOMTAEnabled, gfxPrefs::OverrideBase_WebRender());
DECL_GFX_PREF(Live, "gfx.webrender.profiler.enabled", WebRenderProfilerEnabled, bool, false);
DECL_GFX_PREF(Live, "gfx.webrender.layers-free", WebRenderLayersFree, bool, false);
DECL_GFX_PREF(Live, "gfx.webrendest.enabled", WebRendestEnabled, bool, false);
// Use vsync events generated by hardware
DECL_GFX_PREF(Once, "gfx.work-around-driver-bugs", WorkAroundDriverBugs, bool, true);

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

@ -2092,6 +2092,30 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
nsIPresShell* presShell = presContext->PresShell();
nsIDocument* document = presShell->GetDocument();
if (gfxPrefs::WebRenderLayersFree() &&
layerManager->GetBackendType() == layers::LayersBackend::LAYERS_WR &&
// We don't yet support many display items used in chrome, so
// layers-free mode is only for content.
!presContext->IsChrome()) {
if (doBeginTransaction) {
if (aCtx) {
if (!layerManager->BeginTransactionWithTarget(aCtx)) {
return nullptr;
}
} else {
if (!layerManager->BeginTransaction()) {
return nullptr;
}
}
}
MaybeSetupTransactionIdAllocator(layerManager, presContext);
bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
static_cast<WebRenderLayerManager*>(layerManager.get())->EndTransactionWithoutLayer(this, aBuilder);
aBuilder->SetIsCompositingCheap(temp);
return layerManager.forget();
}
NotifySubDocInvalidationFunc computeInvalidFunc =
presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0;

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

@ -1955,10 +1955,16 @@ public:
* The layer this item is in is passed in as rects must be relative
* to their parent.
*/
virtual void CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
virtual void CreateWebRenderCommand(mozilla::wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
nsTArray<WebRenderParentCommand>& aParentCommands,
WebRenderDisplayItemLayer* aLayer) {}
virtual bool CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
const StackingContextHelper& aSc,
nsTArray<WebRenderParentCommand>& aParentCommands,
WebRenderDisplayItemLayer* aLayer) {}
mozilla::layers::WebRenderLayerManager* aManager,
nsDisplayListBuilder* aDisplayListBuilder) { return false; }
/**
* Builds a DisplayItemLayer and sets the display item to this.
*/

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

@ -4828,6 +4828,7 @@ pref("layers.force-active", false);
pref("layers.gralloc.disable", false);
pref("webrender.highlight-painted-layers", false);
pref("gfx.webrender.layers-free", false);
// Enable/Disable the geolocation API for content
pref("geo.enabled", true);