зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1544642 - Do not bind SurfaceTexture of video to gl context if it is used by WebGL r=nical
GeckoSurfaceTexture could bind to only one GL context at once. With WebRender, GeckoSurfaceTexture is soon bounded to sharedGL on render thread. It caused the problem if GeckoSurfaceTexture is rendered to WebGL. It could happen only for video's GeckoSurfaceTexture. To avoid the problem, the GeckoSurfaceTexture is bound to gl context when it is actually rendered on WebRender. Differential Revision: https://phabricator.services.mozilla.com/D27873 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
1521c6622b
Коммит
00fa00cad3
|
@ -291,6 +291,8 @@ Maybe<TextureHost::ResourceUpdateOp> AsyncImagePipelineManager::UpdateImageKeys(
|
|||
return UpdateWithoutExternalImage(texture, aKeys[0], op, aMaybeFastTxn);
|
||||
}
|
||||
|
||||
wrTexture->MaybeNofityForUse(aMaybeFastTxn);
|
||||
|
||||
if (useWrTextureWrapper && aPipeline->mWrTextureWrapper) {
|
||||
MOZ_ASSERT(canUpdate);
|
||||
// Reuse WebRenderTextureHostWrapper. With it, rendered frame could be
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "mozilla/webrender/RenderThread.h"
|
||||
#include "mozilla/webrender/WebRenderAPI.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "mozilla/layers/TextureHostOGL.h"
|
||||
|
@ -17,6 +18,24 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ScheduleNofityForUse : public wr::NotificationHandler {
|
||||
public:
|
||||
explicit ScheduleNofityForUse(uint64_t aExternalImageId)
|
||||
: mExternalImageId(aExternalImageId) {}
|
||||
|
||||
virtual void Notify(wr::Checkpoint aCheckpoint) override {
|
||||
if (aCheckpoint == wr::Checkpoint::FrameTexturesUpdated) {
|
||||
MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
|
||||
wr::RenderThread::Get()->NofityForUse(mExternalImageId);
|
||||
} else {
|
||||
MOZ_ASSERT(aCheckpoint == wr::Checkpoint::TransactionDropped);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
uint64_t mExternalImageId;
|
||||
};
|
||||
|
||||
WebRenderTextureHost::WebRenderTextureHost(
|
||||
const SurfaceDescriptor& aDesc, TextureFlags aFlags, TextureHost* aTexture,
|
||||
wr::ExternalImageId& aExternalImageId)
|
||||
|
@ -182,5 +201,17 @@ bool WebRenderTextureHost::NeedsYFlip() const {
|
|||
return yFlip;
|
||||
}
|
||||
|
||||
void WebRenderTextureHost::MaybeNofityForUse(wr::TransactionBuilder& aTxn) {
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
if (!mWrappedTextureHost->AsSurfaceTextureHost()) {
|
||||
return;
|
||||
}
|
||||
// SurfaceTexture of video needs NofityForUse() to detect if it is rendered
|
||||
// on WebRender.
|
||||
aTxn.Notify(wr::Checkpoint::FrameTexturesUpdated,
|
||||
MakeUnique<ScheduleNofityForUse>(wr::AsUint64(mExternalImageId)));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -84,6 +84,8 @@ class WebRenderTextureHost : public TextureHost {
|
|||
|
||||
bool NeedsYFlip() const override;
|
||||
|
||||
void MaybeNofityForUse(wr::TransactionBuilder& aTxn);
|
||||
|
||||
protected:
|
||||
void CreateRenderTextureHost(const SurfaceDescriptor& aDesc,
|
||||
TextureHost* aTexture);
|
||||
|
|
|
@ -133,39 +133,81 @@ bool RenderAndroidSurfaceTextureHostOGL::EnsureAttachedToGLContext() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RenderAndroidSurfaceTextureHostOGL::CheckIfAttachedToGLContext() {
|
||||
if (mAttachedToGLContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mGL) {
|
||||
mGL = RenderThread::Get()->SharedGL();
|
||||
}
|
||||
|
||||
if (!mSurfTex || !mGL || !mGL->MakeCurrent()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mSurfTex->IsAttachedToGLContext((int64_t)mGL.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mAttachedToGLContext = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RenderAndroidSurfaceTextureHostOGL::PrepareForUse() {
|
||||
// When SurfaceTexture is single buffer mode, UpdateTexImage needs 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());
|
||||
MOZ_ASSERT(mPrepareStatus == STATUS_NONE);
|
||||
|
||||
EnsureAttachedToGLContext();
|
||||
|
||||
if (mContinuousUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPrepareStatus = STATUS_PREPARE_NEEDED;
|
||||
mPrepareStatus = STATUS_MIGHT_BE_USED;
|
||||
|
||||
if (mSurfTex && mSurfTex->IsSingleBuffer()) {
|
||||
// When SurfaceTexture is single buffer mode, it is OK to call
|
||||
// UpdateTexImage() here.
|
||||
EnsureAttachedToGLContext();
|
||||
mSurfTex->UpdateTexImage();
|
||||
mPrepareStatus = STATUS_PREPARED;
|
||||
} else {
|
||||
// If SurfaceTexture is already bound to gl texture, it is already used for
|
||||
// rendering to WebRender.
|
||||
// During video playback, there is a case that rendering is skipped. In this
|
||||
// case, NofityForUse() is not called. But we want to call UpdateTexImage()
|
||||
// for adjusting SurfaceTexture's buffer status.
|
||||
if (CheckIfAttachedToGLContext()) {
|
||||
mPrepareStatus = STATUS_PREPARE_NEEDED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderAndroidSurfaceTextureHostOGL::NofityForUse() {
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
|
||||
if (mPrepareStatus == STATUS_MIGHT_BE_USED) {
|
||||
// This happens when SurfaceTexture of video is rendered on WebRender and
|
||||
// SurfaceTexture is not bounded to gl context yet.
|
||||
// It is necessary to handle a case that SurfaceTexture is not rendered on
|
||||
// WebRender, instead rendered to WebGL.
|
||||
// It is not a good way. But it is same to Compositor rendering.
|
||||
MOZ_ASSERT(!mSurfTex || !mSurfTex->IsSingleBuffer());
|
||||
EnsureAttachedToGLContext();
|
||||
mPrepareStatus = STATUS_PREPARE_NEEDED;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderAndroidSurfaceTextureHostOGL::NotifyNotUsed() {
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
|
||||
EnsureAttachedToGLContext();
|
||||
|
||||
if (mSurfTex && mSurfTex->IsSingleBuffer() &&
|
||||
mPrepareStatus == STATUS_PREPARED) {
|
||||
EnsureAttachedToGLContext();
|
||||
// Release SurfaceTexture's buffer to client side.
|
||||
mGL->MakeCurrent();
|
||||
mSurfTex->ReleaseTexImage();
|
||||
|
@ -173,6 +215,7 @@ void RenderAndroidSurfaceTextureHostOGL::NotifyNotUsed() {
|
|||
// This could happen when video frame was skipped. UpdateTexImage() neeeds
|
||||
// to be called for adjusting SurfaceTexture's buffer status.
|
||||
MOZ_ASSERT(!mSurfTex->IsSingleBuffer());
|
||||
EnsureAttachedToGLContext();
|
||||
mSurfTex->UpdateTexImage();
|
||||
}
|
||||
|
||||
|
|
|
@ -29,14 +29,21 @@ class RenderAndroidSurfaceTextureHostOGL final : public RenderTextureHostOGL {
|
|||
GLuint GetGLHandle(uint8_t aChannelIndex) const override;
|
||||
|
||||
virtual void PrepareForUse() override;
|
||||
virtual void NofityForUse() override;
|
||||
virtual void NotifyNotUsed() override;
|
||||
|
||||
private:
|
||||
virtual ~RenderAndroidSurfaceTextureHostOGL();
|
||||
void DeleteTextureHandle();
|
||||
bool EnsureAttachedToGLContext();
|
||||
bool CheckIfAttachedToGLContext();
|
||||
|
||||
enum PrepareStatus { STATUS_NONE, STATUS_PREPARE_NEEDED, STATUS_PREPARED };
|
||||
enum PrepareStatus {
|
||||
STATUS_NONE,
|
||||
STATUS_MIGHT_BE_USED,
|
||||
STATUS_PREPARE_NEEDED,
|
||||
STATUS_PREPARED
|
||||
};
|
||||
|
||||
const mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
|
||||
const gfx::IntSize mSize;
|
||||
|
|
|
@ -46,6 +46,7 @@ class RenderTextureHost {
|
|||
}
|
||||
|
||||
virtual void PrepareForUse() {}
|
||||
virtual void NofityForUse() {}
|
||||
virtual void NotifyNotUsed() {}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -682,6 +682,20 @@ void RenderThread::UpdateRenderTextureHost(uint64_t aSrcExternalImageId,
|
|||
wrapper->UpdateRenderTextureHost(wrapped->second);
|
||||
}
|
||||
|
||||
void RenderThread::NofityForUse(uint64_t aExternalImageId) {
|
||||
MOZ_ASSERT(RenderThread::IsInRenderThread());
|
||||
|
||||
MutexAutoLock lock(mRenderTextureMapLock);
|
||||
if (mHasShutdown) {
|
||||
return;
|
||||
}
|
||||
auto it = mRenderTextures.find(aExternalImageId);
|
||||
if (it == mRenderTextures.end()) {
|
||||
return;
|
||||
}
|
||||
it->second->NofityForUse();
|
||||
}
|
||||
|
||||
void RenderThread::UnregisterExternalImageDuringShutdown(
|
||||
uint64_t aExternalImageId) {
|
||||
MOZ_ASSERT(IsInRenderThread());
|
||||
|
|
|
@ -197,6 +197,9 @@ class RenderThread final {
|
|||
void UpdateRenderTextureHost(uint64_t aSrcExternalImageId,
|
||||
uint64_t aWrappedExternalImageId);
|
||||
|
||||
/// Can only be called from the render thread.
|
||||
void NofityForUse(uint64_t aExternalImageId);
|
||||
|
||||
/// Can only be called from the render thread.
|
||||
void UnregisterExternalImageDuringShutdown(uint64_t aExternalImageId);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче