From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- gfx/layers/CanvasDrawEventRecorder.h | 181 +++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 gfx/layers/CanvasDrawEventRecorder.h (limited to 'gfx/layers/CanvasDrawEventRecorder.h') diff --git a/gfx/layers/CanvasDrawEventRecorder.h b/gfx/layers/CanvasDrawEventRecorder.h new file mode 100644 index 0000000000..a4b1261cfb --- /dev/null +++ b/gfx/layers/CanvasDrawEventRecorder.h @@ -0,0 +1,181 @@ +/* -*- 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_layers_CanvasDrawEventRecorder_h +#define mozilla_layers_CanvasDrawEventRecorder_h + +#include + +#include "mozilla/Atomics.h" +#include "mozilla/gfx/DrawEventRecorder.h" +#include "mozilla/ipc/CrossProcessSemaphore.h" +#include "mozilla/ipc/SharedMemoryBasic.h" +#include "mozilla/layers/LayersTypes.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" + +namespace mozilla { + +using EventType = gfx::RecordedEvent::EventType; + +namespace layers { + +typedef mozilla::ipc::SharedMemoryBasic::Handle Handle; +typedef mozilla::CrossProcessSemaphoreHandle CrossProcessSemaphoreHandle; + +class CanvasDrawEventRecorder final : public gfx::DrawEventRecorderPrivate, + public gfx::ContiguousBufferStream { + public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(CanvasDrawEventRecorder, final) + + CanvasDrawEventRecorder(); + + enum class State : uint32_t { + Processing, + + /** + * This is the important state to make sure the other side signals or starts + * us as soon as data or space is available. We set AboutToWait first and + * then re-check the condition. If we went straight to Waiting or Stopped + * then in between the last check and setting the state, the other side + * could have used all available data or space and never have signaled us + * because it didn't know we were about to wait, causing a deadlock. + * While we are in this state, the other side must wait until we resolve the + * AboutToWait state to one of the other states and then signal or start us + * if it needs to. + */ + AboutToWait, + Waiting, + Paused, + Stopped, + Failed, + }; + + struct Header { + Atomic eventCount; + Atomic writerWaitCount; + Atomic writerState; + uint8_t padding1[44]; + Atomic processedCount; + Atomic readerState; + }; + + class Helpers { + public: + virtual ~Helpers() = default; + + virtual bool InitTranslator(TextureType aTextureType, + gfx::BackendType aBackendType, + Handle&& aReadHandle, + nsTArray&& aBufferHandles, + uint64_t aBufferSize, + CrossProcessSemaphoreHandle&& aReaderSem, + CrossProcessSemaphoreHandle&& aWriterSem) = 0; + + virtual bool AddBuffer(Handle&& aBufferHandle, uint64_t aBufferSize) = 0; + + /** + * @returns true if the reader of the CanvasEventRingBuffer has permanently + * stopped processing, otherwise returns false. + */ + virtual bool ReaderClosed() = 0; + + /** + * Causes the reader to resume processing when it is in a stopped state. + */ + virtual bool RestartReader() = 0; + }; + + bool Init(TextureType aTextureType, gfx::BackendType aBackendType, + UniquePtr aHelpers); + + /** + * Record an event for processing by the CanvasParent's CanvasTranslator. + * @param aEvent the event to record + */ + void RecordEvent(const gfx::RecordedEvent& aEvent) final; + + void StoreSourceSurfaceRecording(gfx::SourceSurface* aSurface, + const char* aReason) final; + + gfx::RecorderType GetRecorderType() const override { + return gfx::RecorderType::CANVAS; + } + + void Flush() final { NS_ASSERT_OWNINGTHREAD(CanvasDrawEventRecorder); } + + int64_t CreateCheckpoint(); + + /** + * Waits until the given checkpoint has been read by the translator. + * + * @params aCheckpoint the checkpoint to wait for + * @returns true if the checkpoint was reached, false if the reader is closed + * or we timeout. + */ + bool WaitForCheckpoint(int64_t aCheckpoint); + + TextureType GetTextureType() { return mTextureType; } + + void DropFreeBuffers(); + + void ClearProcessedExternalSurfaces(); + + protected: + gfx::ContiguousBuffer& GetContiguousBuffer(size_t aSize) final; + + void IncrementEventCount() final; + + private: + void WriteInternalEvent(EventType aEventType); + + void CheckAndSignalReader(); + + size_t mDefaultBufferSize; + size_t mMaxDefaultBuffers; + uint32_t mMaxSpinCount; + uint32_t mDropBufferLimit; + uint32_t mDropBufferOnZero; + + UniquePtr mHelpers; + + TextureType mTextureType = TextureType::Unknown; + RefPtr mHeaderShmem; + Header* mHeader = nullptr; + + struct CanvasBuffer : public gfx::ContiguousBuffer { + RefPtr shmem; + + CanvasBuffer() : ContiguousBuffer(nullptr) {} + + explicit CanvasBuffer(RefPtr&& aShmem) + : ContiguousBuffer(static_cast(aShmem->memory()), + aShmem->Size()), + shmem(std::move(aShmem)) {} + + size_t Capacity() { return shmem ? shmem->Size() : 0; } + }; + + struct RecycledBuffer { + RefPtr shmem; + int64_t eventCount = 0; + explicit RecycledBuffer(RefPtr&& aShmem, + int64_t aEventCount) + : shmem(std::move(aShmem)), eventCount(aEventCount) {} + size_t Capacity() { return shmem->Size(); } + }; + + CanvasBuffer mCurrentBuffer; + std::queue mRecycledBuffers; + + UniquePtr mWriterSemaphore; + UniquePtr mReaderSemaphore; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_CanvasDrawEventRecorder_h -- cgit v1.2.3