mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1529870 - Add handling of single buffer mode android SurfaceTexture r=nical
When SurfaceTexture is single buffer mode, UpdateTexImage() should be called only once for each publish. If UpdateTexImage() is called more than once, it causes hand on puglish side. Differential Revision: https://phabricator.services.mozilla.com/D24483 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
1cd564b971
commit
817c9ec8c9
@ -57,6 +57,7 @@ class SurfaceDescriptor;
|
||||
class HostIPCAllocator;
|
||||
class ISurfaceAllocator;
|
||||
class MacIOSurfaceTextureHostOGL;
|
||||
class SurfaceTextureHost;
|
||||
class TextureHostOGL;
|
||||
class TextureReadLock;
|
||||
class TextureSourceOGL;
|
||||
@ -623,6 +624,7 @@ class TextureHost : public AtomicRefCountedWithFinalize<TextureHost> {
|
||||
return nullptr;
|
||||
}
|
||||
virtual WebRenderTextureHost* AsWebRenderTextureHost() { return nullptr; }
|
||||
virtual SurfaceTextureHost* AsSurfaceTextureHost() { return nullptr; }
|
||||
|
||||
// Create the corresponding RenderTextureHost type of this texture, and
|
||||
// register the RenderTextureHost into render thread.
|
||||
|
@ -437,6 +437,8 @@ class SurfaceTextureHost : public TextureHost {
|
||||
|
||||
virtual const char* Name() override { return "SurfaceTextureHost"; }
|
||||
|
||||
virtual SurfaceTextureHost* AsSurfaceTextureHost() override { return this; }
|
||||
|
||||
virtual void CreateRenderTexture(
|
||||
const wr::ExternalImageId& aExternalImageId) override;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc
|
||||
#include "mozilla/layers/LayerManagerComposite.h" // for TexturedEffect, Effect, etc
|
||||
#include "mozilla/layers/WebRenderBridgeParent.h"
|
||||
#include "mozilla/layers/WebRenderTextureHost.h"
|
||||
#include "mozilla/layers/AsyncImagePipelineManager.h"
|
||||
#include "nsAString.h"
|
||||
#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
|
||||
@ -163,6 +164,13 @@ void WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTexture && aTexture->AsWebRenderTextureHost()) {
|
||||
// If WebRenderTextureHost wraps SurfaceTextureHost, it is important to call
|
||||
// PrepareForUse for each texture that we receive.
|
||||
// See RenderAndroidSurfaceTextureHostOGL::PrepareForUse.
|
||||
aTexture->AsWebRenderTextureHost()->PrepareForUse();
|
||||
}
|
||||
|
||||
mCurrentTextureHost = aTexture;
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,10 @@
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "mozilla/layers/TextureHostOGL.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
@ -91,6 +95,25 @@ gfx::SurfaceFormat WebRenderTextureHost::GetFormat() const {
|
||||
return mWrappedTextureHost->GetFormat();
|
||||
}
|
||||
|
||||
void WebRenderTextureHost::NotifyNotUsed() {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
if (mWrappedTextureHost && mWrappedTextureHost->AsSurfaceTextureHost()) {
|
||||
wr::RenderThread::Get()->NotifyNotUsed(wr::AsUint64(mExternalImageId));
|
||||
}
|
||||
#endif
|
||||
TextureHost::NotifyNotUsed();
|
||||
}
|
||||
|
||||
void WebRenderTextureHost::PrepareForUse() {
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
if (mWrappedTextureHost && mWrappedTextureHost->AsSurfaceTextureHost()) {
|
||||
// Call PrepareForUse on render thread.
|
||||
// See RenderAndroidSurfaceTextureHostOGL::PrepareForUse.
|
||||
wr::RenderThread::Get()->PrepareForUse(wr::AsUint64(mExternalImageId));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat WebRenderTextureHost::GetReadFormat() const {
|
||||
if (!mWrappedTextureHost) {
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
|
@ -39,6 +39,8 @@ class WebRenderTextureHost : public TextureHost {
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual void NotifyNotUsed() override;
|
||||
|
||||
// Return the format used for reading the texture. Some hardware specific
|
||||
// textureHosts use their special data representation internally, but we could
|
||||
// treat these textureHost as the read-format when we read them.
|
||||
@ -62,6 +64,8 @@ class WebRenderTextureHost : public TextureHost {
|
||||
return this;
|
||||
}
|
||||
|
||||
virtual void PrepareForUse();
|
||||
|
||||
wr::ExternalImageId GetExternalImageKey() { return mExternalImageId; }
|
||||
|
||||
int32_t GetRGBStride();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "RenderAndroidSurfaceTextureHostOGL.h"
|
||||
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "GLContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -15,16 +16,24 @@ namespace wr {
|
||||
RenderAndroidSurfaceTextureHostOGL::RenderAndroidSurfaceTextureHostOGL(
|
||||
const java::GeckoSurfaceTexture::GlobalRef& aSurfTex, gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat, bool aContinuousUpdate)
|
||||
: mSurfTex(aSurfTex), mSize(aSize) {
|
||||
: mSurfTex(aSurfTex),
|
||||
mSize(aSize),
|
||||
mIsPrepared(false),
|
||||
mAttachedToGLContext(false) {
|
||||
MOZ_COUNT_CTOR_INHERITED(RenderAndroidSurfaceTextureHostOGL,
|
||||
RenderTextureHostOGL);
|
||||
|
||||
if (mSurfTex) {
|
||||
mSurfTex->IncrementUse();
|
||||
}
|
||||
|
||||
if (mSurfTex && !mSurfTex->IsSingleBuffer()) {
|
||||
mIsPrepared = true;
|
||||
}
|
||||
}
|
||||
|
||||
RenderAndroidSurfaceTextureHostOGL::~RenderAndroidSurfaceTextureHostOGL() {
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
MOZ_COUNT_DTOR_INHERITED(RenderAndroidSurfaceTextureHostOGL,
|
||||
RenderTextureHostOGL);
|
||||
DeleteTextureHandle();
|
||||
@ -51,30 +60,20 @@ wr::WrExternalImage RenderAndroidSurfaceTextureHostOGL::Lock(
|
||||
MOZ_ASSERT(aChannelIndex == 0);
|
||||
|
||||
if (mGL.get() != aGL) {
|
||||
// release the texture handle in the previous gl context
|
||||
DeleteTextureHandle();
|
||||
mGL = aGL;
|
||||
mGL->MakeCurrent();
|
||||
// This should not happen. On android, SharedGL is used.
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected GL context");
|
||||
return InvalidToWrExternalImage();
|
||||
}
|
||||
|
||||
if (!mSurfTex || !mGL || !mGL->MakeCurrent()) {
|
||||
return InvalidToWrExternalImage();
|
||||
}
|
||||
|
||||
if (!mSurfTex->IsAttachedToGLContext((int64_t)mGL.get())) {
|
||||
GLuint texName;
|
||||
mGL->fGenTextures(1, &texName);
|
||||
// Cache rendering filter.
|
||||
if (!mAttachedToGLContext) {
|
||||
// Cache new rendering filter.
|
||||
mCachedRendering = aRendering;
|
||||
ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
|
||||
LOCAL_GL_TEXTURE_EXTERNAL_OES, texName,
|
||||
aRendering);
|
||||
|
||||
if (NS_FAILED(mSurfTex->AttachToGLContext((int64_t)mGL.get(), texName))) {
|
||||
MOZ_ASSERT(0);
|
||||
mGL->fDeleteTextures(1, &texName);
|
||||
if (!EnsureAttachedToGLContext()) {
|
||||
return InvalidToWrExternalImage();
|
||||
;
|
||||
}
|
||||
} else if (IsFilterUpdateNecessary(aRendering)) {
|
||||
// Cache new rendering filter.
|
||||
@ -84,11 +83,10 @@ wr::WrExternalImage RenderAndroidSurfaceTextureHostOGL::Lock(
|
||||
mSurfTex->GetTexName(), aRendering);
|
||||
}
|
||||
|
||||
// XXX Call UpdateTexImage() only when it is necessary.
|
||||
// For now, alyways call UpdateTexImage().
|
||||
// if (mContinuousUpdate) {
|
||||
mSurfTex->UpdateTexImage();
|
||||
//}
|
||||
// Bug 1507078, Call UpdateTexImage() only when mContinuousUpdate is true
|
||||
if (mSurfTex && !mSurfTex->IsSingleBuffer()) {
|
||||
mSurfTex->UpdateTexImage();
|
||||
}
|
||||
|
||||
return NativeTextureToWrExternalImage(mSurfTex->GetTexName(), 0, 0,
|
||||
mSize.width, mSize.height);
|
||||
@ -97,8 +95,67 @@ wr::WrExternalImage RenderAndroidSurfaceTextureHostOGL::Lock(
|
||||
void RenderAndroidSurfaceTextureHostOGL::Unlock() {}
|
||||
|
||||
void RenderAndroidSurfaceTextureHostOGL::DeleteTextureHandle() {
|
||||
// XXX Do we need to call mSurfTex->DetachFromGLContext() here?
|
||||
// But Surface texture is shared among many SurfaceTextureHosts.
|
||||
NotifyNotUsed();
|
||||
}
|
||||
|
||||
bool RenderAndroidSurfaceTextureHostOGL::EnsureAttachedToGLContext() {
|
||||
if (mAttachedToGLContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mGL) {
|
||||
mGL = RenderThread::Get()->SharedGL();
|
||||
}
|
||||
|
||||
if (!mSurfTex || !mGL || !mGL->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mSurfTex->IsAttachedToGLContext((int64_t)mGL.get())) {
|
||||
GLuint texName;
|
||||
mGL->fGenTextures(1, &texName);
|
||||
ActivateBindAndTexParameteri(mGL, LOCAL_GL_TEXTURE0,
|
||||
LOCAL_GL_TEXTURE_EXTERNAL_OES, texName,
|
||||
mCachedRendering);
|
||||
|
||||
if (NS_FAILED(mSurfTex->AttachToGLContext((int64_t)mGL.get(), texName))) {
|
||||
MOZ_ASSERT(0);
|
||||
mGL->fDeleteTextures(1, &texName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
mAttachedToGLContext = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderAndroidSurfaceTextureHostOGL::PrepareForUse() {
|
||||
// When SurfaceTexture is single buffer mode, UpdateTexImage neeeds to be
|
||||
// called only once for each publish. If UpdateTexImage is called more
|
||||
// than once, it causes hang on puglish side. And UpdateTexImage needs to
|
||||
// be called on render thread, since the SurfaceTexture is consumed on render
|
||||
// thread.
|
||||
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
|
||||
EnsureAttachedToGLContext();
|
||||
|
||||
if (mSurfTex && mSurfTex->IsSingleBuffer() && !mIsPrepared) {
|
||||
mSurfTex->UpdateTexImage();
|
||||
mIsPrepared = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderAndroidSurfaceTextureHostOGL::NotifyNotUsed() {
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
|
||||
EnsureAttachedToGLContext();
|
||||
|
||||
if (mSurfTex && mSurfTex->IsSingleBuffer() && mIsPrepared) {
|
||||
mGL->MakeCurrent();
|
||||
mSurfTex->ReleaseTexImage();
|
||||
mIsPrepared = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace wr
|
||||
|
@ -28,14 +28,20 @@ class RenderAndroidSurfaceTextureHostOGL final : public RenderTextureHostOGL {
|
||||
virtual gfx::IntSize GetSize(uint8_t aChannelIndex) const override;
|
||||
virtual GLuint GetGLHandle(uint8_t aChannelIndex) const override;
|
||||
|
||||
virtual void PrepareForUse() override;
|
||||
virtual void NotifyNotUsed() override;
|
||||
|
||||
private:
|
||||
virtual ~RenderAndroidSurfaceTextureHostOGL();
|
||||
void DeleteTextureHandle();
|
||||
bool EnsureAttachedToGLContext();
|
||||
|
||||
const mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
|
||||
const gfx::IntSize mSize;
|
||||
// XXX const bool mContinuousUpdate;
|
||||
// XXX const bool mIgnoreTransform;
|
||||
bool mIsPrepared;
|
||||
bool mAttachedToGLContext;
|
||||
|
||||
RefPtr<gl::GLContext> mGL;
|
||||
};
|
||||
|
@ -25,7 +25,10 @@ void ActivateBindAndTexParameteri(gl::GLContext* aGL, GLenum aActiveTexture,
|
||||
: LOCAL_GL_LINEAR);
|
||||
}
|
||||
|
||||
RenderTextureHost::RenderTextureHost() { MOZ_COUNT_CTOR(RenderTextureHost); }
|
||||
RenderTextureHost::RenderTextureHost()
|
||||
: mCachedRendering(wr::ImageRendering::Auto) {
|
||||
MOZ_COUNT_CTOR(RenderTextureHost);
|
||||
}
|
||||
|
||||
RenderTextureHost::~RenderTextureHost() {
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
|
@ -45,6 +45,9 @@ class RenderTextureHost {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual void PrepareForUse() {}
|
||||
virtual void NotifyNotUsed() {}
|
||||
|
||||
protected:
|
||||
virtual ~RenderTextureHost();
|
||||
|
||||
|
@ -612,6 +612,52 @@ void RenderThread::UnregisterExternalImage(uint64_t aExternalImageId) {
|
||||
}
|
||||
}
|
||||
|
||||
void RenderThread::PrepareForUse(uint64_t aExternalImageId) {
|
||||
if (!IsInRenderThread()) {
|
||||
Loop()->PostTask(NewRunnableMethod<uint64_t>(
|
||||
"RenderThread::PrepareForUse", this, &RenderThread::PrepareForUse,
|
||||
aExternalImageId));
|
||||
return;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mRenderTextureMapLock);
|
||||
if (mHasShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = mRenderTextures.find(aExternalImageId);
|
||||
MOZ_ASSERT(it != mRenderTextures.end());
|
||||
if (it == mRenderTextures.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<RenderTextureHost> texture = it->second;
|
||||
texture->PrepareForUse();
|
||||
}
|
||||
|
||||
void RenderThread::NotifyNotUsed(uint64_t aExternalImageId) {
|
||||
if (!IsInRenderThread()) {
|
||||
Loop()->PostTask(NewRunnableMethod<uint64_t>(
|
||||
"RenderThread::NotifyNotUsed", this, &RenderThread::NotifyNotUsed,
|
||||
aExternalImageId));
|
||||
return;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(mRenderTextureMapLock);
|
||||
if (mHasShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = mRenderTextures.find(aExternalImageId);
|
||||
MOZ_ASSERT(it != mRenderTextures.end());
|
||||
if (it == mRenderTextures.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<RenderTextureHost> texture = it->second;
|
||||
texture->NotifyNotUsed();
|
||||
}
|
||||
|
||||
void RenderThread::UpdateRenderTextureHost(uint64_t aSrcExternalImageId,
|
||||
uint64_t aWrappedExternalImageId) {
|
||||
MOZ_ASSERT(aSrcExternalImageId != aWrappedExternalImageId);
|
||||
|
@ -187,6 +187,12 @@ class RenderThread final {
|
||||
/// Can be called from any thread.
|
||||
void UnregisterExternalImage(uint64_t aExternalImageId);
|
||||
|
||||
/// Can be called from any thread.
|
||||
void PrepareForUse(uint64_t aExternalImageId);
|
||||
|
||||
/// Can be called from any thread.
|
||||
void NotifyNotUsed(uint64_t aExternalImageId);
|
||||
|
||||
/// Can only be called from the render thread.
|
||||
void UpdateRenderTextureHost(uint64_t aSrcExternalImageId,
|
||||
uint64_t aWrappedExternalImageId);
|
||||
|
Loading…
Reference in New Issue
Block a user