Bug 1322650 - Support a 'continuous' mode for SurfaceTexture r=jgilbert
This is needed to support Flash on Android (sigh).
MozReview-Commit-ID: 5yNIoZHonla
--- a/dom/media/platforms/android/RemoteDataDecoder.cpp
+++ b/dom/media/platforms/android/RemoteDataDecoder.cpp
@@ -128,17 +128,17 @@ public:
InputInfo inputInfo;
if (!mDecoder->mInputInfos.Find(presentationTimeUs, inputInfo)
&& !isEOS) {
return;
}
if (size > 0) {
RefPtr<layers::Image> img = new SurfaceTextureImage(
- mDecoder->mSurfaceHandle, inputInfo.mImageSize,
+ mDecoder->mSurfaceHandle, inputInfo.mImageSize, false /* NOT continuous */,
gl::OriginPos::BottomLeft);
RefPtr<VideoData> v = VideoData::CreateFromImage(
inputInfo.mDisplaySize, offset, presentationTimeUs, inputInfo.mDurationUs,
img, !!(flags & MediaCodec::BUFFER_FLAG_SYNC_FRAME),
presentationTimeUs);
v->SetListener(Move(releaseSample));
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -251,17 +251,16 @@ SharedSurface_SurfaceTexture::GetTexture
void
SharedSurface_SurfaceTexture::LockProdImpl()
{
if (!mSurface->GetAvailable()) {
return;
}
GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(mEglSurface);
-
}
void
SharedSurface_SurfaceTexture::UnlockProdImpl()
{
if (!mSurface->GetAvailable()) {
return;
}
@@ -269,17 +268,17 @@ SharedSurface_SurfaceTexture::UnlockProd
mGL->SwapBuffers();
mSurface->SetAvailable(false);
GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(nullptr);
}
bool
SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
- *out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize);
+ *out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize, false /* NOT continuous */);
return true;
}
bool
SharedSurface_SurfaceTexture::ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface)
{
return false;
}
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -95,20 +95,22 @@ GLImage::GetAsSourceSurface()
ScopedBindFramebuffer bind(sSnapshotContext, autoFBForTex.FB());
ReadPixelsIntoDataSurface(sSnapshotContext, source);
return source.forget();
}
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureImage::SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize,
+ bool aContinuous,
gl::OriginPos aOriginPos)
: GLImage(ImageFormat::SURFACE_TEXTURE),
mHandle(aHandle),
mSize(aSize),
+ mContinuous(aContinuous),
mOriginPos(aOriginPos)
{
MOZ_ASSERT(mHandle);
}
#endif
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -61,33 +61,38 @@ private:
};
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureImage : public GLImage {
public:
SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize,
+ bool aContinuous,
gl::OriginPos aOriginPos);
gfx::IntSize GetSize() override { return mSize; }
AndroidSurfaceTextureHandle GetHandle() const {
return mHandle;
}
+ bool GetContinuous() const {
+ return mContinuous;
+ }
gl::OriginPos GetOriginPos() const {
return mOriginPos;
}
SurfaceTextureImage* AsSurfaceTextureImage() override {
return this;
}
private:
AndroidSurfaceTextureHandle mHandle;
gfx::IntSize mSize;
+ bool mContinuous;
gl::OriginPos mOriginPos;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -127,17 +127,17 @@ ImageClient::CreateTextureClientForImage
if (aImage->GetFormat() == ImageFormat::EGLIMAGE) {
EGLImageImage* typedImage = aImage->AsEGLImageImage();
texture = EGLImageTextureData::CreateTextureClient(
typedImage, size, aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
#ifdef MOZ_WIDGET_ANDROID
} else if (aImage->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
SurfaceTextureImage* typedImage = aImage->AsSurfaceTextureImage();
texture = AndroidSurfaceTextureData::CreateTextureClient(
- typedImage->GetHandle(), size, typedImage->GetOriginPos(),
+ typedImage->GetHandle(), size, typedImage->GetContinuous(), typedImage->GetOriginPos(),
aForwarder->GetTextureForwarder(), TextureFlags::DEFAULT);
#endif
} else {
MOZ_ASSERT(false, "Bad ImageFormat.");
}
} else {
RefPtr<gfx::SourceSurface> surface = aImage->GetAsSourceSurface();
MOZ_ASSERT(surface);
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -57,16 +57,17 @@ struct SurfaceDescriptorMacIOSurface {
uint32_t surfaceId;
double scaleFactor;
bool isOpaque;
};
struct SurfaceTextureDescriptor {
uint64_t handle;
IntSize size;
+ bool continuous;
};
struct EGLImageDescriptor {
uintptr_t image; // `EGLImage` is a `void*`.
uintptr_t fence;
IntSize size;
bool hasAlpha;
};
--- a/gfx/layers/opengl/TextureClientOGL.cpp
+++ b/gfx/layers/opengl/TextureClientOGL.cpp
@@ -76,34 +76,36 @@ EGLImageTextureData::Serialize(SurfaceDe
////////////////////////////////////////////////////////////////////////
// AndroidSurface
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<TextureClient>
AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize,
+ bool aContinuous,
gl::OriginPos aOriginPos,
LayersIPCChannel* aAllocator,
TextureFlags aFlags)
{
if (aOriginPos == gl::OriginPos::BottomLeft) {
aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
}
return TextureClient::CreateWithData(
- new AndroidSurfaceTextureData(aHandle, aSize),
+ new AndroidSurfaceTextureData(aHandle, aSize, aContinuous),
aFlags, aAllocator
);
}
AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle,
- gfx::IntSize aSize)
+ gfx::IntSize aSize, bool aContinuous)
: mHandle(aHandle)
, mSize(aSize)
+ , mContinuous(aContinuous)
{
MOZ_ASSERT(mHandle);
}
AndroidSurfaceTextureData::~AndroidSurfaceTextureData()
{}
void
@@ -115,16 +117,16 @@ AndroidSurfaceTextureData::FillInfo(Text
aInfo.hasSynchronization = false;
aInfo.supportsMoz2D = false;
aInfo.canExposeMappedData = false;
}
bool
AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
- aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize);
+ aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize, mContinuous);
return true;
}
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -51,16 +51,17 @@ protected:
#ifdef MOZ_WIDGET_ANDROID
class AndroidSurfaceTextureData : public TextureData
{
public:
static already_AddRefed<TextureClient>
CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize,
+ bool aContinuous,
gl::OriginPos aOriginPos,
LayersIPCChannel* aAllocator,
TextureFlags aFlags);
~AndroidSurfaceTextureData();
virtual void FillInfo(TextureData::Info& aInfo) const override;
@@ -70,20 +71,21 @@ public:
virtual bool Lock(OpenMode) override { return true; }
virtual void Unlock() override {}
// Our data is always owned externally.
virtual void Deallocate(LayersIPCChannel*) override {}
protected:
- AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize);
+ AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize, bool aContinuous);
const AndroidSurfaceTextureHandle mHandle;
const gfx::IntSize mSize;
+ const bool mContinuous;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla
#endif
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -58,17 +58,18 @@ CreateTextureHostOGL(const SurfaceDescri
const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::Lookup(desc.handle());
if (!surfaceTexture) {
return nullptr;
}
result = new SurfaceTextureHost(aFlags,
surfaceTexture,
- desc.size());
+ desc.size(),
+ desc.continuous());
break;
}
#endif
case SurfaceDescriptor::TEGLImageDescriptor: {
const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
result = new EGLImageTextureHost(aFlags,
(EGLImage)desc.image(),
@@ -406,38 +407,42 @@ SurfaceTextureSource::DeallocateDeviceDa
{
mSurfTex = nullptr;
}
////////////////////////////////////////////////////////////////////////
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
- gfx::IntSize aSize)
+ gfx::IntSize aSize,
+ bool aContinuousUpdate)
: TextureHost(aFlags)
, mSurfTex(aSurfTex)
, mSize(aSize)
+ , mContinuousUpdate(aContinuousUpdate)
{
+ // Continuous update makes no sense with single buffer mode
+ MOZ_ASSERT(!mSurfTex->GetIsSingleBuffer() || !mContinuousUpdate);
}
SurfaceTextureHost::~SurfaceTextureHost()
{
}
void
SurfaceTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
{
GLContext* gl = this->gl();
if (!gl || !gl->MakeCurrent()) {
return;
}
- // This advances the SurfaceTexture's internal buffer queue. We only want to do this
- // once per transaction. We can then composite that texture as many times as needed.
- mSurfTex->UpdateTexImage();
+ if (!mContinuousUpdate) {
+ mSurfTex->UpdateTexImage();
+ }
}
gl::GLContext*
SurfaceTextureHost::gl() const
{
return mProvider ? mProvider->GetGLContext() : nullptr;
}
@@ -445,16 +450,20 @@ bool
SurfaceTextureHost::Lock()
{
MOZ_ASSERT(mSurfTex);
GLContext* gl = this->gl();
if (!gl || !gl->MakeCurrent()) {
return false;
}
+ if (mContinuousUpdate) {
+ mSurfTex->UpdateTexImage();
+ }
+
if (!mTextureSource) {
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL; // This is required by SurfaceTexture
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
mTextureSource = new SurfaceTextureSource(mProvider,
mSurfTex,
format,
target,
@@ -483,18 +492,18 @@ SurfaceTextureHost::SetTextureSourceProv
void
SurfaceTextureHost::NotifyNotUsed()
{
if (mSurfTex->GetIsSingleBuffer()) {
mSurfTex->ReleaseTexImage();
}
- // We don't want to wait until it's done compositing, there are fences that protect
- // us from problems there. Send a message to recycle this surface immediately.
+ // We don't want to wait until it's done compositing, as there are built-in fences that protect
+ // us from any problems there. Send a message to recycle this surface immediately.
CallNotifyNotUsed();
}
gfx::SurfaceFormat
SurfaceTextureHost::GetFormat() const
{
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
}
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -384,17 +384,18 @@ protected:
const gfx::IntSize mSize;
};
class SurfaceTextureHost : public TextureHost
{
public:
SurfaceTextureHost(TextureFlags aFlags,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
- gfx::IntSize aSize);
+ gfx::IntSize aSize,
+ bool aContinuousUpdate);
virtual ~SurfaceTextureHost();
virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) override;
virtual void DeallocateDeviceData() override;
virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
@@ -420,16 +421,17 @@ public:
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual const char* Name() override { return "SurfaceTextureHost"; }
protected:
mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
const gfx::IntSize mSize;
+ bool mContinuousUpdate;
RefPtr<CompositorOGL> mCompositor;
RefPtr<SurfaceTextureSource> mTextureSource;
};
#endif // MOZ_WIDGET_ANDROID
////////////////////////////////////////////////////////////////////////
// EGLImage