summaryrefslogtreecommitdiffstats
path: root/gfx/layers/ipc/CanvasTranslator.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/layers/ipc/CanvasTranslator.cpp66
1 files changed, 65 insertions, 1 deletions
diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp
index 4a184f48d8..3fd7a4c4c4 100644
--- a/gfx/layers/ipc/CanvasTranslator.cpp
+++ b/gfx/layers/ipc/CanvasTranslator.cpp
@@ -21,6 +21,7 @@
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/SharedSurfacesParent.h"
#include "mozilla/layers/TextureClient.h"
+#include "mozilla/layers/VideoBridgeParent.h"
#include "mozilla/StaticPrefs_gfx.h"
#include "mozilla/SyncRunnable.h"
#include "mozilla/TaskQueue.h"
@@ -112,6 +113,8 @@ static bool CreateAndMapShmem(RefPtr<ipc::SharedMemoryBasic>& aShmem,
return true;
}
+StaticRefPtr<gfx::SharedContextWebgl> CanvasTranslator::sSharedContext;
+
bool CanvasTranslator::EnsureSharedContextWebgl() {
if (!mSharedContext || mSharedContext->IsContextLost()) {
if (mSharedContext) {
@@ -121,7 +124,14 @@ bool CanvasTranslator::EnsureSharedContextWebgl() {
mRemoteTextureOwner->ClearRecycledTextures();
}
}
- mSharedContext = gfx::SharedContextWebgl::Create();
+ // Check if the global shared context is still valid. If not, instantiate
+ // a new one before we try to use it.
+ if (!sSharedContext || sSharedContext->IsContextLost()) {
+ sSharedContext = gfx::SharedContextWebgl::Create();
+ }
+ mSharedContext = sSharedContext;
+ // If we can't get a new context, then the only thing left to do is block
+ // new canvases.
if (!mSharedContext || mSharedContext->IsContextLost()) {
mSharedContext = nullptr;
BlockCanvas();
@@ -131,6 +141,13 @@ bool CanvasTranslator::EnsureSharedContextWebgl() {
return true;
}
+void CanvasTranslator::Shutdown() {
+ if (sSharedContext) {
+ gfx::CanvasRenderThread::Dispatch(NS_NewRunnableFunction(
+ "CanvasTranslator::Shutdown", []() { sSharedContext = nullptr; }));
+ }
+}
+
mozilla::ipc::IPCResult CanvasTranslator::RecvInitTranslator(
TextureType aTextureType, TextureType aWebglTextureType,
gfx::BackendType aBackendType, Handle&& aReadHandle,
@@ -1144,6 +1161,13 @@ void CanvasTranslator::ClearTextureInfo() {
mTextureInfo.clear();
mDrawTargets.Clear();
mSharedContext = nullptr;
+ // If the global shared context's ref is the last ref left, then clear out
+ // any internal caches and textures from the context, but still keep it
+ // alive. This saves on startup costs while not contributing significantly
+ // to memory usage.
+ if (sSharedContext && sSharedContext->hasOneRef()) {
+ sSharedContext->ClearCaches();
+ }
mBaseDT = nullptr;
if (mReferenceTextureData) {
mReferenceTextureData->Unlock();
@@ -1163,6 +1187,46 @@ already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupExternalSurface(
return mSharedSurfacesHolder->Get(wr::ToExternalImageId(aKey));
}
+// Check if the surface descriptor describes a GPUVideo texture for which we
+// only have an opaque source/handle from SurfaceDescriptorRemoteDecoder to
+// derive the actual texture from.
+static bool SDIsNullRemoteDecoder(const SurfaceDescriptor& sd) {
+ return sd.type() == SurfaceDescriptor::TSurfaceDescriptorGPUVideo &&
+ sd.get_SurfaceDescriptorGPUVideo()
+ .get_SurfaceDescriptorRemoteDecoder()
+ .subdesc()
+ .type() == RemoteDecoderVideoSubDescriptor::Tnull_t;
+}
+
+already_AddRefed<gfx::SourceSurface>
+CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor(
+ const SurfaceDescriptor& aDesc) {
+ if (!SDIsNullRemoteDecoder(aDesc)) {
+ return nullptr;
+ }
+
+ const auto& sdrd = aDesc.get_SurfaceDescriptorGPUVideo()
+ .get_SurfaceDescriptorRemoteDecoder();
+ RefPtr<VideoBridgeParent> parent =
+ VideoBridgeParent::GetSingleton(sdrd.source());
+ if (!parent) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNote << "TexUnpackSurface failed to get VideoBridgeParent";
+ return nullptr;
+ }
+ RefPtr<TextureHost> texture =
+ parent->LookupTexture(mContentId, sdrd.handle());
+ if (!texture) {
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ gfxCriticalNote << "TexUnpackSurface failed to get TextureHost";
+ return nullptr;
+ }
+
+ RefPtr<gfx::DataSourceSurface> surf = texture->GetAsSurface();
+
+ return surf.forget();
+}
+
void CanvasTranslator::CheckpointReached() { CheckAndSignalWriter(); }
void CanvasTranslator::PauseTranslation() {