Bug 1794380 - Fix RemoteTexture with WebGL sync present on Android r=gfx-reviewers,lsalzman

The change addressed followings problems.

- Recycling of gl::SharedSurface by RemoteTextureMap is not handled by gl::SwapChain.
- PrepareForUse()/NotifyNotUsed() of remote texture's TextureHost(SurfaceTextureHost) is not handled
- Wrapping of RenderAndroidSurfaceTextureHost by RenderTextureHostWrapper is not handled

PrepareForUse()/NotifyNotUsed() is called based on compositor ref count of TextureHost. Normally TextureHost is wrapped by WebRenderTextureHost, then the WebRenderTextureHost handles PrepareForUse()/NotifyNotUsed(). But in remote texture case, WebRenderTextureHost wraps RemoteTextureHostWrapper. And compositable ref of remote texture's TextureHost is updated within RemoteTextureMap::mMutex. Then PrepareForUse()/NotifyNotUsed() happen outside of WebRenderTextureHost in non compositor thread.

With pref gfx.canvas.accelerated=true, canvas renderings were broken on android emulator. The boroken rendering seemed to happen by GL of android emulator. The boroken rendering did not happen with tests on android hardware.

Differential Revision: https://phabricator.services.mozilla.com/D159261
This commit is contained in:
sotaro 2022-12-07 12:40:02 +00:00
parent 7e770c016b
commit ad6c294e3c
14 changed files with 66 additions and 7 deletions

View File

