new file mode 100644
--- /dev/null
+++ b/gfx/gl/AndroidNativeWindow.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:set ts=2 sts=2 sw=2 et cin:
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef AndroidNativeWindow_h__
+#define AndroidNativeWindow_h__
+#ifdef MOZ_WIDGET_ANDROID
+
+#include <jni.h>
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+#include "GeneratedJNIWrappers.h"
+#include "SurfaceTexture.h"
+
+namespace mozilla {
+namespace gl {
+
+class AndroidNativeWindow {
+public:
+ AndroidNativeWindow(java::sdk::Surface::Param aSurface) {
+ mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
+ aSurface.Get());
+ }
+
+ AndroidNativeWindow(java::GeckoSurface::Param aSurface) {
+ auto surf = java::sdk::Surface::LocalRef(java::sdk::Surface::Ref::From(aSurface));
+ mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
+ surf.Get());
+ }
+
+ ~AndroidNativeWindow() {
+ if (mNativeWindow) {
+ ANativeWindow_release(mNativeWindow);
+ mNativeWindow = nullptr;
+ }
+ }
+
+ ANativeWindow* NativeWindow() const {
+ return mNativeWindow;
+ }
+
+private:
+ ANativeWindow* mNativeWindow;
+};
+
+} // gl
+} // mozilla
+
+#endif // MOZ_WIDGET_ANDROID
+#endif // AndroidNativeWindow_h__
--- a/gfx/gl/GLContextEGL.h
+++ b/gfx/gl/GLContextEGL.h
@@ -64,16 +64,19 @@ public:
return sEGLLibrary.IsWARP();
}
virtual bool BindTexImage() override;
virtual bool ReleaseTexImage() override;
void SetEGLSurfaceOverride(EGLSurface surf);
+ EGLSurface GetEGLSurfaceOverride() {
+ return mSurfaceOverride;
+ }
virtual bool MakeCurrentImpl(bool aForce) override;
virtual bool IsCurrent() override;
virtual bool RenewSurface(widget::CompositorWidget* aWidget) override;
virtual void ReleaseSurface() override;
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -85,16 +85,22 @@ GLScreenBuffer::CreateFactory(GLContext*
case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX)
factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
#elif defined(GL_PROVIDER_GLX)
if (sGLXLibrary.UseTextureFromPixmap())
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
#elif defined(MOZ_WIDGET_UIKIT)
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags);
+#elif defined(MOZ_WIDGET_ANDROID)
+ if (XRE_IsParentProcess()) {
+ factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
+ } else {
+ factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
+ }
#else
if (gl->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
}
}
#endif
break;
--- a/gfx/gl/SharedSurface.h
+++ b/gfx/gl/SharedSurface.h
@@ -91,16 +91,20 @@ public:
// This locks the SharedSurface as the production buffer for the context.
// This is needed by backends which use PBuffers and/or EGLSurfaces.
void LockProd();
// Unlocking is harmless if we're already unlocked.
void UnlockProd();
+ // This surface has been moved to the front buffer and will not be locked again
+ // until it is recycled. Do any finalization steps here.
+ virtual void Commit(){}
+
protected:
virtual void LockProdImpl() = 0;
virtual void UnlockProdImpl() = 0;
virtual void ProducerAcquireImpl() = 0;
virtual void ProducerReleaseImpl() = 0;
virtual void ProducerReadAcquireImpl() { ProducerAcquireImpl(); }
virtual void ProducerReadReleaseImpl() { ProducerReleaseImpl(); }
--- a/gfx/gl/SharedSurfaceEGL.cpp
+++ b/gfx/gl/SharedSurfaceEGL.cpp
@@ -2,16 +2,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SharedSurfaceEGL.h"
#include "GLBlitHelper.h"
#include "GLContextEGL.h"
+#include "GLContextProvider.h"
#include "GLLibraryEGL.h"
#include "GLReadTexImageHelper.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
#include "SharedSurface.h"
namespace mozilla {
namespace gl {
@@ -180,11 +181,154 @@ SurfaceFactory_EGLImage::Create(GLContex
GLLibraryEGL* egl = &sEGLLibrary;
if (SharedSurface_EGLImage::HasExtensions(egl, prodGL)) {
ret.reset( new ptrT(prodGL, caps, allocator, flags, context) );
}
return Move(ret);
}
+////////////////////////////////////////////////////////////////////////
+
+#ifdef MOZ_WIDGET_ANDROID
+
+/*static*/ UniquePtr<SharedSurface_SurfaceTexture>
+SharedSurface_SurfaceTexture::Create(GLContext* prodGL,
+ const GLFormats& formats,
+ const gfx::IntSize& size,
+ bool hasAlpha,
+ java::GeckoSurface::Param surface)
+{
+ MOZ_ASSERT(surface);
+
+ UniquePtr<SharedSurface_SurfaceTexture> ret;
+
+ AndroidNativeWindow window(surface);
+ EGLSurface eglSurface = GLContextProviderEGL::CreateEGLSurface(window.NativeWindow());
+ if (!eglSurface) {
+ return Move(ret);
+ }
+
+ ret.reset(new SharedSurface_SurfaceTexture(prodGL, size, hasAlpha,
+ formats, surface, eglSurface));
+ return Move(ret);
+}
+
+bool
+SharedSurface_SurfaceTexture::IsAvailable()
+{
+ return true;
+}
+
+SharedSurface_SurfaceTexture::SharedSurface_SurfaceTexture(GLContext* gl,
+ const gfx::IntSize& size,
+ bool hasAlpha,
+ const GLFormats& formats,
+ java::GeckoSurface::Param surface,
+ EGLSurface eglSurface)
+ : SharedSurface(SharedSurfaceType::AndroidSurfaceTexture,
+ AttachmentType::Screen,
+ gl,
+ size,
+ hasAlpha,
+ true)
+ , mSurface(surface)
+ , mEglSurface(eglSurface)
+{
+}
+
+SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture()
+{
+ GLContextProviderEGL::DestroyEGLSurface(mEglSurface);
+ java::SurfaceAllocator::DisposeSurface(mSurface);
+}
+
+layers::TextureFlags
+SharedSurface_SurfaceTexture::GetTextureFlags() const
+{
+ return layers::TextureFlags::DEALLOCATE_CLIENT;
+}
+
+void
+SharedSurface_SurfaceTexture::LockProdImpl()
+{
+ MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
+
+ GLContextEGL *gl = GLContextEGL::Cast(mGL);
+ mOrigEglSurface = gl->GetEGLSurfaceOverride();
+ gl->SetEGLSurfaceOverride(mEglSurface);
+}
+
+void
+SharedSurface_SurfaceTexture::UnlockProdImpl()
+{
+ MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
+
+ GLContextEGL::Cast(mGL)->SetEGLSurfaceOverride(mOrigEglSurface);
+ mOrigEglSurface = nullptr;
+}
+
+void
+SharedSurface_SurfaceTexture::Commit()
+{
+ MOZ_RELEASE_ASSERT(mSurface->GetAvailable());
+
+ LockProdImpl();
+ mGL->SwapBuffers();
+ UnlockProdImpl();
+ mSurface->SetAvailable(false);
+}
+
+void
+SharedSurface_SurfaceTexture::WaitForBufferOwnership()
+{
+ MOZ_RELEASE_ASSERT(!mSurface->GetAvailable());
+ mSurface->SetAvailable(true);
+}
+
+bool
+SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
+{
+ *out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize);
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////
+
+/*static*/ UniquePtr<SurfaceFactory_SurfaceTexture>
+SurfaceFactory_SurfaceTexture::Create(GLContext* prodGL, const SurfaceCaps& caps,
+ const RefPtr<layers::LayersIPCChannel>& allocator,
+ const layers::TextureFlags& flags)
+{
+ typedef SurfaceFactory_SurfaceTexture ptrT;
+ UniquePtr<ptrT> ret;
+
+ if (SharedSurface_SurfaceTexture::IsAvailable()) {
+ ret.reset(new ptrT(prodGL, caps, allocator, flags));
+ }
+
+ return Move(ret);
+}
+
+UniquePtr<SharedSurface>
+SurfaceFactory_SurfaceTexture::CreateShared(const gfx::IntSize& size)
+{
+ bool hasAlpha = mReadCaps.alpha;
+
+ jni::Object::LocalRef surface = java::SurfaceAllocator::AcquireSurface(size.width, size.height, true);
+ if (!surface) {
+ // Try multi-buffer mode
+ surface = java::SurfaceAllocator::AcquireSurface(size.width, size.height, false);
+ if (!surface) {
+ // Give up
+ return nullptr;
+ }
+ }
+
+ return SharedSurface_SurfaceTexture::Create(mGL, mFormats, size, hasAlpha,
+ java::GeckoSurface::Ref::From(surface));
+}
+
+#endif // MOZ_WIDGET_ANDROID
+
} // namespace gl
} /* namespace mozilla */
--- a/gfx/gl/SharedSurfaceEGL.h
+++ b/gfx/gl/SharedSurfaceEGL.h
@@ -5,16 +5,21 @@
#ifndef SHARED_SURFACE_EGL_H_
#define SHARED_SURFACE_EGL_H_
#include "mozilla/Attributes.h"
#include "mozilla/Mutex.h"
#include "SharedSurface.h"
+#ifdef MOZ_WIDGET_ANDROID
+#include "GeneratedJNIWrappers.h"
+#include "AndroidNativeWindow.h"
+#endif
+
namespace mozilla {
namespace gl {
class GLContext;
class GLLibraryEGL;
class SharedSurface_EGLImage
: public SharedSurface
@@ -105,13 +110,97 @@ protected:
public:
virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override {
bool hasAlpha = mReadCaps.alpha;
return SharedSurface_EGLImage::Create(mGL, mFormats, size, hasAlpha, mContext);
}
};
+#ifdef MOZ_WIDGET_ANDROID
+
+class SharedSurface_SurfaceTexture
+ : public SharedSurface
+{
+public:
+ static UniquePtr<SharedSurface_SurfaceTexture> Create(GLContext* prodGL,
+ const GLFormats& formats,
+ const gfx::IntSize& size,
+ bool hasAlpha,
+ java::GeckoSurface::Param surface);
+
+ static SharedSurface_SurfaceTexture* Cast(SharedSurface* surf) {
+ MOZ_ASSERT(surf->mType == SharedSurfaceType::AndroidSurfaceTexture);
+
+ return (SharedSurface_SurfaceTexture*)surf;
+ }
+
+ static bool IsAvailable();
+
+ java::GeckoSurface::Param JavaSurface() { return mSurface; }
+
+protected:
+ java::GeckoSurface::GlobalRef mSurface;
+ EGLSurface mEglSurface;
+ EGLSurface mOrigEglSurface;
+
+ SharedSurface_SurfaceTexture(GLContext* gl,
+ const gfx::IntSize& size,
+ bool hasAlpha,
+ const GLFormats& formats,
+ java::GeckoSurface::Param surface,
+ EGLSurface eglSurface);
+
+public:
+ virtual ~SharedSurface_SurfaceTexture();
+
+ virtual layers::TextureFlags GetTextureFlags() const override;
+
+ virtual void LockProdImpl() override;
+ virtual void UnlockProdImpl() override;
+
+ virtual void ProducerAcquireImpl() override {}
+ virtual void ProducerReleaseImpl() override {}
+
+ virtual void ProducerReadAcquireImpl() override {}
+ virtual void ProducerReadReleaseImpl() override {}
+
+ // Implementation-specific functions below:
+ // Returns texture and target
+ virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
+
+ virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) override { return false; }
+
+ virtual void Commit() override;
+
+ virtual void WaitForBufferOwnership() override;
+};
+
+
+
+class SurfaceFactory_SurfaceTexture
+ : public SurfaceFactory
+{
+public:
+ // Fallible:
+ static UniquePtr<SurfaceFactory_SurfaceTexture> Create(GLContext* prodGL,
+ const SurfaceCaps& caps,
+ const RefPtr<layers::LayersIPCChannel>& allocator,
+ const layers::TextureFlags& flags);
+
+protected:
+ SurfaceFactory_SurfaceTexture(GLContext* prodGL, const SurfaceCaps& caps,
+ const RefPtr<layers::LayersIPCChannel>& allocator,
+ const layers::TextureFlags& flags)
+ : SurfaceFactory(SharedSurfaceType::AndroidSurfaceTexture, prodGL, caps, allocator, flags)
+ { }
+
+public:
+ virtual UniquePtr<SharedSurface> CreateShared(const gfx::IntSize& size) override;
+};
+
+#endif // MOZ_WIDGET_ANDROID
+
} // namespace gl
} /* namespace mozilla */
#endif /* SHARED_SURFACE_EGL_H_ */
--- a/gfx/gl/SurfaceTypes.h
+++ b/gfx/gl/SurfaceTypes.h
@@ -72,16 +72,17 @@ enum class SharedSurfaceType : uint8_t {
Basic,
EGLImageShare,
EGLSurfaceANGLE,
DXGLInterop,
DXGLInterop2,
IOSurface,
GLXDrawable,
SharedGLTexture,
+ AndroidSurfaceTexture,
Max
};
enum class AttachmentType : uint8_t {
Screen = 0,
GLTexture,
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -19,16 +19,17 @@ elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT
gl_provider = 'GLX'
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
gl_provider = 'EGL'
if CONFIG['MOZ_GL_PROVIDER']:
gl_provider = CONFIG['MOZ_GL_PROVIDER']
EXPORTS += [
+ 'AndroidNativeWindow.h',
'AndroidSurfaceTexture.h',
'DecomposeIntoNoRepeatTriangles.h',
'EGLUtils.h',
'ForceDiscreteGPUHelperCGL.h',
'GfxTexturesReporter.h',
'GLBlitHelper.h',
'GLConsts.h',
'GLContext.h',
--- a/gfx/layers/GLImages.cpp
+++ b/gfx/layers/GLImages.cpp
@@ -93,21 +93,22 @@ GLImage::GetAsSourceSurface()
}
ScopedBindFramebuffer bind(sSnapshotContext, autoFBForTex.FB());
ReadPixelsIntoDataSurface(sSnapshotContext, source);
return source.forget();
}
#ifdef MOZ_WIDGET_ANDROID
-SurfaceTextureImage::SurfaceTextureImage(gl::AndroidSurfaceTexture* aSurfTex,
+SurfaceTextureImage::SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize,
gl::OriginPos aOriginPos)
: GLImage(ImageFormat::SURFACE_TEXTURE),
- mSurfaceTexture(aSurfTex),
+ mHandle(aHandle),
mSize(aSize),
mOriginPos(aOriginPos)
{
+ MOZ_ASSERT(mHandle);
}
#endif
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -59,34 +59,34 @@ private:
gl::OriginPos mPos;
bool mOwns;
};
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureImage : public GLImage {
public:
- SurfaceTextureImage(gl::AndroidSurfaceTexture* aSurfTex,
+ SurfaceTextureImage(AndroidSurfaceTextureHandle aHandle,
const gfx::IntSize& aSize,
gl::OriginPos aOriginPos);
gfx::IntSize GetSize() override { return mSize; }
- gl::AndroidSurfaceTexture* GetSurfaceTexture() const {
- return mSurfaceTexture;
+ AndroidSurfaceTextureHandle GetHandle() const {
+ return mHandle;
}
gl::OriginPos GetOriginPos() const {
return mOriginPos;
}
SurfaceTextureImage* AsSurfaceTextureImage() override {
return this;
}
private:
- RefPtr<gl::AndroidSurfaceTexture> mSurfaceTexture;
+ AndroidSurfaceTextureHandle mHandle;
gfx::IntSize mSize;
gl::OriginPos mOriginPos;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -456,16 +456,18 @@ CanvasClientSharedSurface::UpdateRendere
auto layersBackend = shadowForwarder->GetCompositorBackendType();
mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend);
newFront = mReadbackClient;
} else {
mReadbackClient = nullptr;
}
+ surf->Commit();
+
if (asyncRenderer) {
// If surface type is Basic, above codes will readback
// the GLContext to mReadbackClient in order to send frame to
// compositor. We copy from this TextureClient directly by
// calling CopyFromTextureClient().
// Therefore, if main-thread want the content of GLContext,
// it doesn't have to readback from GLContext again.
//
--- 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->GetSurfaceTexture(), size, typedImage->GetOriginPos(),
+ typedImage->GetHandle(), size, 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/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -593,17 +593,17 @@ protected:
void RecycleTexture(TextureFlags aFlags);
virtual void UpdatedInternal(const nsIntRegion *Region) {}
/**
* Called when mCompositableCount becomes 0.
*/
- void NotifyNotUsed();
+ virtual void NotifyNotUsed();
// for Compositor.
void CallNotifyNotUsed();
PTextureParent* mActor;
RefPtr<TextureSourceProvider> mProvider;
RefPtr<TextureReadLock> mReadLock;
TextureFlags mFlags;
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -55,17 +55,17 @@ struct SurfaceDescriptorDXGIYCbCr {
struct SurfaceDescriptorMacIOSurface {
uint32_t surfaceId;
double scaleFactor;
bool isOpaque;
};
struct SurfaceTextureDescriptor {
- uintptr_t surfTex;
+ uint64_t handle;
IntSize size;
};
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
@@ -74,44 +74,39 @@ EGLImageTextureData::Serialize(SurfaceDe
}
////////////////////////////////////////////////////////////////////////
// AndroidSurface
#ifdef MOZ_WIDGET_ANDROID
already_AddRefed<TextureClient>
-AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTexture* aSurfTex,
+AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize,
gl::OriginPos aOriginPos,
LayersIPCChannel* aAllocator,
TextureFlags aFlags)
{
- MOZ_ASSERT(XRE_IsParentProcess(),
- "Can't pass an android surfaces between processes.");
-
- if (!aSurfTex || !XRE_IsParentProcess()) {
- return nullptr;
- }
-
if (aOriginPos == gl::OriginPos::BottomLeft) {
aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
}
return TextureClient::CreateWithData(
- new AndroidSurfaceTextureData(aSurfTex, aSize),
+ new AndroidSurfaceTextureData(aHandle, aSize),
aFlags, aAllocator
);
}
-AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTexture* aSurfTex,
+AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize)
- : mSurfTex(aSurfTex)
+ : mHandle(aHandle)
, mSize(aSize)
-{}
+{
+ MOZ_ASSERT(mHandle);
+}
AndroidSurfaceTextureData::~AndroidSurfaceTextureData()
{}
void
AndroidSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = mSize;
@@ -120,17 +115,16 @@ AndroidSurfaceTextureData::FillInfo(Text
aInfo.hasSynchronization = false;
aInfo.supportsMoz2D = false;
aInfo.canExposeMappedData = false;
}
bool
AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
- aOutDescriptor = SurfaceTextureDescriptor((uintptr_t)mSurfTex.get(),
- mSize);
+ aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize);
return true;
}
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -49,17 +49,17 @@ protected:
};
#ifdef MOZ_WIDGET_ANDROID
class AndroidSurfaceTextureData : public TextureData
{
public:
static already_AddRefed<TextureClient>
- CreateTextureClient(gl::AndroidSurfaceTexture* aSurfTex,
+ CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
gfx::IntSize aSize,
gl::OriginPos aOriginPos,
LayersIPCChannel* aAllocator,
TextureFlags aFlags);
~AndroidSurfaceTextureData();
virtual void FillInfo(TextureData::Info& aInfo) const override;
@@ -70,19 +70,19 @@ 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(gl::AndroidSurfaceTexture* aSurfTex, gfx::IntSize aSize);
+ AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle, gfx::IntSize aSize);
- const RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
+ const AndroidSurfaceTextureHandle mHandle;
const gfx::IntSize mSize;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/opengl/TextureHostOGL.cpp
+++ b/gfx/layers/opengl/TextureHostOGL.cpp
@@ -51,18 +51,22 @@ CreateTextureHostOGL(const SurfaceDescri
aBackend,
aFlags);
break;
}
#ifdef MOZ_WIDGET_ANDROID
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
+ java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::Lookup(desc.handle());
+
+ MOZ_RELEASE_ASSERT(surfaceTexture);
+
result = new SurfaceTextureHost(aFlags,
- (AndroidSurfaceTexture*)desc.surfTex(),
+ surfaceTexture,
desc.size());
break;
}
#endif
case SurfaceDescriptor::TEGLImageDescriptor: {
const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
result = new EGLImageTextureHost(aFlags,
@@ -330,17 +334,17 @@ GLTextureSource::IsValid() const
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// SurfaceTextureHost
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureSource::SurfaceTextureSource(TextureSourceProvider* aProvider,
- AndroidSurfaceTexture* aSurfTex,
+ mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize)
: mGL(aProvider->GetGLContext())
, mSurfTex(aSurfTex)
, mFormat(aFormat)
, mTextureTarget(aTarget)
@@ -356,22 +360,17 @@ SurfaceTextureSource::BindTexture(GLenum
MOZ_ASSERT(mSurfTex);
GLContext* gl = this->gl();
if (!gl || !gl->MakeCurrent()) {
NS_WARNING("Trying to bind a texture without a GLContext");
return;
}
gl->fActiveTexture(aTextureUnit);
-
- // SurfaceTexture spams us if there are any existing GL errors, so
- // we'll clear them here in order to avoid that.
- gl->FlushErrors();
-
- mSurfTex->UpdateTexImage();
+ gl->fBindTexture(mTextureTarget, mSurfTex->GetTexName());
ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
}
void
SurfaceTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
{
GLContext* newGL = aProvider->GetGLContext();
@@ -390,42 +389,57 @@ SurfaceTextureSource::IsValid() const
}
gfx::Matrix4x4
SurfaceTextureSource::GetTextureTransform()
{
MOZ_ASSERT(mSurfTex);
gfx::Matrix4x4 ret;
- mSurfTex->GetTransformMatrix(ret);
+
+ const auto& surf = java::sdk::SurfaceTexture::LocalRef(java::sdk::SurfaceTexture::Ref::From(mSurfTex));
+ AndroidSurfaceTexture::GetTransformMatrix(surf, ret);
return ret;
}
void
SurfaceTextureSource::DeallocateDeviceData()
{
mSurfTex = nullptr;
}
////////////////////////////////////////////////////////////////////////
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
- AndroidSurfaceTexture* aSurfTex,
+ mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize)
: TextureHost(aFlags)
, mSurfTex(aSurfTex)
, mSize(aSize)
{
}
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();
+}
+
gl::GLContext*
SurfaceTextureHost::gl() const
{
return mProvider ? mProvider->GetGLContext() : nullptr;
}
bool
SurfaceTextureHost::Lock()
@@ -433,34 +447,27 @@ SurfaceTextureHost::Lock()
MOZ_ASSERT(mSurfTex);
GLContext* gl = this->gl();
if (!gl || !gl->MakeCurrent()) {
return false;
}
if (!mTextureSource) {
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
- GLenum target = LOCAL_GL_TEXTURE_EXTERNAL;
+ 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,
wrapMode,
mSize);
}
- return NS_SUCCEEDED(mSurfTex->Attach(gl));
-}
-
-void
-SurfaceTextureHost::Unlock()
-{
- MOZ_ASSERT(mSurfTex);
- mSurfTex->Detach();
+ return true;
}
void
SurfaceTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
{
if (mProvider != aProvider) {
if (!aProvider || !aProvider->GetGLContext()) {
DeallocateDeviceData();
@@ -469,16 +476,28 @@ SurfaceTextureHost::SetTextureSourceProv
mProvider = aProvider;
}
if (mTextureSource) {
mTextureSource->SetTextureSourceProvider(aProvider);
}
}
+void
+SurfaceTextureHost::NotifyNotUsed()
+{
+ if (mSurfTex->IsSingleBuffer()) {
+ 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.
+ CallNotifyNotUsed();
+}
+
gfx::SurfaceFormat
SurfaceTextureHost::GetFormat() const
{
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
}
void
SurfaceTextureHost::DeallocateDeviceData()
--- a/gfx/layers/opengl/TextureHostOGL.h
+++ b/gfx/layers/opengl/TextureHostOGL.h
@@ -26,25 +26,26 @@
#include "mozilla/layers/TextureHost.h" // for TextureHost, etc
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsDebug.h" // for NS_WARNING
#include "nsISupportsImpl.h" // for TextureImage::Release, etc
#include "nsRegionFwd.h" // for nsIntRegion
#include "OGLShaderProgram.h" // for ShaderProgramType, etc
+#ifdef MOZ_WIDGET_ANDROID
+#include "GeneratedJNIWrappers.h"
+#include "AndroidSurfaceTexture.h"
+#endif
+
namespace mozilla {
namespace gfx {
class DataSourceSurface;
} // namespace gfx
-namespace gl {
-class AndroidSurfaceTexture;
-} // namespace gl
-
namespace layers {
class Compositor;
class CompositorOGL;
class TextureImageTextureSourceOGL;
class GLTextureSource;
inline void ApplySamplingFilterToBoundTexture(gl::GLContext* aGL,
@@ -336,17 +337,17 @@ protected:
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureSource : public TextureSource
, public TextureSourceOGL
{
public:
SurfaceTextureSource(TextureSourceProvider* aProvider,
- mozilla::gl::AndroidSurfaceTexture* aSurfTex,
+ java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize);
virtual const char* Name() const override { return "SurfaceTextureSource"; }
virtual TextureSourceOGL* AsSourceOGL() override { return this; }
@@ -371,41 +372,43 @@ public:
virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
gl::GLContext* gl() const {
return mGL;
}
protected:
RefPtr<gl::GLContext> mGL;
- RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
+ mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
const gfx::SurfaceFormat mFormat;
const GLenum mTextureTarget;
const GLenum mWrapMode;
const gfx::IntSize mSize;
};
class SurfaceTextureHost : public TextureHost
{
public:
SurfaceTextureHost(TextureFlags aFlags,
- mozilla::gl::AndroidSurfaceTexture* aSurfTex,
+ mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize);
virtual ~SurfaceTextureHost();
+ virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) override;
+
virtual void DeallocateDeviceData() override;
virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider) override;
virtual bool Lock() override;
- virtual void Unlock() override;
+ virtual gfx::SurfaceFormat GetFormat() const override;
- virtual gfx::SurfaceFormat GetFormat() const override;
+ virtual void NotifyNotUsed() override;
virtual bool BindTextureSource(CompositableTextureSourceRef& aTexture) override
{
aTexture = mTextureSource;
return !!aTexture;
}
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override
@@ -415,17 +418,17 @@ public:
gl::GLContext* gl() const;
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual const char* Name() override { return "SurfaceTextureHost"; }
protected:
- RefPtr<gl::AndroidSurfaceTexture> mSurfTex;
+ mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
const gfx::IntSize mSize;
RefPtr<CompositorOGL> mCompositor;
RefPtr<SurfaceTextureSource> mTextureSource;
};
#endif // MOZ_WIDGET_ANDROID
////////////////////////////////////////////////////////////////////////
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/gfx/SurfaceAllocator.java
@@ -37,23 +37,28 @@ public final class SurfaceAllocator {
// FIXME: may not want to auto create
if (!GeckoAppShell.getApplicationContext().bindService(intent, sConnection, Context.BIND_AUTO_CREATE)) {
throw new Exception("Failed to connect to surface allocator service!");
}
}
@WrapForJNI
- public static GeckoSurface acquireSurface(int width, int height, boolean singleBufferMode) throws Exception {
- ensureConnection();
-
+ public static GeckoSurface acquireSurface(int width, int height, boolean singleBufferMode) {
try {
+ ensureConnection();
+
+ if (singleBufferMode && !GeckoSurfaceTexture.isSingleBufferSupported()) {
+ return null;
+ }
+
return sConnection.getAllocator().acquireSurface(width, height, singleBufferMode);
- } catch (RemoteException e) {
- throw new Exception("Failed to acquire GeckoSurface", e);
+ } catch (Exception e) {
+ Log.w(LOGTAG, "Failed to acquire GeckoSurface", e);
+ return null;
}
}
@WrapForJNI
public static void disposeSurface(GeckoSurface surface) {
try {
ensureConnection();
} catch (Exception e) {