summaryrefslogtreecommitdiffstats
path: root/layout/painting/WindowRenderer.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--layout/painting/WindowRenderer.h284
1 files changed, 284 insertions, 0 deletions
diff --git a/layout/painting/WindowRenderer.h b/layout/painting/WindowRenderer.h
new file mode 100644
index 0000000000..e018a4cf56
--- /dev/null
+++ b/layout/painting/WindowRenderer.h
@@ -0,0 +1,284 @@
+/* -*- 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 MOZILLA_PAINTING_WINDOWRENDERER_H
+#define MOZILLA_PAINTING_WINDOWRENDERER_H
+
+#include "mozilla/webrender/webrender_ffi.h"
+#include "mozilla/layers/LayersTypes.h"
+#include "mozilla/dom/Animation.h" // for Animation
+#include "mozilla/layers/ScrollableLayerGuid.h" // for ScrollableLayerGuid, ScrollableLayerGuid::ViewID
+#include "mozilla/ScrollPositionUpdate.h" // for ScrollPositionUpdate
+#include "nsRefPtrHashtable.h" // for nsRefPtrHashtable
+#include "gfxContext.h"
+
+namespace mozilla {
+namespace layers {
+class LayerManager;
+class WebRenderLayerManager;
+class KnowsCompositor;
+class CompositorBridgeChild;
+class FrameUniformityData;
+class PersistentBufferProvider;
+} // namespace layers
+class FallbackRenderer;
+class nsDisplayListBuilder;
+class nsDisplayList;
+
+class FrameRecorder {
+ public:
+ /**
+ * Record (and return) frame-intervals and paint-times for frames which were
+ * presented between calling StartFrameTimeRecording and
+ * StopFrameTimeRecording.
+ *
+ * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is
+ * called too late
+ * (elements were overwritten since Start), result is considered invalid
+ * and hence empty.)
+ * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were
+ * less frequent).
+ * Can be changed (up to 1 hour) via pref:
+ * toolkit.framesRecording.bufferSize.
+ * - Note: the first frame-interval may be longer than expected because last
+ * frame
+ * might have been presented some time before calling
+ * StartFrameTimeRecording.
+ */
+
+ /**
+ * Returns a handle which represents current recording start position.
+ */
+ virtual uint32_t StartFrameTimeRecording(int32_t aBufferSize);
+
+ /**
+ * Clears, then populates aFrameIntervals with the recorded frame timing
+ * data. The array will be empty if data was overwritten since
+ * aStartIndex was obtained.
+ */
+ virtual void StopFrameTimeRecording(uint32_t aStartIndex,
+ nsTArray<float>& aFrameIntervals);
+
+ void RecordFrame();
+
+ private:
+ struct FramesTimingRecording {
+ // Stores state and data for frame intervals and paint times recording.
+ // see LayerManager::StartFrameTimeRecording() at Layers.cpp for more
+ // details.
+ FramesTimingRecording()
+ : mNextIndex(0),
+ mLatestStartIndex(0),
+ mCurrentRunStartIndex(0),
+ mIsPaused(true) {}
+ nsTArray<float> mIntervals;
+ TimeStamp mLastFrameTime;
+ uint32_t mNextIndex;
+ uint32_t mLatestStartIndex;
+ uint32_t mCurrentRunStartIndex;
+ bool mIsPaused;
+ };
+ FramesTimingRecording mRecording;
+};
+
+/**
+ * WindowRenderer is the retained rendering object owned by an nsIWidget for
+ * drawing the contents of that window, the role previously handled by
+ * LayerManager.
+ *
+ * It can be WebRender, (deprecated) Layers, or an immediate-mode
+ * FallbackRenderer.
+ *
+ * The intention is for LayerManager to be removed entirely in the near future,
+ * with WebRender inheriting directly from this class. It is likely that more
+ * cleanup can be done once that happens.
+ */
+class WindowRenderer : public FrameRecorder {
+ NS_INLINE_DECL_REFCOUNTING(WindowRenderer)
+
+ public:
+ // Cast to implementation types.
+ virtual layers::WebRenderLayerManager* AsWebRender() { return nullptr; }
+ virtual FallbackRenderer* AsFallback() { return nullptr; }
+
+ // Required functionality
+
+ /**
+ * Start a new transaction. Nested transactions are not allowed so
+ * there must be no transaction currently in progress.
+ * This transaction will update the state of the window from which
+ * this LayerManager was obtained.
+ */
+ virtual bool BeginTransaction(const nsCString& aURL = nsCString()) = 0;
+
+ enum EndTransactionFlags {
+ END_DEFAULT = 0,
+ END_NO_IMMEDIATE_REDRAW = 1 << 0, // Do not perform the drawing phase
+ END_NO_COMPOSITE =
+ 1 << 1, // Do not composite after drawing painted layer contents.
+ END_NO_REMOTE_COMPOSITE = 1 << 2 // Do not schedule a composition with a
+ // remote Compositor, if one exists.
+ };
+
+ /**
+ * Attempts to end an "empty transaction". There must have been no
+ * changes to the layer tree since the BeginTransaction().
+ * It's possible for this to fail; PaintedLayers may need to be updated
+ * due to VRAM data being lost, for example. In such cases this method
+ * returns false, and the caller must proceed with a normal layer tree
+ * update and EndTransaction.
+ */
+ virtual bool EndEmptyTransaction(
+ EndTransactionFlags aFlags = END_DEFAULT) = 0;
+
+ virtual void Destroy() {}
+
+ /**
+ * Type of layer manager this is. This is to be used sparsely in order to
+ * avoid a lot of Layers backend specific code. It should be used only when
+ * Layers backend specific functionality is necessary.
+ */
+ virtual layers::LayersBackend GetBackendType() = 0;
+
+ /**
+ * Type of layers backend that will be used to composite this layer tree.
+ * When compositing is done remotely, then this returns the layers type
+ * of the compositor.
+ */
+ virtual layers::LayersBackend GetCompositorBackendType() {
+ return GetBackendType();
+ }
+
+ /**
+ * Checks if we need to invalidate the OS widget to trigger
+ * painting when updating this renderer.
+ */
+ virtual bool NeedsWidgetInvalidation() { return true; }
+
+ /**
+ * Make sure that the previous transaction has been entirely
+ * completed.
+ *
+ * Note: This may sychronously wait on a remote compositor
+ * to complete rendering.
+ */
+ virtual void FlushRendering(wr::RenderReasons aReasons) {}
+
+ /**
+ * Make sure that the previous transaction has been
+ * received. This will synchronsly wait on a remote compositor.
+ */
+ virtual void WaitOnTransactionProcessed() {}
+
+ virtual bool IsCompositingCheap() { return true; }
+
+ /**
+ * returns the maximum texture size on this layer backend, or INT32_MAX
+ * if there is no maximum
+ */
+ virtual int32_t GetMaxTextureSize() const { return INT32_MAX; }
+
+ /**
+ * Return the name of the layer manager's backend.
+ */
+ virtual void GetBackendName(nsAString& aName) = 0;
+
+ virtual void GetFrameUniformity(layers::FrameUniformityData* aOutData) {}
+
+ virtual bool AddPendingScrollUpdateForNextTransaction(
+ layers::ScrollableLayerGuid::ViewID aScrollId,
+ const ScrollPositionUpdate& aUpdateInfo) {
+ return false;
+ }
+
+ /**
+ * Creates a PersistentBufferProvider for use with canvas which is optimized
+ * for inter-operating with this layermanager.
+ */
+ virtual already_AddRefed<layers::PersistentBufferProvider>
+ CreatePersistentBufferProvider(const mozilla::gfx::IntSize& aSize,
+ mozilla::gfx::SurfaceFormat aFormat);
+
+ // Helper wrappers around cast to impl and then cast again.
+
+ virtual layers::KnowsCompositor* AsKnowsCompositor() { return nullptr; }
+
+ virtual layers::CompositorBridgeChild* GetCompositorBridgeChild() {
+ return nullptr;
+ }
+
+ // Provided functionality
+
+ void AddPartialPrerenderedAnimation(uint64_t aCompositorAnimationId,
+ dom::Animation* aAnimation);
+ void RemovePartialPrerenderedAnimation(uint64_t aCompositorAnimationId,
+ dom::Animation* aAnimation);
+ void UpdatePartialPrerenderedAnimations(
+ const nsTArray<uint64_t>& aJankedAnimations);
+
+ const TimeStamp& GetAnimationReadyTime() const { return mAnimationReadyTime; }
+
+ protected:
+ virtual ~WindowRenderer() = default;
+
+ // Transform animations which are not fully pre-rendered because it's on a
+ // large frame. We need to update the pre-rendered area once after we tried
+ // to composite area which is outside of the pre-rendered area on the
+ // compositor.
+ nsRefPtrHashtable<nsUint64HashKey, dom::Animation>
+ mPartialPrerenderedAnimations;
+
+ // The time when painting most recently finished. This is recorded so that
+ // we can time any play-pending animations from this point.
+ 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);
+
+ gfxContext* mTarget;
+ layers::BufferMode mBufferMode;
+};
+
+} // namespace mozilla
+
+#endif /* MOZILLA_PAINTING_WINDOWRENDERER_H */