@ -1193,6 +1193,7 @@ bool WebGLContext::PushRemoteTexture(WebGLFramebuffer* fb,
switch (desc->type()) {
case layers::SurfaceDescriptor::TSurfaceDescriptorD3D10:
case layers::SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
case layers::SurfaceDescriptor::TSurfaceTextureDescriptor:
keepAlive = surf;
break;
default:

View File

@ -42,7 +42,11 @@ UniquePtr<SwapChainPresenter> SwapChain::Acquire(
}
}
if (!mPool.empty() && (!kPoolSize || mPool.size() == kPoolSize)) {
// When mDestroyedCallback exists, recycling of SharedSurfaces is managed by
// the owner of the SwapChain by calling StoreRecycledSurface().
const auto poolSize = mDestroyedCallback ? 0 : kPoolSize;
if (!mPool.empty() && (!poolSize || mPool.size() == poolSize)) {
surf = mPool.front();
mPool.pop();
}
@ -52,7 +56,7 @@ UniquePtr<SwapChainPresenter> SwapChain::Acquire(
surf.reset(uniquePtrSurf.release());
}
mPool.push(surf);
while (mPool.size() > kPoolSize) {
while (mPool.size() > poolSize) {
mPool.pop();
}

View File

@ -77,6 +77,7 @@ class SwapChain final {
void SetDestroyedCallback(std::function<void()>&& aDestroyedCallback) {
MOZ_ASSERT(!mDestroyedCallback);
mDestroyedCallback = std::move(aDestroyedCallback);
mPool = {};
}
};

View File

@ -206,6 +206,13 @@ bool GPUVideoTextureHost::IsWrappingBufferTextureHost() {
return false;
}
bool GPUVideoTextureHost::IsWrappingSurfaceTextureHost() {
if (EnsureWrappedTextureHost()) {
return EnsureWrappedTextureHost()->IsWrappingSurfaceTextureHost();
}
return false;
}
TextureHostType GPUVideoTextureHost::GetTextureHostType() {
if (!mWrappedTextureHost) {
return TextureHostType::Unknown;

View File

@ -64,6 +64,7 @@ class GPUVideoTextureHost : public TextureHost {
void NotifyNotUsed() override;
bool IsWrappingBufferTextureHost() override;
bool IsWrappingSurfaceTextureHost() override;
TextureHostType GetTextureHostType() override;

View File

@ -163,7 +163,7 @@ void RemoteTextureHostWrapper::UnbindTextureSource() {}
void RemoteTextureHostWrapper::NotifyNotUsed() {
if (mRemoteTextureForDisplayList) {
// Release mRemoteTextureHost.
// Release mRemoteTextureForDisplayList.
RemoteTextureMap::Get()->ReleaseRemoteTextureHostForDisplayList(this);
}
MOZ_ASSERT(!mRemoteTextureForDisplayList);
@ -208,4 +208,11 @@ void RemoteTextureHostWrapper::SetRemoteTextureHostForDisplayList(
mRemoteTextureForDisplayList = aTextureHost;
}
bool RemoteTextureHostWrapper::IsWrappingSurfaceTextureHost() {
if (!mRemoteTextureForDisplayList) {
return false;
}
return mRemoteTextureForDisplayList->IsWrappingSurfaceTextureHost();
}
} // namespace mozilla::layers

View File

@ -74,6 +74,8 @@ class RemoteTextureHostWrapper : public TextureHost {
TextureHostType GetTextureHostType() override;
bool IsWrappingSurfaceTextureHost() override;
bool CheckIsReadyForRendering();
void ApplyTextureFlagsToRemoteTexture();

View File

@ -391,8 +391,21 @@ void TextureHost::RecycleTexture(TextureFlags aFlags) {
mFlags = aFlags;
}
void TextureHost::PrepareForUse() {
if ((mFlags & TextureFlags::REMOTE_TEXTURE) && AsSurfaceTextureHost()) {
MOZ_ASSERT(mExternalImageId.isSome());
// Call PrepareForUse on render thread.
// See RenderAndroidSurfaceTextureHostOGL::PrepareForUse.
wr::RenderThread::Get()->PrepareForUse(*mExternalImageId);
}
}
void TextureHost::NotifyNotUsed() {
if (!mActor) {
if ((mFlags & TextureFlags::REMOTE_TEXTURE) && AsSurfaceTextureHost()) {
MOZ_ASSERT(mExternalImageId.isSome());
wr::RenderThread::Get()->NotifyNotUsed(*mExternalImageId);
}
return;
}

View File

@ -609,6 +609,7 @@ class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> {
}
virtual bool IsWrappingBufferTextureHost() { return false; }
virtual bool IsWrappingSurfaceTextureHost() { return false; }
// Create the corresponding RenderTextureHost type of this texture, and
// register the RenderTextureHost into render thread.
@ -726,7 +727,7 @@ class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> {
/**
* Called when mCompositableCount becomes from 0 to 1.
*/
virtual void PrepareForUse() {}
virtual void PrepareForUse();
/**
* Called when mCompositableCount becomes 0.

View File

@ -408,6 +408,8 @@ class SurfaceTextureHost : public TextureHost {
SurfaceTextureHost* AsSurfaceTextureHost() override { return this; }
bool IsWrappingSurfaceTextureHost() override { return true; }
void CreateRenderTexture(
const wr::ExternalImageId& aExternalImageId) override;

View File

@ -101,7 +101,10 @@ gfx::SurfaceFormat WebRenderTextureHost::GetFormat() const {
void WebRenderTextureHost::NotifyNotUsed() {
#ifdef MOZ_WIDGET_ANDROID
if (mWrappedTextureHost->AsSurfaceTextureHost()) {
// When SurfaceTextureHost is wrapped by RemoteTextureHostWrapper,
// NotifyNotUsed() is handled by SurfaceTextureHost.
if (IsWrappingSurfaceTextureHost() &&
!mWrappedTextureHost->AsRemoteTextureHostWrapper()) {
wr::RenderThread::Get()->NotifyNotUsed(GetExternalImageKey());
}
#endif
@ -113,7 +116,7 @@ void WebRenderTextureHost::NotifyNotUsed() {
void WebRenderTextureHost::MaybeNotifyForUse(wr::TransactionBuilder& aTxn) {
#if defined(MOZ_WIDGET_ANDROID)
if (mWrappedTextureHost->AsSurfaceTextureHost()) {
if (IsWrappingSurfaceTextureHost()) {
wr::RenderThread::Get()->NotifyForUse(GetExternalImageKey());
aTxn.Notify(wr::Checkpoint::FrameTexturesUpdated,
MakeUnique<ScheduleHandleRenderTextureOps>());
@ -125,8 +128,15 @@ bool WebRenderTextureHost::IsWrappingBufferTextureHost() {
return mWrappedTextureHost->IsWrappingBufferTextureHost();
}
bool WebRenderTextureHost::IsWrappingSurfaceTextureHost() {
return mWrappedTextureHost->IsWrappingSurfaceTextureHost();
}
void WebRenderTextureHost::PrepareForUse() {
if (mWrappedTextureHost->AsSurfaceTextureHost() ||
// When SurfaceTextureHost is wrapped by RemoteTextureHostWrapper,
// PrepareForUse() is handled by SurfaceTextureHost.
if ((IsWrappingSurfaceTextureHost() &&
!mWrappedTextureHost->AsRemoteTextureHostWrapper()) ||
mWrappedTextureHost->IsWrappingBufferTextureHost()) {
// Call PrepareForUse on render thread.
// See RenderAndroidSurfaceTextureHostOGL::PrepareForUse.

View File

@ -62,6 +62,7 @@ class WebRenderTextureHost : public TextureHost {
}
bool IsWrappingBufferTextureHost() override;
bool IsWrappingSurfaceTextureHost() override;
virtual void PrepareForUse() override;

View File

@ -170,6 +170,14 @@ RenderTextureHostSWGL* RenderTextureHostWrapper::AsRenderTextureHostSWGL() {
return mTextureHost->AsRenderTextureHostSWGL();
}
RenderAndroidSurfaceTextureHost*
RenderTextureHostWrapper::AsRenderAndroidSurfaceTextureHost() {
if (!mTextureHost) {
return nullptr;
}
return mTextureHost->AsRenderAndroidSurfaceTextureHost();
}
RenderTextureHostSWGL* RenderTextureHostWrapper::EnsureRenderTextureHostSWGL()
const {
if (mTextureId.isSome()) {

View File

@ -43,6 +43,7 @@ class RenderTextureHostWrapper final : public RenderTextureHostSWGL {
RenderDXGITextureHost* AsRenderDXGITextureHost() override;
RenderDXGIYCbCrTextureHost* AsRenderDXGIYCbCrTextureHost() override;
RenderDcompSurfaceTextureHost* AsRenderDcompSurfaceTextureHost() override;
RenderAndroidSurfaceTextureHost* AsRenderAndroidSurfaceTextureHost() override;
RenderTextureHostSWGL* AsRenderTextureHostSWGL() override;
bool IsWrappingAsyncRemoteTexture() override;