From d3bd7ab3f1a033896d68aeceb3ece0c367317f53 Mon Sep 17 00:00:00 2001 From: sotaro Date: Thu, 6 Jun 2024 03:25:53 +0000 Subject: [PATCH] Bug 1900677 - Add a capability to recycle DataSourceSurface allocated in CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor() if possible r=gfx-reviewers,lsalzman By default, it is disabled by pref gfx.canvas.remote.recycle-used-data-surface = false. Add a capability to reuse used DataSourceSurface that was previously used for storing converted video data. Add argument gfx::DataSourceSurface* aSurface to TextureHost::GetAsSurface(). aSurface may be used as returned DataSourceSurfacefi the TextureHost supports it. Differential Revision: https://phabricator.services.mozilla.com/D212608 --- gfx/layers/DcompSurfaceImage.h | 3 +- gfx/layers/MacIOSurfaceHelpers.cpp | 21 ++++++--- gfx/layers/MacIOSurfaceHelpers.h | 2 +- gfx/layers/composite/GPUVideoTextureHost.h | 3 +- .../composite/RemoteTextureHostWrapper.h | 3 +- gfx/layers/composite/TextureHost.cpp | 5 ++- gfx/layers/composite/TextureHost.h | 13 ++++-- gfx/layers/d3d11/TextureD3D11.cpp | 3 +- gfx/layers/d3d11/TextureD3D11.h | 6 ++- gfx/layers/d3d11/TextureHostWrapperD3D11.h | 3 +- gfx/layers/ipc/CanvasTranslator.cpp | 44 ++++++++++++++++++- gfx/layers/ipc/CanvasTranslator.h | 5 +++ gfx/layers/opengl/DMABUFTextureHostOGL.h | 3 +- .../opengl/MacIOSurfaceTextureHostOGL.h | 5 ++- gfx/layers/opengl/TextureHostOGL.h | 12 +++-- gfx/layers/wr/WebRenderTextureHost.cpp | 5 ++- gfx/layers/wr/WebRenderTextureHost.h | 3 +- modules/libpref/init/StaticPrefList.yaml | 5 +++ 18 files changed, 113 insertions(+), 31 deletions(-) diff --git a/gfx/layers/DcompSurfaceImage.h b/gfx/layers/DcompSurfaceImage.h index c1eb41258067..4962793fb648 100644 --- a/gfx/layers/DcompSurfaceImage.h +++ b/gfx/layers/DcompSurfaceImage.h @@ -95,7 +95,8 @@ class DcompSurfaceHandleHost : public TextureHost { const char* Name() override { return "DcompSurfaceHandleHost"; } - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; } diff --git a/gfx/layers/MacIOSurfaceHelpers.cpp b/gfx/layers/MacIOSurfaceHelpers.cpp index ff5b59b626bf..d5cd00570aed 100644 --- a/gfx/layers/MacIOSurfaceHelpers.cpp +++ b/gfx/layers/MacIOSurfaceHelpers.cpp @@ -149,7 +149,7 @@ static nsresult CopyFromLockedMacIOSurface(MacIOSurface* aSurface, } already_AddRefed CreateSourceSurfaceFromMacIOSurface( - MacIOSurface* aSurface) { + MacIOSurface* aSurface, gfx::DataSourceSurface* aDataSurface) { aSurface->Lock(); auto scopeExit = MakeScopeExit([&]() { aSurface->Unlock(); }); @@ -163,10 +163,21 @@ already_AddRefed CreateSourceSurfaceFromMacIOSurface( ? SurfaceFormat::B8G8R8X8 : SurfaceFormat::B8G8R8A8; - RefPtr dataSurface = - Factory::CreateDataSourceSurface(size, format); - if (NS_WARN_IF(!dataSurface)) { - return nullptr; + RefPtr dataSurface; + if (aDataSurface) { + MOZ_ASSERT(aDataSurface->GetSize() == size); + MOZ_ASSERT(aDataSurface->GetFormat() == format); + if (aDataSurface->GetSize() == size && + aDataSurface->GetFormat() == format) { + dataSurface = aDataSurface; + } + } + + if (!dataSurface) { + dataSurface = Factory::CreateDataSourceSurface(size, format); + if (NS_WARN_IF(!dataSurface)) { + return nullptr; + } } DataSourceSurface::ScopedMap map(dataSurface, DataSourceSurface::WRITE); diff --git a/gfx/layers/MacIOSurfaceHelpers.h b/gfx/layers/MacIOSurfaceHelpers.h index 1f16df2e80b7..0784768ffc6c 100644 --- a/gfx/layers/MacIOSurfaceHelpers.h +++ b/gfx/layers/MacIOSurfaceHelpers.h @@ -24,7 +24,7 @@ namespace layers { // Unlike MacIOSurface::GetAsSurface, this also handles IOSurface formats // with multiple planes and does YCbCr to RGB conversion, if necessary. already_AddRefed CreateSourceSurfaceFromMacIOSurface( - MacIOSurface* aSurface); + MacIOSurface* aSurface, gfx::DataSourceSurface* aDataSurface = nullptr); nsresult CreateSurfaceDescriptorBufferFromMacIOSurface( MacIOSurface* aSurface, SurfaceDescriptorBuffer& aSdBuffer, diff --git a/gfx/layers/composite/GPUVideoTextureHost.h b/gfx/layers/composite/GPUVideoTextureHost.h index b4f6cc249ea6..205ced66b425 100644 --- a/gfx/layers/composite/GPUVideoTextureHost.h +++ b/gfx/layers/composite/GPUVideoTextureHost.h @@ -24,7 +24,8 @@ class GPUVideoTextureHost : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/composite/RemoteTextureHostWrapper.h b/gfx/layers/composite/RemoteTextureHostWrapper.h index d20bc406c0fe..2ad703bc58f5 100644 --- a/gfx/layers/composite/RemoteTextureHostWrapper.h +++ b/gfx/layers/composite/RemoteTextureHostWrapper.h @@ -27,7 +27,8 @@ class RemoteTextureHostWrapper : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; } diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index 8efafbac0787..90b0cc2b55d6 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -702,14 +702,15 @@ int32_t BufferTextureHost::GetCbCrStride() const { return 0; } -already_AddRefed BufferTextureHost::GetAsSurface() { +already_AddRefed BufferTextureHost::GetAsSurface( + gfx::DataSourceSurface* aSurface) { RefPtr result; if (mFormat == gfx::SurfaceFormat::UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return nullptr; } else if (mFormat == gfx::SurfaceFormat::YUV) { result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor( - GetBuffer(), mDescriptor.get_YCbCrDescriptor()); + GetBuffer(), mDescriptor.get_YCbCrDescriptor(), aSurface); if (NS_WARN_IF(!result)) { return nullptr; } diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 343ba6f6008c..319a3808dcd9 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -90,7 +90,7 @@ class TextureHostWrapperD3D11; class BigImageIterator { public: virtual void BeginBigImageIteration() = 0; - virtual void EndBigImageIteration(){}; + virtual void EndBigImageIteration() {}; virtual gfx::IntRect GetTileRect() = 0; virtual size_t GetTileCount() = 0; virtual bool NextTile() = 0; @@ -498,10 +498,14 @@ class TextureHost : public AtomicRefCountedWithFinalize { virtual void SetCropRect(nsIntRect aCropRect) {} /** - * Debug facility. + * Return TextureHost's data as DataSourceSurface. + * + * @param aSurface may be used as returned DataSourceSurface. + * * XXX - cool kids use Moz2D. See bug 882113. */ - virtual already_AddRefed GetAsSurface() = 0; + virtual already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface = nullptr) = 0; /** * XXX - Flags should only be set at creation time, this will be removed. @@ -813,7 +817,8 @@ class BufferTextureHost : public TextureHost { gfx::IntSize GetSize() const override { return mSize; } - already_AddRefed GetAsSurface() override; + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override; bool NeedsDeferredDeletion() const override { return TextureHost::NeedsDeferredDeletion() || UseExternalTextures(); diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 7a56504b8aec..70acb6339c34 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -921,7 +921,8 @@ bool DXGITextureHostD3D11::LockInternal() { return mIsLocked; } -already_AddRefed DXGITextureHostD3D11::GetAsSurface() { +already_AddRefed DXGITextureHostD3D11::GetAsSurface( + gfx::DataSourceSurface* aSurface) { switch (GetFormat()) { case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8A8: diff --git a/gfx/layers/d3d11/TextureD3D11.h b/gfx/layers/d3d11/TextureD3D11.h index 57de485de23c..cb245b1a1004 100644 --- a/gfx/layers/d3d11/TextureD3D11.h +++ b/gfx/layers/d3d11/TextureD3D11.h @@ -358,7 +358,8 @@ class DXGITextureHostD3D11 : public TextureHost { gfx::IntSize GetSize() const override { return mSize; } gfx::ColorRange GetColorRange() const override { return mColorRange; } - already_AddRefed GetAsSurface() override; + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override; void CreateRenderTexture( const wr::ExternalImageId& aExternalImageId) override; @@ -427,7 +428,8 @@ class DXGIYCbCrTextureHostD3D11 : public TextureHost { gfx::IntSize GetSize() const override { return mSize; } - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; } diff --git a/gfx/layers/d3d11/TextureHostWrapperD3D11.h b/gfx/layers/d3d11/TextureHostWrapperD3D11.h index dd0afc8be7ea..afeb577f1333 100644 --- a/gfx/layers/d3d11/TextureHostWrapperD3D11.h +++ b/gfx/layers/d3d11/TextureHostWrapperD3D11.h @@ -93,7 +93,8 @@ class TextureHostWrapperD3D11 : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp index 7895c7739b09..966d590631d3 100644 --- a/gfx/layers/ipc/CanvasTranslator.cpp +++ b/gfx/layers/ipc/CanvasTranslator.cpp @@ -865,6 +865,7 @@ void CanvasTranslator::PrepareShmem(int64_t aTextureId) { } void CanvasTranslator::ClearCachedResources() { + mUsedDataSurfaceForSurfaceDescriptor = nullptr; if (mSharedContext) { // If there are any DrawTargetWebgls, then try to cache their framebuffers // in software surfaces, just in case the GL context is lost. So long as @@ -1153,6 +1154,7 @@ bool CanvasTranslator::PushRemoteTexture(int64_t aTextureId, TextureData* aData, } void CanvasTranslator::ClearTextureInfo() { + mUsedDataSurfaceForSurfaceDescriptor = nullptr; for (auto const& entry : mTextureInfo) { if (entry.second.mTextureData) { entry.second.mTextureData->Unlock(); @@ -1214,6 +1216,36 @@ static bool SDIsSupportedRemoteDecoder(const SurfaceDescriptor& sd) { return false; } +already_AddRefed +CanvasTranslator::GetRecycledDataSurfaceForSurfaceDescriptor( + TextureHost* aTextureHost) { + if (!StaticPrefs::gfx_canvas_remote_recycle_used_data_surface()) { + return nullptr; + } + + auto& usedSurf = mUsedDataSurfaceForSurfaceDescriptor; + + bool isYuvVideo = false; + if (aTextureHost->AsMacIOSurfaceTextureHost()) { + if (aTextureHost->GetFormat() == SurfaceFormat::NV12 || + aTextureHost->GetFormat() == SurfaceFormat::YUV422) { + isYuvVideo = true; + } + } else if (aTextureHost->GetFormat() == gfx::SurfaceFormat::YUV) { + isYuvVideo = true; + } + + if (isYuvVideo && usedSurf && usedSurf->refCount() == 1 && + usedSurf->GetFormat() == gfx::SurfaceFormat::B8G8R8X8 && + aTextureHost->GetSize() == usedSurf->GetSize()) { + // Reuse previously used DataSourceSurface if it is not used and same + // size/format. + return usedSurf.forget(); + } + usedSurf = nullptr; + return nullptr; +} + already_AddRefed CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor( const SurfaceDescriptor& aDesc) { @@ -1244,11 +1276,19 @@ CanvasTranslator::LookupSourceSurfaceFromSurfaceDescriptor( if (subdescType == RemoteDecoderVideoSubDescriptor::TSurfaceDescriptorMacIOSurface) { MOZ_ASSERT(texture->AsMacIOSurfaceTextureHost()); - return texture->GetAsSurface(); + + RefPtr reuseSurf = + GetRecycledDataSurfaceForSurfaceDescriptor(texture); + RefPtr surf = texture->GetAsSurface(reuseSurf); + mUsedDataSurfaceForSurfaceDescriptor = surf; + return surf.forget(); } if (subdescType == RemoteDecoderVideoSubDescriptor::Tnull_t) { - RefPtr surf = texture->GetAsSurface(); + RefPtr reuseSurf = + GetRecycledDataSurfaceForSurfaceDescriptor(texture); + RefPtr surf = texture->GetAsSurface(reuseSurf); + mUsedDataSurfaceForSurfaceDescriptor = surf; return surf.forget(); } diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h index e2b6c587b4d4..575444d947ba 100644 --- a/gfx/layers/ipc/CanvasTranslator.h +++ b/gfx/layers/ipc/CanvasTranslator.h @@ -36,6 +36,7 @@ namespace layers { class SharedSurfacesHolder; class TextureData; +class TextureHost; class CanvasTranslator final : public gfx::InlineTranslator, public PCanvasParent { @@ -333,6 +334,9 @@ class CanvasTranslator final : public gfx::InlineTranslator, void ClearCachedResources(); + already_AddRefed + GetRecycledDataSurfaceForSurfaceDescriptor(TextureHost* aTextureHost); + const RefPtr mTranslationTaskQueue; const RefPtr mSharedSurfacesHolder; #if defined(XP_WIN) @@ -396,6 +400,7 @@ class CanvasTranslator final : public gfx::InlineTranslator, Atomic mIPDLClosed{false}; bool mIsInTransaction = false; bool mDeviceResetInProgress = false; + RefPtr mUsedDataSurfaceForSurfaceDescriptor; }; } // namespace layers diff --git a/gfx/layers/opengl/DMABUFTextureHostOGL.h b/gfx/layers/opengl/DMABUFTextureHostOGL.h index 13510a3c0345..4b57cf3d7ce4 100644 --- a/gfx/layers/opengl/DMABUFTextureHostOGL.h +++ b/gfx/layers/opengl/DMABUFTextureHostOGL.h @@ -28,7 +28,8 @@ class DMABUFTextureHostOGL : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h index d4aaa630de67..e3615c5f8476 100644 --- a/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h +++ b/gfx/layers/opengl/MacIOSurfaceTextureHostOGL.h @@ -34,9 +34,10 @@ class MacIOSurfaceTextureHostOGL : public TextureHost { gfx::SurfaceFormat GetFormat() const override; gfx::SurfaceFormat GetReadFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { RefPtr surf = - CreateSourceSurfaceFromMacIOSurface(GetMacIOSurface()); + CreateSourceSurfaceFromMacIOSurface(GetMacIOSurface(), aSurface); return surf->GetDataSurface(); } diff --git a/gfx/layers/opengl/TextureHostOGL.h b/gfx/layers/opengl/TextureHostOGL.h index 8f4ca187687b..6ac7c5939876 100644 --- a/gfx/layers/opengl/TextureHostOGL.h +++ b/gfx/layers/opengl/TextureHostOGL.h @@ -317,7 +317,8 @@ class GLTextureHost : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } @@ -396,7 +397,8 @@ class SurfaceTextureHost : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } @@ -509,7 +511,8 @@ class AndroidHardwareBufferTextureHost : public TextureHost { void NotifyNotUsed() override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } @@ -615,7 +618,8 @@ class EGLImageTextureHost final : public TextureHost { gfx::SurfaceFormat GetFormat() const override; - already_AddRefed GetAsSurface() override { + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override { return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING) } diff --git a/gfx/layers/wr/WebRenderTextureHost.cpp b/gfx/layers/wr/WebRenderTextureHost.cpp index 707588a1f363..99abc7b2a11e 100644 --- a/gfx/layers/wr/WebRenderTextureHost.cpp +++ b/gfx/layers/wr/WebRenderTextureHost.cpp @@ -75,8 +75,9 @@ void WebRenderTextureHost::UnbindTextureSource() { TextureHost::UnbindTextureSource(); } -already_AddRefed WebRenderTextureHost::GetAsSurface() { - return mWrappedTextureHost->GetAsSurface(); +already_AddRefed WebRenderTextureHost::GetAsSurface( + gfx::DataSourceSurface* aSurface) { + return mWrappedTextureHost->GetAsSurface(aSurface); } gfx::ColorDepth WebRenderTextureHost::GetColorDepth() const { diff --git a/gfx/layers/wr/WebRenderTextureHost.h b/gfx/layers/wr/WebRenderTextureHost.h index 21e5e4780e83..5588d3485ee9 100644 --- a/gfx/layers/wr/WebRenderTextureHost.h +++ b/gfx/layers/wr/WebRenderTextureHost.h @@ -43,7 +43,8 @@ class WebRenderTextureHost : public TextureHost { // Please check TextureHost::GetReadFormat(). gfx::SurfaceFormat GetReadFormat() const override; - already_AddRefed GetAsSurface() override; + already_AddRefed GetAsSurface( + gfx::DataSourceSurface* aSurface) override; gfx::ColorDepth GetColorDepth() const override; gfx::YUVColorSpace GetYUVColorSpace() const override; diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 5e858c59cf37..c96857046bbe 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -5873,6 +5873,11 @@ value: true mirror: always +- name: gfx.canvas.remote.recycle-used-data-surface + type: RelaxedAtomicBool + value: false + mirror: always + - name: gfx.canvas.willreadfrequently.enabled type: bool #if defined(XP_WIN)