summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/CanvasTranslator.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/ipc/CanvasTranslator.h')
-rw-r--r--gfx/layers/ipc/CanvasTranslator.h306
1 files changed, 306 insertions, 0 deletions
diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h
new file mode 100644
index 0000000000..af2769b0b4
--- /dev/null
+++ b/gfx/layers/ipc/CanvasTranslator.h
@@ -0,0 +1,306 @@
+/* -*- 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 https://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_layers_CanvasTranslator_h
+#define mozilla_layers_CanvasTranslator_h
+
+#include <unordered_map>
+#include <vector>
+
+#include "mozilla/gfx/InlineTranslator.h"
+#include "mozilla/layers/CanvasDrawEventRecorder.h"
+#include "mozilla/layers/CanvasThread.h"
+#include "mozilla/layers/LayersSurfaces.h"
+#include "mozilla/layers/PCanvasParent.h"
+#include "mozilla/ipc/CrossProcessSemaphore.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+namespace layers {
+
+class TextureData;
+
+class CanvasTranslator final : public gfx::InlineTranslator,
+ public PCanvasParent {
+ public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CanvasTranslator)
+
+ friend class PProtocolParent;
+
+ /**
+ * Create an uninitialized CanvasTranslator and bind it to the given endpoint
+ * on the CanvasPlaybackLoop.
+ *
+ * @param aEndpoint the endpoint to bind to
+ * @return the new CanvasTranslator
+ */
+ static already_AddRefed<CanvasTranslator> Create(
+ Endpoint<PCanvasParent>&& aEndpoint);
+
+ /**
+ * Shutdown all of the CanvasTranslators.
+ */
+ static void Shutdown();
+
+ /**
+ * Initialize the canvas translator for a particular TextureType and
+ * CanvasEventRingBuffer.
+ *
+ * @param aTextureType the TextureType the translator will create
+ * @param aReadHandle handle to the shared memory for the
+ * CanvasEventRingBuffer
+ * @param aReaderSem reading blocked semaphore for the CanvasEventRingBuffer
+ * @param aWriterSem writing blocked semaphore for the CanvasEventRingBuffer
+ */
+ ipc::IPCResult RecvInitTranslator(
+ const TextureType& aTextureType,
+ ipc::SharedMemoryBasic::Handle&& aReadHandle,
+ CrossProcessSemaphoreHandle&& aReaderSem,
+ CrossProcessSemaphoreHandle&& aWriterSem);
+
+ /**
+ * Used to tell the CanvasTranslator to start translating again after it has
+ * stopped due to a timeout waiting for events.
+ */
+ ipc::IPCResult RecvResumeTranslation();
+
+ void ActorDestroy(ActorDestroyReason why) final;
+
+ /**
+ * Translates events until no more are available or the end of a transaction
+ * If this returns false the caller of this is responsible for re-calling
+ * this function.
+ *
+ * @returns true if all events are processed and false otherwise.
+ */
+ bool TranslateRecording();
+
+ /**
+ * Marks the beginning of rendering for a transaction. While in a transaction
+ * the translator will wait for a short time for events before returning.
+ * When not in a transaction the translator will only translate one event at a
+ * time.
+ */
+ void BeginTransaction();
+
+ /**
+ * Marks the end of a transaction.
+ */
+ void EndTransaction();
+
+ /**
+ * Flushes canvas drawing, for example to a device.
+ */
+ void Flush();
+
+ /**
+ * Marks that device change processing in the writing process has finished.
+ */
+ void DeviceChangeAcknowledged();
+
+ /**
+ * Used to send data back to the writer. This is done through the same shared
+ * memory so the writer must wait and read the response after it has submitted
+ * the event that uses this.
+ *
+ * @param aData the data to be written back to the writer
+ * @param aSize the number of chars to write
+ */
+ void ReturnWrite(const char* aData, size_t aSize) {
+ mStream->ReturnWrite(aData, aSize);
+ }
+
+ /**
+ * Set the texture ID that will be used as a lookup for the texture created by
+ * the next CreateDrawTarget.
+ */
+ void SetNextTextureId(int64_t aNextTextureId) {
+ mNextTextureId = aNextTextureId;
+ }
+
+ /**
+ * Used during playback of events to create DrawTargets. For the
+ * CanvasTranslator this means creating TextureDatas and getting the
+ * DrawTargets from those.
+ *
+ * @param aRefPtr the key to store the created DrawTarget against
+ * @param aSize the size of the DrawTarget
+ * @param aFormat the surface format for the DrawTarget
+ * @returns the new DrawTarget
+ */
+ already_AddRefed<gfx::DrawTarget> CreateDrawTarget(
+ gfx::ReferencePtr aRefPtr, const gfx::IntSize& aSize,
+ gfx::SurfaceFormat aFormat) final;
+
+ already_AddRefed<gfx::GradientStops> GetOrCreateGradientStops(
+ gfx::DrawTarget* aDrawTarget, gfx::GradientStop* aRawStops,
+ uint32_t aNumStops, gfx::ExtendMode aExtendMode) final;
+
+ /**
+ * Get the TextureData associated with a TextureData from another process.
+ *
+ * @param aTextureId the key used to find the TextureData
+ * @returns the TextureData found
+ */
+ TextureData* LookupTextureData(int64_t aTextureId);
+
+ /**
+ * Waits for the SurfaceDescriptor associated with a TextureData from another
+ * process to be created and then returns it.
+ *
+ * @param aTextureId the key used to find the SurfaceDescriptor
+ * @returns the SurfaceDescriptor found
+ */
+ UniquePtr<SurfaceDescriptor> WaitForSurfaceDescriptor(int64_t aTextureId);
+
+ /**
+ * Removes the texture and other objects associated with a texture ID.
+ *
+ * @param aTextureId the texture ID to remove
+ */
+ void RemoveTexture(int64_t aTextureId);
+
+ /**
+ * Overriden to remove any DataSourceSurfaces associated with the RefPtr.
+ *
+ * @param aRefPtr the key to the surface
+ * @param aSurface the surface to store
+ */
+ void AddSourceSurface(gfx::ReferencePtr aRefPtr,
+ gfx::SourceSurface* aSurface) final {
+ if (mMappedSurface == aRefPtr) {
+ mPreparedMap = nullptr;
+ mMappedSurface = nullptr;
+ }
+ RemoveDataSurface(aRefPtr);
+ InlineTranslator::AddSourceSurface(aRefPtr, aSurface);
+ }
+
+ /**
+ * Removes the SourceSurface and other objects associated with a SourceSurface
+ * from another process.
+ *
+ * @param aRefPtr the key to the objects to remove
+ */
+ void RemoveSourceSurface(gfx::ReferencePtr aRefPtr) final {
+ if (mMappedSurface == aRefPtr) {
+ mPreparedMap = nullptr;
+ mMappedSurface = nullptr;
+ }
+ RemoveDataSurface(aRefPtr);
+ InlineTranslator::RemoveSourceSurface(aRefPtr);
+ }
+
+ already_AddRefed<gfx::SourceSurface> LookupExternalSurface(
+ uint64_t aKey) final;
+
+ /**
+ * Gets the cached DataSourceSurface, if it exists, associated with a
+ * SourceSurface from another process.
+ *
+ * @param aRefPtr the key used to find the DataSourceSurface
+ * @returns the DataSourceSurface or nullptr if not found
+ */
+ gfx::DataSourceSurface* LookupDataSurface(gfx::ReferencePtr aRefPtr);
+
+ /**
+ * Used to cache the DataSourceSurface from a SourceSurface associated with a
+ * SourceSurface from another process. This is to improve performance if we
+ * require the data for that SourceSurface.
+ *
+ * @param aRefPtr the key used to store the DataSourceSurface
+ * @param aSurface the DataSourceSurface to store
+ */
+ void AddDataSurface(gfx::ReferencePtr aRefPtr,
+ RefPtr<gfx::DataSourceSurface>&& aSurface);
+
+ /**
+ * Gets the cached DataSourceSurface, if it exists, associated with a
+ * SourceSurface from another process.
+ *
+ * @param aRefPtr the key used to find the DataSourceSurface
+ * @returns the DataSourceSurface or nullptr if not found
+ */
+ void RemoveDataSurface(gfx::ReferencePtr aRefPtr);
+
+ /**
+ * Sets a ScopedMap, to be used in a later event.
+ *
+ * @param aSurface the associated surface in the other process
+ * @param aMap the ScopedMap to store
+ */
+ void SetPreparedMap(gfx::ReferencePtr aSurface,
+ UniquePtr<gfx::DataSourceSurface::ScopedMap> aMap);
+
+ /**
+ * Gets the ScopedMap stored using SetPreparedMap.
+ *
+ * @param aSurface must match the surface from the SetPreparedMap call
+ * @returns the ScopedMap if aSurface matches otherwise nullptr
+ */
+ UniquePtr<gfx::DataSourceSurface::ScopedMap> GetPreparedMap(
+ gfx::ReferencePtr aSurface);
+
+ private:
+ explicit CanvasTranslator(
+ already_AddRefed<CanvasThreadHolder> aCanvasThreadHolder);
+
+ ~CanvasTranslator();
+
+ void Bind(Endpoint<PCanvasParent>&& aEndpoint);
+
+ void StartTranslation();
+
+ void FinishShutdown();
+
+ void Deactivate();
+
+ TextureData* CreateTextureData(TextureType aTextureType,
+ const gfx::IntSize& aSize,
+ gfx::SurfaceFormat aFormat);
+
+ void AddSurfaceDescriptor(int64_t aTextureId, TextureData* atextureData);
+
+ bool HandleExtensionEvent(int32_t aType);
+
+ bool CreateReferenceTexture();
+ bool CheckForFreshCanvasDevice(int aLineNumber);
+ void NotifyDeviceChanged();
+
+ RefPtr<CanvasThreadHolder> mCanvasThreadHolder;
+ RefPtr<TaskQueue> mTranslationTaskQueue;
+#if defined(XP_WIN)
+ RefPtr<ID3D11Device> mDevice;
+#endif
+ // We hold the ring buffer as a UniquePtr so we can drop it once
+ // mTranslationTaskQueue has shutdown to break a RefPtr cycle.
+ UniquePtr<CanvasEventRingBuffer> mStream;
+ TextureType mTextureType = TextureType::Unknown;
+ UniquePtr<TextureData> mReferenceTextureData;
+ // Sometimes during device reset our reference DrawTarget can be null, so we
+ // hold the BackendType separately.
+ gfx::BackendType mBackendType = gfx::BackendType::NONE;
+ typedef std::unordered_map<int64_t, UniquePtr<TextureData>> TextureMap;
+ TextureMap mTextureDatas;
+ int64_t mNextTextureId = -1;
+ nsRefPtrHashtable<nsPtrHashKey<void>, gfx::DataSourceSurface> mDataSurfaces;
+ gfx::ReferencePtr mMappedSurface;
+ UniquePtr<gfx::DataSourceSurface::ScopedMap> mPreparedMap;
+ typedef std::unordered_map<int64_t, UniquePtr<SurfaceDescriptor>>
+ DescriptorMap;
+ DescriptorMap mSurfaceDescriptors MOZ_GUARDED_BY(mSurfaceDescriptorsMonitor);
+ Monitor mSurfaceDescriptorsMonitor{
+ "CanvasTranslator::mSurfaceDescriptorsMonitor"};
+ Atomic<bool> mDeactivated{false};
+ bool mIsInTransaction = false;
+ bool mDeviceResetInProgress = false;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_CanvasTranslator_h