Bug 1656034 - Support multiple EglDisplays per GLLibraryEGL. r=lsalzman,sotaro,stransky

Have webrender use its own EGLDisplay, letting WebGL use a different
one.

Differential Revision: https://phabricator.services.mozilla.com/D85496
This commit is contained in:
Jeff Gilbert 2020-08-06 22:53:53 +00:00
parent 953004415b
commit b5d6906473
45 changed files with 1381 additions and 1513 deletions

View File

@ -6,39 +6,24 @@
#include "AndroidSurfaceTexture.h"
#include "mozilla/java/GeckoSurfaceTextureNatives.h"
#include "AndroidNativeWindow.h"
#include "GLContextEGL.h"
#include "GLBlitHelper.h"
#include "GLImages.h"
using namespace mozilla;
#ifdef MOZ_WIDGET_ANDROID
# include "mozilla/java/GeckoSurfaceTextureNatives.h"
# include "AndroidNativeWindow.h"
#endif // MOZ_WIDGET_ANDROID
namespace mozilla {
namespace gl {
void AndroidSurfaceTexture::GetTransformMatrix(
java::sdk::SurfaceTexture::Param surfaceTexture,
gfx::Matrix4x4* outMatrix) {
JNIEnv* const env = jni::GetEnvForThread();
auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
surfaceTexture->GetTransformMatrix(jarray);
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
memcpy(&(outMatrix->_11), array, sizeof(float) * 16);
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
}
class SharedGL final {
class AndroidSharedBlitGL final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedGL);
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidSharedBlitGL);
explicit SharedGL(AndroidNativeWindow& window) {
MutexAutoLock lock(sMutex);
explicit AndroidSharedBlitGL(const EGLNativeWindowType window) {
StaticMutexAutoLock lock(sMutex);
if (!sContext) {
MOZ_ASSERT(sInstanceCount == 0);
@ -48,20 +33,23 @@ class SharedGL final {
}
}
InitSurface(window);
const auto& egl = *(sContext->mEgl);
mTargetSurface = egl.fCreateWindowSurface(sContext->mConfig, window, 0);
++sInstanceCount;
}
void Blit(const AndroidSurfaceTextureHandle& sourceTextureHandle,
const gfx::IntSize& imageSize) {
MutexAutoLock lock(sMutex);
void Blit(layers::SurfaceTextureImage* img, const gfx::IntSize& imageSize) {
StaticMutexAutoLock lock(sMutex);
MOZ_ASSERT(sContext);
// Setting overide also makes conext and surface current.
sContext->SetEGLSurfaceOverride(mTargetSurface);
RefPtr<layers::SurfaceTextureImage> img = new layers::SurfaceTextureImage(
sourceTextureHandle, imageSize, false, OriginPos::TopLeft);
#ifdef MOZ_WIDGET_ANDROID
sContext->BlitHelper()->BlitImage(img, imageSize, OriginPos::BottomLeft);
#else
MOZ_CRASH("bad platform");
#endif
sContext->SwapBuffers();
// This method is called through binder IPC and could run on any thread in
// the pool. Release the context and surface from this thread after use so
@ -70,12 +58,12 @@ class SharedGL final {
}
private:
~SharedGL() {
MutexAutoLock lock(sMutex);
~AndroidSharedBlitGL() {
StaticMutexAutoLock lock(sMutex);
if (mTargetSurface != EGL_NO_SURFACE) {
const auto& egl = *(sContext->mEgl);
egl.fDestroySurface(egl.Display(), mTargetSurface);
egl.fDestroySurface(mTargetSurface);
}
// Destroy shared GL context when no one uses it.
@ -88,21 +76,14 @@ class SharedGL final {
sMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(!sContext);
auto* egl = gl::GLLibraryEGL::Get();
EGLDisplay eglDisplay = egl->fGetDisplay(EGL_DEFAULT_DISPLAY);
MOZ_ASSERT(eglDisplay == egl->Display());
nsCString ignored;
const auto egl = gl::DefaultEglDisplay(&ignored);
EGLConfig eglConfig;
CreateConfig(egl, &eglConfig, /* bpp */ 24, /* depth buffer? */ false,
CreateConfig(*egl, &eglConfig, /* bpp */ 24, /* depth buffer? */ false,
aUseGles);
EGLint attributes[] = {LOCAL_EGL_CONTEXT_CLIENT_VERSION, 2, LOCAL_EGL_NONE};
EGLContext eglContext =
egl->fCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, attributes);
if (!eglContext) {
return nullptr;
}
RefPtr<GLContextEGL> gl =
new GLContextEGL(egl, {}, eglConfig, EGL_NO_SURFACE, eglContext);
if (!gl->Init()) {
auto gl = GLContextEGL::CreateGLContext(egl, {}, eglConfig, EGL_NO_SURFACE,
true, &ignored);
if (!gl) {
NS_WARNING("Fail to create GL context for native blitter.");
return nullptr;
}
@ -124,16 +105,7 @@ class SharedGL final {
return gl.forget();
}
void InitSurface(AndroidNativeWindow& window) {
sMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(sContext);
const auto& egl = *(sContext->mEgl);
mTargetSurface = egl.fCreateWindowSurface(egl.Display(), sContext->mConfig,
window.NativeWindow(), 0);
}
static bool UnmakeCurrent(RefPtr<GLContextEGL>& gl) {
static bool UnmakeCurrent(GLContextEGL* const gl) {
sMutex.AssertCurrentThreadOwns();
MOZ_ASSERT(gl);
@ -141,20 +113,37 @@ class SharedGL final {
return true;
}
const auto& egl = *(gl->mEgl);
return egl.fMakeCurrent(egl.Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
return egl.fMakeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
static Mutex sMutex;
static RefPtr<GLContextEGL> sContext;
static StaticMutex sMutex;
static StaticRefPtr<GLContextEGL> sContext;
static size_t sInstanceCount;
EGLSurface mTargetSurface;
};
Mutex SharedGL::sMutex("SharedGLContext::sMutex");
RefPtr<GLContextEGL> SharedGL::sContext(nullptr);
size_t SharedGL::sInstanceCount = 0;
StaticMutex AndroidSharedBlitGL::sMutex;
StaticRefPtr<GLContextEGL> AndroidSharedBlitGL::sContext;
size_t AndroidSharedBlitGL::sInstanceCount = 0;
// -
#ifdef MOZ_WIDGET_ANDROID
void AndroidSurfaceTexture::GetTransformMatrix(
java::sdk::SurfaceTexture::Param surfaceTexture,
gfx::Matrix4x4* outMatrix) {
JNIEnv* const env = jni::GetEnvForThread();
auto jarray = jni::FloatArray::LocalRef::Adopt(env, env->NewFloatArray(16));
surfaceTexture->GetTransformMatrix(jarray);
jfloat* array = env->GetFloatArrayElements(jarray.Get(), nullptr);
memcpy(&(outMatrix->_11), array, sizeof(float) * 16);
env->ReleaseFloatArrayElements(jarray.Get(), array, 0);
}
class GLBlitterSupport final
: public java::GeckoSurfaceTexture::NativeGLBlitHelper::Natives<
@ -171,28 +160,35 @@ class GLBlitterSupport final
jint height) {
AndroidNativeWindow win(java::GeckoSurface::Ref::From(targetSurface));
auto helper = java::GeckoSurfaceTexture::NativeGLBlitHelper::New();
RefPtr<SharedGL> gl = new SharedGL(win);
const auto& eglWindow = win.NativeWindow();
RefPtr<AndroidSharedBlitGL> gl = new AndroidSharedBlitGL(eglWindow);
GLBlitterSupport::AttachNative(
helper, MakeUnique<GLBlitterSupport>(std::move(gl), sourceTextureHandle,
width, height));
return helper;
}
GLBlitterSupport(RefPtr<SharedGL>&& gl, jint sourceTextureHandle, jint width,
jint height)
GLBlitterSupport(RefPtr<AndroidSharedBlitGL>&& gl, jint sourceTextureHandle,
jint width, jint height)
: mGl(gl),
mSourceTextureHandle(sourceTextureHandle),
mSize(width, height) {}
void Blit() { mGl->Blit(mSourceTextureHandle, mSize); }
void Blit() {
RefPtr<layers::SurfaceTextureImage> img = new layers::SurfaceTextureImage(
mSourceTextureHandle, mSize, false, OriginPos::TopLeft);
mGl->Blit(img, mSize);
}
private:
const RefPtr<SharedGL> mGl;
const RefPtr<AndroidSharedBlitGL> mGl;
const AndroidSurfaceTextureHandle mSourceTextureHandle;
const gfx::IntSize mSize;
};
void AndroidSurfaceTexture::Init() { GLBlitterSupport::Init(); }
#endif // MOZ_WIDGET_ANDROID
} // namespace gl
} // namespace mozilla

View File

@ -8,10 +8,13 @@
#define AndroidSurfaceTexture_h__
#include "mozilla/gfx/Matrix.h"
#include "SurfaceTexture.h"
typedef uint32_t AndroidSurfaceTextureHandle;
#ifdef MOZ_WIDGET_ANDROID
# include "SurfaceTexture.h"
namespace mozilla {
namespace gl {
@ -26,4 +29,6 @@ class AndroidSurfaceTexture {
} // namespace gl
} // namespace mozilla
#endif // MOZ_WIDGET_ANDROID
#endif // AndroidSurfaceTexture_h__

View File

@ -20,30 +20,29 @@
namespace mozilla {
namespace gl {
static EGLStreamKHR StreamFromD3DTexture(GLLibraryEGL* const egl,
static EGLStreamKHR StreamFromD3DTexture(EglDisplay* const egl,
ID3D11Texture2D* const texD3D,
const EGLAttrib* const postAttribs) {
if (!egl->IsExtensionSupported(
GLLibraryEGL::NV_stream_consumer_gltexture_yuv) ||
EGLExtension::NV_stream_consumer_gltexture_yuv) ||
!egl->IsExtensionSupported(
GLLibraryEGL::ANGLE_stream_producer_d3d_texture)) {
EGLExtension::ANGLE_stream_producer_d3d_texture)) {
return 0;
}
const auto& display = egl->Display();
const auto stream = egl->fCreateStreamKHR(display, nullptr);
const auto stream = egl->fCreateStreamKHR(nullptr);
MOZ_ASSERT(stream);
if (!stream) return 0;
bool ok = true;
MOZ_ALWAYS_TRUE(ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
display, stream, nullptr)));
MOZ_ALWAYS_TRUE(ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(
display, stream, nullptr)));
MOZ_ALWAYS_TRUE(ok &= bool(egl->fStreamPostD3DTextureANGLE(
display, stream, texD3D, postAttribs)));
stream, nullptr)));
MOZ_ALWAYS_TRUE(
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(stream, nullptr)));
MOZ_ALWAYS_TRUE(
ok &= bool(egl->fStreamPostD3DTextureANGLE(stream, texD3D, postAttribs)));
if (ok) return stream;
(void)egl->fDestroyStreamKHR(display, stream);
(void)egl->fDestroyStreamKHR(stream);
return 0;
}
@ -87,7 +86,6 @@ class BindAnglePlanes final {
const auto& gl = mParent.mGL;
const auto& gle = GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
const auto& display = egl->Display();
gl->fGenTextures(numPlanes, mTempTexs);
@ -98,13 +96,13 @@ class BindAnglePlanes final {
if (postAttribsList) {
postAttribs = postAttribsList[i];
}
mStreams[i] = StreamFromD3DTexture(egl, texD3DList[i], postAttribs);
mStreams[i] = StreamFromD3DTexture(egl.get(), texD3DList[i], postAttribs);
mSuccess &= bool(mStreams[i]);
}
if (mSuccess) {
for (uint8_t i = 0; i < mNumPlanes; i++) {
MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(display, mStreams[i]));
MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStreams[i]));
auto& mutex = mMutexList[i];
texD3DList[i]->QueryInterface(IID_IDXGIKeyedMutex,
@ -124,11 +122,10 @@ class BindAnglePlanes final {
const auto& gl = mParent.mGL;
const auto& gle = GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
const auto& display = egl->Display();
if (mSuccess) {
for (uint8_t i = 0; i < mNumPlanes; i++) {
MOZ_ALWAYS_TRUE(egl->fStreamConsumerReleaseKHR(display, mStreams[i]));
MOZ_ALWAYS_TRUE(egl->fStreamConsumerReleaseKHR(mStreams[i]));
if (mMutexList[i]) {
mMutexList[i]->ReleaseSync(0);
}
@ -136,7 +133,7 @@ class BindAnglePlanes final {
}
for (uint8_t i = 0; i < mNumPlanes; i++) {
(void)egl->fDestroyStreamKHR(display, mStreams[i]);
(void)egl->fDestroyStreamKHR(mStreams[i]);
}
gl->fDeleteTextures(mNumPlanes, mTempTexs);
@ -155,9 +152,9 @@ ID3D11Device* GLBlitHelper::GetD3D11() const {
const auto& gle = GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
EGLDeviceEXT deviceEGL = 0;
MOZ_ALWAYS_TRUE(egl->fQueryDisplayAttribEXT(
egl->Display(), LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&deviceEGL));
if (!egl->fQueryDeviceAttribEXT(
MOZ_ALWAYS_TRUE(egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT,
(EGLAttrib*)&deviceEGL));
if (!egl->mLib->fQueryDeviceAttribEXT(
deviceEGL, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)(ID3D11Device**)getter_AddRefs(mD3D11))) {
MOZ_ASSERT(false, "d3d9?");

View File

@ -2326,8 +2326,6 @@ uint32_t GetBytesPerTexel(GLenum format, GLenum type) {
bool GLContext::MakeCurrent(bool aForce) const {
if (MOZ_UNLIKELY(IsContextLost())) return false;
if (MOZ_UNLIKELY(!IsAliveImpl())) return false;
if (MOZ_LIKELY(!aForce)) {
bool isCurrent;
if (mUseTLSIsCurrent) {

View File

@ -301,7 +301,6 @@ class GLContext : public GenericAtomicRefCounted, public SupportsWeakPtr {
virtual GLContextType GetContextType() const = 0;
virtual bool IsAliveImpl() const = 0;
virtual bool IsCurrentImpl() const = 0;
virtual bool MakeCurrentImpl() const = 0;

View File

@ -61,8 +61,6 @@ class GLContextCGL : public GLContext {
// the active GPU has changed since the last call.
void MigrateToActiveGPU();
virtual bool IsAliveImpl() const override;
virtual bool MakeCurrentImpl() const override;
virtual bool IsCurrentImpl() const override;

View File

@ -40,8 +40,6 @@ class GLContextEAGL : public GLContext {
EAGLContext* GetEAGLContext() const { return mContext; }
virtual bool IsAliveImpl() const override;
virtual bool MakeCurrentImpl() const override;
virtual bool IsCurrentImpl() const override;

View File

@ -10,28 +10,47 @@
#include "GLContext.h"
#include "GLLibraryEGL.h"
#include "nsRegion.h"
#include <memory>
class gfxASurface;
namespace mozilla {
namespace layers {
class SurfaceTextureImage;
} // namespace layers
namespace widget {
class CompositorWidget;
} // namespace widget
namespace gl {
class GLContextEGL : public GLContext {
friend class TextureImageEGL;
RefPtr<GLLibraryEGL> DefaultEglLibrary(nsACString* const out_failureId);
static already_AddRefed<GLContextEGL> CreateGLContext(
GLLibraryEGL*, const GLContextDesc&, EGLConfig config, EGLSurface surface,
const bool useGles, nsACString* const out_failureId);
inline std::shared_ptr<EglDisplay> DefaultEglDisplay(
nsACString* const out_failureId) {
const auto lib = DefaultEglLibrary(out_failureId);
if (!lib) {
return nullptr;
}
return lib->DefaultDisplay(out_failureId);
}
// -
class GLContextEGL final : public GLContext {
friend class TextureImageEGL;
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL, override)
GLContextEGL(GLLibraryEGL*, const GLContextDesc&, EGLConfig config,
EGLSurface surface, EGLContext context);
static RefPtr<GLContextEGL> CreateGLContext(
std::shared_ptr<EglDisplay>, const GLContextDesc&, EGLConfig config,
EGLSurface surface, const bool useGles, nsACString* const out_failureId);
private:
GLContextEGL(std::shared_ptr<EglDisplay>, const GLContextDesc&,
EGLConfig config, EGLSurface surface, EGLContext context);
~GLContextEGL();
public:
virtual GLContextType GetContextType() const override {
return GLContextType::EGL;
}
@ -47,8 +66,8 @@ class GLContextEGL : public GLContext {
void SetIsDoubleBuffered(bool aIsDB) { mIsDoubleBuffered = aIsDB; }
virtual bool IsANGLE() const override { return mEgl->IsANGLE(); }
virtual bool IsWARP() const override { return mEgl->IsWARP(); }
virtual bool IsANGLE() const override { return mEgl->mLib->IsANGLE(); }
virtual bool IsWARP() const override { return mEgl->mIsWARP; }
virtual bool BindTexImage() override;
@ -57,8 +76,6 @@ class GLContextEGL : public GLContext {
void SetEGLSurfaceOverride(EGLSurface surf);
EGLSurface GetEGLSurfaceOverride() { return mSurfaceOverride; }
virtual bool IsAliveImpl() const override;
virtual bool MakeCurrentImpl() const override;
virtual bool IsCurrentImpl() const override;
@ -90,17 +107,16 @@ class GLContextEGL : public GLContext {
void Destroy();
static already_AddRefed<GLContextEGL> CreateEGLPBufferOffscreenContext(
const GLContextCreateDesc&, const gfx::IntSize& size,
nsACString* const out_FailureId);
static already_AddRefed<GLContextEGL> CreateEGLPBufferOffscreenContextImpl(
const GLContextCreateDesc&, const gfx::IntSize& size, bool aUseGles,
nsACString* const out_FailureId);
static RefPtr<GLContextEGL> CreateEGLPBufferOffscreenContext(
std::shared_ptr<EglDisplay>, const GLContextCreateDesc&,
const gfx::IntSize& size, nsACString* const out_FailureId);
static RefPtr<GLContextEGL> CreateEGLPBufferOffscreenContextImpl(
std::shared_ptr<EglDisplay>, const GLContextCreateDesc&,
const gfx::IntSize& size, bool aUseGles, nsACString* const out_FailureId);
#if defined(MOZ_WAYLAND) || defined(MOZ_WIDGET_ANDROID)
static EGLSurface CreateEGLSurfaceForCompositorWidget(
widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig);
#endif
protected:
friend class GLContextProviderEGL;
friend class GLContextEGLFactory;
@ -108,7 +124,7 @@ class GLContextEGL : public GLContext {
virtual void OnMarkDestroyed() override;
public:
const RefPtr<GLLibraryEGL> mEgl;
const std::shared_ptr<EglDisplay> mEgl;
const EGLConfig mConfig;
const EGLContext mContext;
@ -129,19 +145,19 @@ class GLContextEGL : public GLContext {
nsIntRegion mDamageRegion;
static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(
GLLibraryEGL*, EGLConfig config, EGLenum bindToTextureFormat,
EglDisplay&, EGLConfig, EGLenum bindToTextureFormat,
gfx::IntSize& pbsize);
#if defined(MOZ_WAYLAND)
static EGLSurface CreateWaylandBufferSurface(GLLibraryEGL*, EGLConfig config,
static EGLSurface CreateWaylandBufferSurface(EglDisplay&, EGLConfig,
gfx::IntSize& pbsize);
#endif
#if defined(MOZ_WIDGET_ANDROID)
public:
EGLSurface CreateCompatibleSurface(void* aWindow);
#endif // defined(MOZ_WIDGET_ANDROID)
EGLSurface CreateCompatibleSurface(void* aWindow) const;
};
bool CreateConfig(GLLibraryEGL* const egl, EGLConfig* aConfig, int32_t depth,
// -
bool CreateConfig(EglDisplay&, EGLConfig* aConfig, int32_t depth,
bool aEnableDepthBuffer, bool aUseGles);
} // namespace gl

View File

@ -43,8 +43,6 @@ class GLContextGLX : public GLContext {
bool Init() override;
bool IsAliveImpl() const override;
bool MakeCurrentImpl() const override;
bool IsCurrentImpl() const override;

View File

@ -80,8 +80,6 @@ CGLContextObj GLContextCGL::GetCGLContext() const {
return static_cast<CGLContextObj>([mContext CGLContextObj]);
}
bool GLContextCGL::IsAliveImpl() const { return true; }
bool GLContextCGL::MakeCurrentImpl() const {
if (mContext) {
[mContext makeCurrentContext];
@ -228,10 +226,6 @@ Maybe<SymbolLoader> GLContextCGL::GetSymbolLoader() const {
return Some(SymbolLoader(*lib));
}
already_AddRefed<GLContext> GLContextProviderCGL::CreateWrappingExisting(void*, void*) {
return nullptr;
}
already_AddRefed<GLContext> GLContextProviderCGL::CreateForCompositorWidget(
CompositorWidget* aCompositorWidget, bool aWebRender, bool aForceAccelerated) {
CreateContextFlags flags = CreateContextFlags::ALLOW_OFFLINE_RENDERER;

View File

@ -123,10 +123,6 @@ bool GLContextEAGL::SwapBuffers() {
void GLContextEAGL::GetWSIInfo(nsCString* const out) const { out->AppendLiteral("EAGL"); }
already_AddRefed<GLContext> GLContextProviderEAGL::CreateWrappingExisting(void*, void*) {
return nullptr;
}
static GLContextEAGL* GetGlobalContextEAGL() {
return static_cast<GLContextEAGL*>(GLContextProviderEAGL::GetGlobalContext());
}

View File

@ -79,12 +79,21 @@
# include <dlfcn.h>
# include <gdk/gdkwayland.h>
# include <wayland-egl.h>
# define IS_WAYLAND_DISPLAY() \
(gdk_display_get_default() && \
GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
# define MOZ_GTK_WAYLAND 1
# endif
#endif
inline bool IsWaylandDisplay() {
#ifdef MOZ_GTK_WAYLAND
return gdk_display_get_default() &&
GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default());
#else
return false;
#endif
}
struct wl_egl_window;
using namespace mozilla::gfx;
namespace mozilla {
@ -109,7 +118,7 @@ static nsDataHashtable<nsPtrHashKey<void>, WaylandGLSurface*> sWaylandGLSurface;
void DeleteWaylandGLSurface(EGLSurface surface) {
// We're running on Wayland which means our EGLSurface may
// have attached Wayland backend data which must be released.
if (IS_WAYLAND_DISPLAY()) {
if (IsWaylandDisplay()) {
auto entry = sWaylandGLSurface.Lookup(surface);
if (entry) {
delete entry.Data();
@ -119,19 +128,7 @@ void DeleteWaylandGLSurface(EGLSurface surface) {
}
#endif
#define ADD_ATTR_2(_array, _k, _v) \
do { \
(_array).AppendElement(_k); \
(_array).AppendElement(_v); \
} while (0)
#define ADD_ATTR_1(_array, _k) \
do { \
(_array).AppendElement(_k); \
} while (0)
static bool CreateConfigScreen(GLLibraryEGL* const egl,
EGLConfig* const aConfig,
static bool CreateConfigScreen(EglDisplay&, EGLConfig* const aConfig,
const bool aEnableDepthBuffer,
const bool aUseGles);
@ -164,28 +161,20 @@ static bool is_power_of_two(int v) {
return (v & (v - 1)) == 0;
}
static void DestroySurface(GLLibraryEGL* const egl,
const EGLSurface oldSurface) {
static void DestroySurface(EglDisplay& egl, const EGLSurface oldSurface) {
if (oldSurface != EGL_NO_SURFACE) {
// TODO: This breaks TLS MakeCurrent caching.
egl->fMakeCurrent(egl->Display(), EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
egl->fDestroySurface(egl->Display(), oldSurface);
egl.fMakeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
egl.fDestroySurface(oldSurface);
#if defined(MOZ_WAYLAND)
DeleteWaylandGLSurface(oldSurface);
#endif
}
}
static EGLSurface CreateFallbackSurface(GLLibraryEGL* const egl,
static EGLSurface CreateFallbackSurface(EglDisplay& egl,
const EGLConfig& config) {
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
gfxCriticalNote << "Failed to load EGL library 3!";
return EGL_NO_SURFACE;
}
if (egl->IsExtensionSupported(GLLibraryEGL::KHR_surfaceless_context)) {
if (egl.IsExtensionSupported(EGLExtension::KHR_surfaceless_context)) {
// We don't need a PBuffer surface in this case
return EGL_NO_SURFACE;
}
@ -200,8 +189,7 @@ static EGLSurface CreateFallbackSurface(GLLibraryEGL* const egl,
pbattrs.push_back(cur);
}
EGLSurface surface =
egl->fCreatePbufferSurface(egl->Display(), config, pbattrs.data());
EGLSurface surface = egl.fCreatePbufferSurface(config, pbattrs.data());
if (!surface) {
MOZ_CRASH("Failed to create fallback EGLSurface");
}
@ -210,13 +198,7 @@ static EGLSurface CreateFallbackSurface(GLLibraryEGL* const egl,
}
static EGLSurface CreateSurfaceFromNativeWindow(
GLLibraryEGL* const egl, const EGLNativeWindowType window,
const EGLConfig config) {
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
gfxCriticalNote << "Failed to load EGL library 7!";
return EGL_NO_SURFACE;
}
EglDisplay& egl, const EGLNativeWindowType window, const EGLConfig config) {
MOZ_ASSERT(window);
EGLSurface newSurface = EGL_NO_SURFACE;
@ -227,11 +209,11 @@ static EGLSurface CreateSurfaceFromNativeWindow(
if (!nativeWindow) {
return EGL_NO_SURFACE;
}
newSurface = egl->fCreateWindowSurface(egl->fGetDisplay(EGL_DEFAULT_DISPLAY),
config, nativeWindow, 0);
const auto& display = egl.mLib->fGetDisplay(EGL_DEFAULT_DISPLAY);
newSurface = egl.mLib->fCreateWindowSurface(display, config, nativeWindow, 0);
ANativeWindow_release(nativeWindow);
#else
newSurface = egl->fCreateWindowSurface(egl->Display(), config, window, 0);
newSurface = egl.fCreateWindowSurface(config, window, 0);
#endif
return newSurface;
}
@ -257,35 +239,41 @@ class GLContextEGLFactory {
already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
EGLNativeWindowType aWindow, bool aWebRender, bool aUseGles,
int32_t aDepth) {
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
gfxCriticalNote << "Failed to load EGL library 3!";
nsCString failureId;
const auto lib = gl::DefaultEglLibrary(&failureId);
if (!lib) {
gfxCriticalNote << "Failed[3] to load EGL library: " << failureId.get();
return nullptr;
}
const auto egl = lib->CreateDisplay(true, &failureId);
if (!egl) {
gfxCriticalNote << "Failed[3] to create EGL library display: "
<< failureId.get();
return nullptr;
}
auto* egl = gl::GLLibraryEGL::Get();
bool doubleBuffered = true;
EGLConfig config;
if (aWebRender && egl->IsANGLE()) {
if (aWebRender && egl->mLib->IsANGLE()) {
// Force enable alpha channel to make sure ANGLE use correct framebuffer
// formart
const int bpp = 32;
const bool withDepth = true;
if (!CreateConfig(egl, &config, bpp, withDepth, aUseGles)) {
if (!CreateConfig(*egl, &config, bpp, withDepth, aUseGles)) {
gfxCriticalNote << "Failed to create EGLConfig for WebRender ANGLE!";
return nullptr;
}
} else {
if (aDepth) {
if (!CreateConfig(egl, &config, aDepth, aWebRender, aUseGles)) {
if (!CreateConfig(*egl, &config, aDepth, aWebRender, aUseGles)) {
gfxCriticalNote
<< "Failed to create EGLConfig for WebRender with depth!";
return nullptr;
}
} else {
if (!CreateConfigScreen(egl, &config, /* aEnableDepthBuffer */ aWebRender,
aUseGles)) {
if (!CreateConfigScreen(*egl, &config,
/* aEnableDepthBuffer */ aWebRender, aUseGles)) {
gfxCriticalNote << "Failed to create EGLConfig!";
return nullptr;
}
@ -294,7 +282,7 @@ already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
EGLSurface surface = EGL_NO_SURFACE;
if (aWindow) {
surface = mozilla::gl::CreateSurfaceFromNativeWindow(egl, aWindow, config);
surface = mozilla::gl::CreateSurfaceFromNativeWindow(*egl, aWindow, config);
}
CreateContextFlags flags = CreateContextFlags::NONE;
@ -307,26 +295,24 @@ already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
const auto desc = GLContextDesc{{flags}, false};
RefPtr<GLContextEGL> gl = GLContextEGL::CreateGLContext(
egl, desc, config, surface, aUseGles, &discardFailureId);
egl, desc, config, surface, aUseGles, &failureId);
if (!gl) {
const auto err = egl->fGetError();
const auto err = egl->mLib->fGetError();
gfxCriticalNote << "Failed to create EGLContext!: " << gfx::hexa(err);
mozilla::gl::DestroySurface(egl, surface);
mozilla::gl::DestroySurface(*egl, surface);
return nullptr;
}
gl->MakeCurrent();
gl->SetIsDoubleBuffered(doubleBuffered);
#if defined(MOZ_WAYLAND)
if (surface != EGL_NO_SURFACE && IS_WAYLAND_DISPLAY()) {
if (surface && IsWaylandDisplay()) {
// Make eglSwapBuffers() non-blocking on wayland
egl->fSwapInterval(egl->Display(), 0);
egl->fSwapInterval(0);
}
#endif
if (aWebRender && egl->IsANGLE()) {
if (aWebRender && egl->mLib->IsANGLE()) {
MOZ_ASSERT(doubleBuffered);
egl->fSwapInterval(egl->Display(), 0);
egl->fSwapInterval(0);
}
return gl.forget();
}
@ -344,12 +330,12 @@ already_AddRefed<GLContext> GLContextEGLFactory::Create(
return glContext.forget();
}
#if defined(MOZ_WAYLAND) || defined(MOZ_WIDGET_ANDROID)
/* static */
EGLSurface GLContextEGL::CreateEGLSurfaceForCompositorWidget(
widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig) {
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
const auto egl = DefaultEglDisplay(&discardFailureId);
if (!egl) {
gfxCriticalNote << "Failed to load EGL library 6!";
return EGL_NO_SURFACE;
}
@ -362,23 +348,21 @@ EGLSurface GLContextEGL::CreateEGLSurfaceForCompositorWidget(
return EGL_NO_SURFACE;
}
const auto& egl = GLLibraryEGL::Get();
return mozilla::gl::CreateSurfaceFromNativeWindow(egl, window, aConfig);
return mozilla::gl::CreateSurfaceFromNativeWindow(*egl, window, aConfig);
}
#endif
GLContextEGL::GLContextEGL(GLLibraryEGL* const egl, const GLContextDesc& desc,
EGLConfig config, EGLSurface surface,
EGLContext context)
GLContextEGL::GLContextEGL(const std::shared_ptr<EglDisplay> egl,
const GLContextDesc& desc, EGLConfig config,
EGLSurface surface, EGLContext context)
: GLContext(desc, nullptr, false),
mEgl(egl),
mConfig(config),
mContext(context),
mSurface(surface),
mFallbackSurface(CreateFallbackSurface(mEgl, mConfig)) {
mFallbackSurface(CreateFallbackSurface(*mEgl, mConfig)) {
#ifdef DEBUG
printf_stderr("Initializing context %p surface %p on display %p\n", mContext,
mSurface, mEgl->Display());
mSurface, mEgl->mDisplay);
#endif
}
@ -392,19 +376,19 @@ GLContextEGL::~GLContextEGL() {
MarkDestroyed();
// Wrapped context should not destroy eglContext/Surface
if (!mOwnsContext || !mEgl->IsAlive()) {
if (!mOwnsContext) {
return;
}
#ifdef DEBUG
printf_stderr("Destroying context %p surface %p on display %p\n", mContext,
mSurface, mEgl->Display());
mSurface, mEgl->mDisplay);
#endif
mEgl->fDestroyContext(mEgl->Display(), mContext);
mEgl->fDestroyContext(mContext);
mozilla::gl::DestroySurface(mEgl, mSurface);
mozilla::gl::DestroySurface(mEgl, mFallbackSurface);
mozilla::gl::DestroySurface(*mEgl, mSurface);
mozilla::gl::DestroySurface(*mEgl, mFallbackSurface);
}
bool GLContextEGL::Init() {
@ -416,9 +400,10 @@ bool GLContextEGL::Init() {
return false;
}
mShareWithEGLImage = mEgl->HasKHRImageBase() &&
mEgl->HasKHRImageTexture2D() &&
IsExtensionSupported(OES_EGL_image);
mShareWithEGLImage =
mEgl->HasKHRImageBase() &&
mEgl->IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
IsExtensionSupported(OES_EGL_image);
return true;
}
@ -428,8 +413,8 @@ bool GLContextEGL::BindTexImage() {
if (mBound && !ReleaseTexImage()) return false;
EGLBoolean success = mEgl->fBindTexImage(
mEgl->Display(), (EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
EGLBoolean success =
mEgl->fBindTexImage((EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
if (success == LOCAL_EGL_FALSE) return false;
mBound = true;
@ -442,8 +427,7 @@ bool GLContextEGL::ReleaseTexImage() {
if (!mSurface) return false;
EGLBoolean success;
success = mEgl->fReleaseTexImage(mEgl->Display(), (EGLSurface)mSurface,
LOCAL_EGL_BACK_BUFFER);
success = mEgl->fReleaseTexImage((EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
if (success == LOCAL_EGL_FALSE) return false;
mBound = false;
@ -456,8 +440,6 @@ void GLContextEGL::SetEGLSurfaceOverride(EGLSurface surf) {
MOZ_ASSERT(ok);
}
bool GLContextEGL::IsAliveImpl() const { return mEgl->IsAlive(); }
bool GLContextEGL::MakeCurrentImpl() const {
EGLSurface surface =
(mSurfaceOverride != EGL_NO_SURFACE) ? mSurfaceOverride : mSurface;
@ -465,10 +447,9 @@ bool GLContextEGL::MakeCurrentImpl() const {
surface = mFallbackSurface;
}
const bool succeeded =
mEgl->fMakeCurrent(mEgl->Display(), surface, surface, mContext);
const bool succeeded = mEgl->fMakeCurrent(surface, surface, mContext);
if (!succeeded) {
const auto eglError = mEgl->fGetError();
const auto eglError = mEgl->mLib->fGetError();
if (eglError == LOCAL_EGL_CONTEXT_LOST) {
OnContextLostError();
} else {
@ -483,7 +464,7 @@ bool GLContextEGL::MakeCurrentImpl() const {
}
bool GLContextEGL::IsCurrentImpl() const {
return mEgl->fGetCurrentContext() == mContext;
return mEgl->mLib->fGetCurrentContext() == mContext;
}
bool GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
@ -499,8 +480,8 @@ bool GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
EGLNativeWindowType nativeWindow =
GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aWidget);
if (nativeWindow) {
mSurface =
mozilla::gl::CreateSurfaceFromNativeWindow(mEgl, nativeWindow, mConfig);
mSurface = mozilla::gl::CreateSurfaceFromNativeWindow(*mEgl, nativeWindow,
mConfig);
if (!mSurface) {
NS_WARNING("Failed to create EGLSurface from native window");
return false;
@ -508,18 +489,16 @@ bool GLContextEGL::RenewSurface(CompositorWidget* aWidget) {
}
const bool ok = MakeCurrent(true);
MOZ_ASSERT(ok);
#if defined(MOZ_WAYLAND)
if (mSurface && IS_WAYLAND_DISPLAY()) {
if (mSurface && IsWaylandDisplay()) {
// Make eglSwapBuffers() non-blocking on wayland
mEgl->fSwapInterval(mEgl->Display(), 0);
mEgl->fSwapInterval(0);
}
#endif
return ok;
}
void GLContextEGL::ReleaseSurface() {
if (mOwnsContext) {
mozilla::gl::DestroySurface(mEgl, mSurface);
mozilla::gl::DestroySurface(*mEgl, mSurface);
}
if (mSurface == mSurfaceOverride) {
mSurfaceOverride = EGL_NO_SURFACE;
@ -528,7 +507,7 @@ void GLContextEGL::ReleaseSurface() {
}
Maybe<SymbolLoader> GLContextEGL::GetSymbolLoader() const {
return mEgl->GetSymbolLoader();
return mEgl->mLib->GetSymbolLoader();
}
bool GLContextEGL::SwapBuffers() {
@ -536,9 +515,9 @@ bool GLContextEGL::SwapBuffers() {
mSurfaceOverride != EGL_NO_SURFACE ? mSurfaceOverride : mSurface;
if (surface) {
if ((mEgl->IsExtensionSupported(
GLLibraryEGL::EXT_swap_buffers_with_damage) ||
EGLExtension::EXT_swap_buffers_with_damage) ||
mEgl->IsExtensionSupported(
GLLibraryEGL::KHR_swap_buffers_with_damage))) {
EGLExtension::KHR_swap_buffers_with_damage))) {
std::vector<EGLint> rects;
for (auto iter = mDamageRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& r = iter.Get();
@ -548,10 +527,10 @@ bool GLContextEGL::SwapBuffers() {
rects.push_back(r.Height());
}
mDamageRegion.SetEmpty();
return mEgl->fSwapBuffersWithDamage(mEgl->Display(), surface,
rects.data(), rects.size() / 4);
return mEgl->fSwapBuffersWithDamage(surface, rects.data(),
rects.size() / 4);
}
return mEgl->fSwapBuffers(mEgl->Display(), surface);
return mEgl->fSwapBuffers(surface);
} else {
return false;
}
@ -564,19 +543,20 @@ void GLContextEGL::SetDamage(const nsIntRegion& aDamageRegion) {
void GLContextEGL::GetWSIInfo(nsCString* const out) const {
out->AppendLiteral("EGL_VENDOR: ");
out->Append(
(const char*)mEgl->fQueryString(mEgl->Display(), LOCAL_EGL_VENDOR));
(const char*)mEgl->mLib->fQueryString(mEgl->mDisplay, LOCAL_EGL_VENDOR));
out->AppendLiteral("\nEGL_VERSION: ");
out->Append(
(const char*)mEgl->fQueryString(mEgl->Display(), LOCAL_EGL_VERSION));
(const char*)mEgl->mLib->fQueryString(mEgl->mDisplay, LOCAL_EGL_VERSION));
out->AppendLiteral("\nEGL_EXTENSIONS: ");
out->Append(
(const char*)mEgl->fQueryString(mEgl->Display(), LOCAL_EGL_EXTENSIONS));
out->Append((const char*)mEgl->mLib->fQueryString(mEgl->mDisplay,
LOCAL_EGL_EXTENSIONS));
#ifndef ANDROID // This query will crash some old android.
out->AppendLiteral("\nEGL_EXTENSIONS(nullptr): ");
out->Append((const char*)mEgl->fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
out->Append(
(const char*)mEgl->mLib->fQueryString(nullptr, LOCAL_EGL_EXTENSIONS));
#endif
}
@ -585,7 +565,7 @@ void GLContextEGL::GetWSIInfo(nsCString* const out) const {
void GLContextEGL::HoldSurface(gfxASurface* aSurf) { mThebesSurface = aSurf; }
bool GLContextEGL::HasBufferAge() const {
return mEgl->IsExtensionSupported(GLLibraryEGL::EXT_buffer_age);
return mEgl->IsExtensionSupported(EGLExtension::EXT_buffer_age);
}
EGLint GLContextEGL::GetBufferAge() const {
@ -594,8 +574,7 @@ EGLint GLContextEGL::GetBufferAge() const {
if (surface && HasBufferAge()) {
EGLint result;
mEgl->fQuerySurface(mEgl->Display(), surface, LOCAL_EGL_BUFFER_AGE_EXT,
&result);
mEgl->fQuerySurface(surface, LOCAL_EGL_BUFFER_AGE_EXT, &result);
return result;
}
@ -604,15 +583,17 @@ EGLint GLContextEGL::GetBufferAge() const {
#define LOCAL_EGL_CONTEXT_PROVOKING_VERTEX_DONT_CARE_MOZ 0x6000
already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
GLLibraryEGL* const egl, const GLContextDesc& desc, EGLConfig config,
EGLSurface surface, const bool useGles, nsACString* const out_failureId) {
RefPtr<GLContextEGL> GLContextEGL::CreateGLContext(
const std::shared_ptr<EglDisplay> egl, const GLContextDesc& desc,
EGLConfig config, EGLSurface surface, const bool useGles,
nsACString* const out_failureId) {
const auto& flags = desc.flags;
std::vector<EGLint> required_attribs;
if (useGles) {
if (egl->fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
// TODO: This fBindAPI could be more thread-safe
if (egl->mLib->fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
*out_failureId = "FEATURE_FAILURE_EGL_ES"_ns;
NS_WARNING("Failed to bind API to GLES!");
return nullptr;
@ -624,7 +605,7 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
required_attribs.push_back(2);
}
} else {
if (egl->fBindAPI(LOCAL_EGL_OPENGL_API) == LOCAL_EGL_FALSE) {
if (egl->mLib->fBindAPI(LOCAL_EGL_OPENGL_API) == LOCAL_EGL_FALSE) {
*out_failureId = "FEATURE_FAILURE_EGL"_ns;
NS_WARNING("Failed to bind API to GL!");
return nullptr;
@ -643,7 +624,8 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
}
}
if ((flags & CreateContextFlags::PREFER_EXACT_VERSION) && egl->IsANGLE()) {
if ((flags & CreateContextFlags::PREFER_EXACT_VERSION) &&
egl->mLib->IsANGLE()) {
required_attribs.push_back(
LOCAL_EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE);
required_attribs.push_back(LOCAL_EGL_FALSE);
@ -651,14 +633,14 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
const auto debugFlags = GLContext::ChooseDebugFlags(flags);
if (!debugFlags && flags & CreateContextFlags::NO_VALIDATION &&
egl->IsExtensionSupported(GLLibraryEGL::KHR_create_context_no_error)) {
egl->IsExtensionSupported(EGLExtension::KHR_create_context_no_error)) {
required_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_NO_ERROR_KHR);
required_attribs.push_back(LOCAL_EGL_TRUE);
}
if (flags & CreateContextFlags::PROVOKING_VERTEX_DONT_CARE &&
egl->IsExtensionSupported(
GLLibraryEGL::MOZ_create_context_provoking_vertex_dont_care)) {
EGLExtension::MOZ_create_context_provoking_vertex_dont_care)) {
required_attribs.push_back(
LOCAL_EGL_CONTEXT_PROVOKING_VERTEX_DONT_CARE_MOZ);
required_attribs.push_back(LOCAL_EGL_TRUE);
@ -668,7 +650,7 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
std::vector<EGLint> rbab_attribs; // RBAB: Robust Buffer Access Behavior
if (flags & CreateContextFlags::PREFER_ROBUSTNESS) {
if (egl->IsExtensionSupported(
GLLibraryEGL::EXT_create_context_robustness)) {
EGLExtension::EXT_create_context_robustness)) {
robustness_attribs = required_attribs;
robustness_attribs.push_back(
LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT);
@ -684,7 +666,7 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
rbab_attribs.push_back(LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT);
rbab_attribs.push_back(LOCAL_EGL_TRUE);
}
} else if (egl->IsExtensionSupported(GLLibraryEGL::KHR_create_context)) {
} else if (egl->IsExtensionSupported(EGLExtension::KHR_create_context)) {
robustness_attribs = required_attribs;
robustness_attribs.push_back(
LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR);
@ -703,7 +685,7 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
terminated_attribs.push_back(cur);
}
return egl->fCreateContext(egl->Display(), config, EGL_NO_CONTEXT,
return egl->fCreateContext(config, EGL_NO_CONTEXT,
terminated_attribs.data());
};
@ -737,12 +719,17 @@ already_AddRefed<GLContextEGL> GLContextEGL::CreateGLContext(
return nullptr;
}
return glContext.forget();
if (GLContext::ShouldSpew()) {
printf_stderr("new GLContextEGL %p on EGLDisplay %p\n", glContext.get(),
egl->mDisplay);
}
return glContext;
}
// static
EGLSurface GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(
GLLibraryEGL* const egl, EGLConfig config, EGLenum bindToTextureFormat,
EglDisplay& egl, EGLConfig config, EGLenum bindToTextureFormat,
mozilla::gfx::IntSize& pbsize) {
nsTArray<EGLint> pbattrs(16);
EGLSurface surface = nullptr;
@ -766,7 +753,7 @@ TRY_AGAIN_POWER_OF_TWO:
pbattrs.AppendElement(cur);
}
surface = egl->fCreatePbufferSurface(egl->Display(), config, &pbattrs[0]);
surface = egl.fCreatePbufferSurface(config, &pbattrs[0]);
if (!surface) {
if (!is_power_of_two(pbsize.width) || !is_power_of_two(pbsize.height)) {
if (!is_power_of_two(pbsize.width))
@ -794,28 +781,33 @@ WaylandGLSurface::~WaylandGLSurface() {
wl_egl_window_destroy(mEGLWindow);
wl_surface_destroy(mWaylandSurface);
}
#endif
// static
EGLSurface GLContextEGL::CreateWaylandBufferSurface(
GLLibraryEGL* const egl, EGLConfig config, mozilla::gfx::IntSize& pbsize) {
EglDisplay& egl, EGLConfig config, mozilla::gfx::IntSize& pbsize) {
wl_egl_window* eglwindow = nullptr;
#ifdef MOZ_GTK_WAYLAND
struct wl_compositor* compositor =
gdk_wayland_display_get_wl_compositor(gdk_display_get_default());
struct wl_surface* wlsurface = wl_compositor_create_surface(compositor);
struct wl_egl_window* eglwindow =
wl_egl_window_create(wlsurface, pbsize.width, pbsize.height);
EGLSurface surface =
egl->fCreateWindowSurface(egl->Display(), config, eglwindow, 0);
eglwindow = wl_egl_window_create(wlsurface, pbsize.width, pbsize.height);
#endif
if (!eglwindow) return nullptr;
const auto surface = egl.fCreateWindowSurface(
config, reinterpret_cast<EGLNativeWindowType>(eglwindow), 0);
if (surface) {
#ifdef MOZ_GTK_WAYLAND
WaylandGLSurface* waylandData = new WaylandGLSurface(wlsurface, eglwindow);
auto entry = sWaylandGLSurface.LookupForAdd(surface);
entry.OrInsert([&waylandData]() { return waylandData; });
#endif
}
return surface;
}
#endif
static const EGLint kEGLConfigAttribsRGB16[] = {
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
@ -838,7 +830,7 @@ static const EGLint kEGLConfigAttribsRGBA32[] = {
LOCAL_EGL_BLUE_SIZE, 8,
LOCAL_EGL_ALPHA_SIZE, 8};
bool CreateConfig(GLLibraryEGL* const egl, EGLConfig* aConfig, int32_t depth,
bool CreateConfig(EglDisplay& egl, EGLConfig* aConfig, int32_t depth,
bool aEnableDepthBuffer, bool aUseGles) {
EGLConfig configs[64];
std::vector<EGLint> attribs;
@ -873,29 +865,23 @@ bool CreateConfig(GLLibraryEGL* const egl, EGLConfig* aConfig, int32_t depth,
attribs.push_back(cur);
}
if (!egl->fChooseConfig(egl->Display(), attribs.data(), configs, ncfg,
&ncfg) ||
ncfg < 1) {
if (!egl.fChooseConfig(attribs.data(), configs, ncfg, &ncfg) || ncfg < 1) {
return false;
}
for (int j = 0; j < ncfg; ++j) {
EGLConfig config = configs[j];
EGLint r, g, b, a;
if (egl->fGetConfigAttrib(egl->Display(), config, LOCAL_EGL_RED_SIZE, &r) &&
egl->fGetConfigAttrib(egl->Display(), config, LOCAL_EGL_GREEN_SIZE,
&g) &&
egl->fGetConfigAttrib(egl->Display(), config, LOCAL_EGL_BLUE_SIZE,
&b) &&
egl->fGetConfigAttrib(egl->Display(), config, LOCAL_EGL_ALPHA_SIZE,
&a) &&
if (egl.fGetConfigAttrib(config, LOCAL_EGL_RED_SIZE, &r) &&
egl.fGetConfigAttrib(config, LOCAL_EGL_GREEN_SIZE, &g) &&
egl.fGetConfigAttrib(config, LOCAL_EGL_BLUE_SIZE, &b) &&
egl.fGetConfigAttrib(config, LOCAL_EGL_ALPHA_SIZE, &a) &&
((depth == 16 && r == 5 && g == 6 && b == 5) ||
(depth == 24 && r == 8 && g == 8 && b == 8) ||
(depth == 32 && r == 8 && g == 8 && b == 8 && a == 8))) {
EGLint z;
if (aEnableDepthBuffer) {
if (!egl->fGetConfigAttrib(egl->Display(), config, LOCAL_EGL_DEPTH_SIZE,
&z) ||
if (!egl.fGetConfigAttrib(config, LOCAL_EGL_DEPTH_SIZE, &z) ||
z != 24) {
continue;
}
@ -912,53 +898,31 @@ bool CreateConfig(GLLibraryEGL* const egl, EGLConfig* aConfig, int32_t depth,
//
// NB: It's entirely legal for the returned EGLConfig to be valid yet
// have the value null.
static bool CreateConfigScreen(GLLibraryEGL* const egl,
EGLConfig* const aConfig,
static bool CreateConfigScreen(EglDisplay& egl, EGLConfig* const aConfig,
const bool aEnableDepthBuffer,
const bool aUseGles) {
int32_t depth = gfxVars::ScreenDepth();
if (!CreateConfig(egl, aConfig, depth, aEnableDepthBuffer, aUseGles)) {
#ifdef MOZ_WIDGET_ANDROID
// Bug 736005
// Android doesn't always support 16 bit so also try 24 bit
if (depth == 16) {
return CreateConfig(egl, aConfig, 24, aEnableDepthBuffer, aUseGles);
}
// Bug 970096
// Some devices that have 24 bit screens only support 16 bit OpenGL?
if (depth == 24) {
return CreateConfig(egl, aConfig, 16, aEnableDepthBuffer, aUseGles);
}
#endif
return false;
} else {
if (CreateConfig(egl, aConfig, depth, aEnableDepthBuffer, aUseGles)) {
return true;
}
}
already_AddRefed<GLContext> GLContextProviderEGL::CreateWrappingExisting(
void* aContext, void* aSurface) {
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 2!");
return nullptr;
#ifdef MOZ_WIDGET_ANDROID
// Bug 736005
// Android doesn't always support 16 bit so also try 24 bit
if (depth == 16) {
return CreateConfig(egl, aConfig, 24, aEnableDepthBuffer, aUseGles);
}
if (!aContext || !aSurface) return nullptr;
const auto& egl = GLLibraryEGL::Get();
EGLConfig config = EGL_NO_CONFIG;
RefPtr<GLContextEGL> gl = new GLContextEGL(
egl, {}, config, (EGLSurface)aSurface, (EGLContext)aContext);
gl->SetIsDoubleBuffered(true);
gl->mOwnsContext = false;
return gl.forget();
// Bug 970096
// Some devices that have 24 bit screens only support 16 bit OpenGL?
if (depth == 24) {
return CreateConfig(egl, aConfig, 16, aEnableDepthBuffer, aUseGles);
}
#endif
return false;
}
already_AddRefed<GLContext> GLContextProviderEGL::CreateForCompositorWidget(
CompositorWidget* aCompositorWidget, bool aWebRender,
bool aForceAccelerated) {
bool /*aForceAccelerated*/) {
EGLNativeWindowType window = nullptr;
int32_t depth = 0;
if (aCompositorWidget) {
@ -970,73 +934,44 @@ already_AddRefed<GLContext> GLContextProviderEGL::CreateForCompositorWidget(
return GLContextEGLFactory::Create(window, aWebRender, depth);
}
#if defined(MOZ_WIDGET_ANDROID)
EGLSurface GLContextEGL::CreateCompatibleSurface(void* aWindow) {
EGLSurface GLContextEGL::CreateCompatibleSurface(void* aWindow) const {
MOZ_ASSERT(aWindow);
if (mConfig == EGL_NO_CONFIG) {
MOZ_CRASH("GFX: Failed with invalid EGLConfig 2!");
}
return GLContextProviderEGL::CreateEGLSurface(aWindow, mConfig);
}
/* static */
static EGLSurface CreateEGLSurfaceImpl(void* aWindow, EGLConfig aConfig,
bool aUseGles) {
// NOTE: aWindow is an ANativeWindow
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 4!");
}
auto* egl = gl::GLLibraryEGL::Get();
EGLConfig config = aConfig;
if (!config && !CreateConfigScreen(egl, &config,
/* aEnableDepthBuffer */ false,
/* useGles */ aUseGles)) {
return EGL_NO_SURFACE;
}
MOZ_ASSERT(aWindow);
return egl->fCreateWindowSurface(egl->Display(), config, aWindow, 0);
}
/* static */
EGLSurface GLContextProviderEGL::CreateEGLSurface(void* aWindow,
EGLConfig aConfig) {
EGLSurface surface =
CreateEGLSurfaceImpl(aWindow, aConfig, /* aUseGles */ false);
if (surface == EGL_NO_SURFACE) {
surface = CreateEGLSurfaceImpl(aWindow, aConfig, /* aUseGles */ true);
if (surface == EGL_NO_SURFACE) {
MOZ_CRASH("GFX: Failed to create EGLSurface 2!");
const auto fnCreate = [&](const bool useGles) -> EGLSurface {
// NOTE: aWindow is an ANativeWindow
auto config = mConfig;
if (!config && !CreateConfigScreen(*mEgl, &config,
/* aEnableDepthBuffer */ false,
/* useGles */ useGles)) {
return nullptr;
}
return mEgl->fCreateWindowSurface(
config, reinterpret_cast<EGLNativeWindowType>(aWindow), 0);
};
auto surface = fnCreate(false);
if (!surface) {
surface = fnCreate(true);
}
if (!surface) {
MOZ_CRASH("GFX: Failed to create EGLSurface 2!");
}
return surface;
}
/* static */
void GLContextProviderEGL::DestroyEGLSurface(EGLSurface surface) {
nsCString discardFailureId;
if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
MOZ_CRASH("GFX: Failed to load EGL library 5!");
}
auto* egl = gl::GLLibraryEGL::Get();
egl->fDestroySurface(egl->Display(), surface);
}
#endif // defined(ANDROID)
static void FillContextAttribs(bool es3, bool useGles, nsTArray<EGLint>* out) {
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
#if defined(MOZ_WAYLAND)
if (IS_WAYLAND_DISPLAY()) {
if (IsWaylandDisplay()) {
// Wayland on desktop does not support PBuffer or FBO.
// We create a dummy wl_egl_window instead.
out->AppendElement(LOCAL_EGL_WINDOW_BIT);
} else {
out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
}
#else
out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
#endif
if (useGles) {
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
@ -1077,15 +1012,14 @@ static void FillContextAttribs(bool es3, bool useGles, nsTArray<EGLint>* out) {
/// Useful for debugging, but normally unused.
static GLint GetAttrib(GLLibraryEGL* egl, EGLConfig config, EGLint attrib) {
EGLint bits = 0;
egl->fGetConfigAttrib(egl->Display(), config, attrib, &bits);
egl->fGetConfigAttrib(config, attrib, &bits);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
return bits;
}
*/
static EGLConfig ChooseConfig(GLLibraryEGL* const egl,
const GLContextCreateDesc& desc,
static EGLConfig ChooseConfig(EglDisplay& egl, const GLContextCreateDesc& desc,
const bool useGles) {
nsTArray<EGLint> configAttribList;
FillContextAttribs(bool(desc.flags & CreateContextFlags::PREFER_ES3), useGles,
@ -1098,8 +1032,7 @@ static EGLConfig ChooseConfig(GLLibraryEGL* const egl,
const EGLint kMaxConfigs = 1;
EGLConfig configs[kMaxConfigs];
EGLint foundConfigs = 0;
if (!egl->fChooseConfig(egl->Display(), configAttribs, configs, kMaxConfigs,
&foundConfigs) ||
if (!egl.fChooseConfig(configAttribs, configs, kMaxConfigs, &foundConfigs) ||
foundConfigs == 0) {
return EGL_NO_CONFIG;
}
@ -1109,18 +1042,11 @@ static EGLConfig ChooseConfig(GLLibraryEGL* const egl,
}
/*static*/
already_AddRefed<GLContextEGL>
GLContextEGL::CreateEGLPBufferOffscreenContextImpl(
const GLContextCreateDesc& desc, const mozilla::gfx::IntSize& size,
const bool useGles, nsACString* const out_failureId) {
const bool forceEnableHardware =
bool(desc.flags & CreateContextFlags::FORCE_ENABLE_HARDWARE);
if (!GLLibraryEGL::EnsureInitialized(forceEnableHardware, out_failureId)) {
return nullptr;
}
auto* egl = gl::GLLibraryEGL::Get();
const EGLConfig config = ChooseConfig(egl, desc, useGles);
RefPtr<GLContextEGL> GLContextEGL::CreateEGLPBufferOffscreenContextImpl(
const std::shared_ptr<EglDisplay> egl, const GLContextCreateDesc& desc,
const mozilla::gfx::IntSize& size, const bool useGles,
nsACString* const out_failureId) {
const EGLConfig config = ChooseConfig(*egl, desc, useGles);
if (config == EGL_NO_CONFIG) {
*out_failureId = "FEATURE_FAILURE_EGL_NO_CONFIG"_ns;
NS_WARNING("Failed to find a compatible config.");
@ -1133,14 +1059,11 @@ GLContextEGL::CreateEGLPBufferOffscreenContextImpl(
mozilla::gfx::IntSize pbSize(size);
EGLSurface surface = nullptr;
#if defined(MOZ_WAYLAND)
if (IS_WAYLAND_DISPLAY()) {
surface = GLContextEGL::CreateWaylandBufferSurface(egl, config, pbSize);
} else
#endif
{
if (IsWaylandDisplay()) {
surface = GLContextEGL::CreateWaylandBufferSurface(*egl, config, pbSize);
} else {
surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(
egl, config, LOCAL_EGL_NONE, pbSize);
*egl, config, LOCAL_EGL_NONE, pbSize);
}
if (!surface) {
*out_failureId = "FEATURE_FAILURE_EGL_POT"_ns;
@ -1154,34 +1077,40 @@ GLContextEGL::CreateEGLPBufferOffscreenContextImpl(
egl, fullDesc, config, surface, useGles, out_failureId);
if (!gl) {
NS_WARNING("Failed to create GLContext from PBuffer");
egl->fDestroySurface(egl->Display(), surface);
egl->fDestroySurface(surface);
#if defined(MOZ_WAYLAND)
DeleteWaylandGLSurface(surface);
#endif
return nullptr;
}
return gl.forget();
return gl;
}
already_AddRefed<GLContextEGL> GLContextEGL::CreateEGLPBufferOffscreenContext(
const GLContextCreateDesc& desc, const mozilla::gfx::IntSize& size,
nsACString* const out_failureId) {
/*static*/
RefPtr<GLContextEGL> GLContextEGL::CreateEGLPBufferOffscreenContext(
const std::shared_ptr<EglDisplay> display, const GLContextCreateDesc& desc,
const mozilla::gfx::IntSize& size, nsACString* const out_failureId) {
RefPtr<GLContextEGL> gl = CreateEGLPBufferOffscreenContextImpl(
desc, size, /* useGles */ false, out_failureId);
display, desc, size, /* useGles */ false, out_failureId);
if (!gl) {
gl = CreateEGLPBufferOffscreenContextImpl(desc, size, /* useGles */ true,
out_failureId);
gl = CreateEGLPBufferOffscreenContextImpl(
display, desc, size, /* useGles */ true, out_failureId);
}
return gl.forget();
return gl;
}
/*static*/
already_AddRefed<GLContext> GLContextProviderEGL::CreateHeadless(
const GLContextCreateDesc& desc, nsACString* const out_failureId) {
const auto display = DefaultEglDisplay(out_failureId);
if (!display) {
return nullptr;
}
mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16);
return GLContextEGL::CreateEGLPBufferOffscreenContext(desc, dummySize,
out_failureId);
auto ret = GLContextEGL::CreateEGLPBufferOffscreenContext(
display, desc, dummySize, out_failureId);
return ret.forget();
}
// Don't want a global context on Android as 1) share groups across 2 threads
@ -1191,12 +1120,31 @@ already_AddRefed<GLContext> GLContextProviderEGL::CreateHeadless(
/*static*/
GLContext* GLContextProviderEGL::GetGlobalContext() { return nullptr; }
// -
static StaticMutex sMutex;
static StaticRefPtr<GLLibraryEGL> gDefaultEglLibrary;
RefPtr<GLLibraryEGL> DefaultEglLibrary(nsACString* const out_failureId) {
StaticMutexAutoLock lock(sMutex);
if (!gDefaultEglLibrary) {
gDefaultEglLibrary = GLLibraryEGL::Create(out_failureId);
if (!gDefaultEglLibrary) {
NS_WARNING("GLLibraryEGL::Create failed");
}
}
return gDefaultEglLibrary.get();
}
// -
/*static*/
void GLContextProviderEGL::Shutdown() {
const RefPtr<GLLibraryEGL> egl = GLLibraryEGL::Get();
if (egl) {
egl->Shutdown();
StaticMutexAutoLock lock(sMutex);
if (!gDefaultEglLibrary) {
return;
}
gDefaultEglLibrary = nullptr;
}
} /* namespace gl */

View File

@ -582,8 +582,6 @@ bool GLContextGLX::Init() {
return true;
}
bool GLContextGLX::IsAliveImpl() const { return true; }
bool GLContextGLX::MakeCurrentImpl() const {
if (mGLX->IsMesa()) {
// Read into the event queue to ensure that Mesa receives a
@ -679,27 +677,6 @@ static bool AreCompatibleVisuals(Visual* one, Visual* two) {
return true;
}
already_AddRefed<GLContext> GLContextProviderGLX::CreateWrappingExisting(
void* aContext, void* aSurface) {
if (!sGLXLibrary.EnsureInitialized()) {
return nullptr;
}
if (aContext && aSurface) {
RefPtr<GLContextGLX> glContext =
new GLContextGLX({},
(Display*)DefaultXDisplay(), // Display
(GLXDrawable)aSurface, (GLXContext)aContext,
false, // aDeleteDrawable,
true, (gfxXlibSurface*)nullptr);
glContext->mOwnsContext = false;
return glContext.forget();
}
return nullptr;
}
already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
bool aWebRender,
bool aForceAccelerated) {

View File

@ -47,23 +47,6 @@ class GL_CONTEXT_PROVIDER_NAME {
static already_AddRefed<GLContext> CreateHeadless(
const GLContextCreateDesc&, nsACString* const out_failureId);
/**
* Create wrapping Gecko GLContext for external gl context.
*
* @param aContext External context which will be wrapped by Gecko GLContext.
* @param aSurface External surface which is used for external context.
*
* @return Wrapping Context to use for rendering
*/
static already_AddRefed<GLContext> CreateWrappingExisting(void* aContext,
void* aSurface);
#if defined(MOZ_WIDGET_ANDROID)
static EGLSurface CreateEGLSurface(void* aWindow,
EGLConfig aConfig = nullptr);
static void DestroyEGLSurface(EGLSurface surface);
#endif // defined(MOZ_WIDGET_ANDROID)
/**
* Get a pointer to the global context, creating it if it doesn't exist.
*/

View File

@ -16,11 +16,6 @@ already_AddRefed<GLContext> GLContextProviderNull::CreateForCompositorWidget(
return nullptr;
}
already_AddRefed<GLContext> GLContextProviderNull::CreateWrappingExisting(
void*, void*) {
return nullptr;
}
already_AddRefed<GLContext> GLContextProviderNull::CreateHeadless(
const GLContextCreateDesc&, nsACString* const out_failureId) {
*out_failureId = "FEATURE_FAILURE_NULL"_ns;

View File

@ -298,8 +298,6 @@ GLContextWGL::~GLContextWGL() {
}
}
bool GLContextWGL::IsAliveImpl() const { return true; }
bool GLContextWGL::MakeCurrentImpl() const {
const bool succeeded = sWGLLib.mSymbols.fMakeCurrent(mDC, mContext);
NS_ASSERTION(succeeded, "Failed to make GL context current!");
@ -320,11 +318,6 @@ void GLContextWGL::GetWSIInfo(nsCString* const out) const {
out->Append(sWGLLib.mSymbols.fGetExtensionsStringARB(mDC));
}
already_AddRefed<GLContext> GLContextProviderWGL::CreateWrappingExisting(
void*, void*) {
return nullptr;
}
HGLRC
WGLLibrary::CreateContextWithFallback(const HDC dc,
const bool tryRobustBuffers) const {

View File

@ -18,15 +18,6 @@ using namespace mozilla::widget;
static class GLContextProviderX11 sGLContextProviderX11;
static class GLContextProviderEGL sGLContextProviderEGL;
already_AddRefed<GLContext> GLContextProviderWayland::CreateWrappingExisting(
void* aContext, void* aSurface) {
if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
return sGLContextProviderX11.CreateWrappingExisting(aContext, aSurface);
} else {
return sGLContextProviderEGL.CreateWrappingExisting(aContext, aSurface);
}
}
already_AddRefed<GLContext> GLContextProviderWayland::CreateForCompositorWidget(
CompositorWidget* aCompositorWidget, bool aWebRender,
bool aForceAccelerated) {

View File

@ -16,15 +16,6 @@ using namespace mozilla::widget;
static class GLContextProviderGLX sGLContextProviderGLX;
static class GLContextProviderEGL sGLContextProviderEGL;
already_AddRefed<GLContext> GLContextProviderX11::CreateWrappingExisting(
void* aContext, void* aSurface) {
if (!gfxVars::UseEGL()) {
return sGLContextProviderGLX.CreateWrappingExisting(aContext, aSurface);
} else {
return sGLContextProviderEGL.CreateWrappingExisting(aContext, aSurface);
}
}
already_AddRefed<GLContext> GLContextProviderX11::CreateForCompositorWidget(
CompositorWidget* aCompositorWidget, bool aWebRender,
bool aForceAccelerated) {

View File

@ -30,7 +30,6 @@ class GLContextWGL final : public GLContext {
return GLContextType::WGL;
}
virtual bool IsAliveImpl() const override;
virtual bool MakeCurrentImpl() const override;
virtual bool IsCurrentImpl() const override;
virtual bool IsDoubleBuffered() const override { return mIsDoubleBuffered; }

View File

@ -46,24 +46,23 @@
namespace mozilla {
namespace gl {
StaticMutex GLLibraryEGL::sMutex;
StaticRefPtr<GLLibraryEGL> GLLibraryEGL::sEGLLibrary;
// should match the order of EGLExtensions, and be null-terminated.
static const char* sEGLLibraryExtensionNames[] = {
"EGL_ANDROID_get_native_client_buffer", "EGL_ANGLE_device_creation",
"EGL_ANGLE_device_creation_d3d11", "EGL_ANGLE_platform_angle",
"EGL_ANGLE_platform_angle_d3d"};
// should match the order of EGLExtensions, and be null-terminated.
static const char* sEGLExtensionNames[] = {
"EGL_KHR_image_base",
"EGL_KHR_image_pixmap",
"EGL_KHR_gl_texture_2D_image",
"EGL_KHR_lock_surface",
"EGL_ANGLE_surface_d3d_texture_2d_share_handle",
"EGL_EXT_create_context_robustness",
"EGL_KHR_image",
"EGL_KHR_fence_sync",
"EGL_ANDROID_native_fence_sync",
"EGL_ANDROID_image_crop",
"EGL_ANDROID_get_native_client_buffer",
"EGL_ANGLE_platform_angle",
"EGL_ANGLE_platform_angle_d3d",
"EGL_ANGLE_d3d_share_handle_client_buffer",
"EGL_KHR_create_context",
"EGL_KHR_stream",
@ -71,8 +70,6 @@ static const char* sEGLExtensionNames[] = {
"EGL_EXT_device_query",
"EGL_NV_stream_consumer_gltexture_yuv",
"EGL_ANGLE_stream_producer_d3d_texture",
"EGL_ANGLE_device_creation",
"EGL_ANGLE_device_creation_d3d11",
"EGL_KHR_surfaceless_context",
"EGL_KHR_create_context_no_error",
"EGL_MOZ_create_context_provoking_vertex_dont_care",
@ -139,14 +136,22 @@ static PRLibrary* LoadLibraryForEGLOnWindows(const nsAString& filename) {
#endif // XP_WIN
static EGLDisplay GetAndInitWARPDisplay(GLLibraryEGL& egl, void* displayType) {
EGLint attrib_list[] = {LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
// Requires:
LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
LOCAL_EGL_NONE};
EGLDisplay display = egl.fGetPlatformDisplayEXT(
static std::shared_ptr<EglDisplay> GetAndInitDisplay(GLLibraryEGL& egl,
void* displayType) {
const auto display = egl.fGetDisplay(displayType);
if (!display) return nullptr;
return EglDisplay::Create(egl, display, false);
}
static std::shared_ptr<EglDisplay> GetAndInitWARPDisplay(GLLibraryEGL& egl,
void* displayType) {
const EGLint attrib_list[] = {LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
LOCAL_EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
// Requires:
LOCAL_EGL_PLATFORM_ANGLE_TYPE_ANGLE,
LOCAL_EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
LOCAL_EGL_NONE};
const EGLDisplay display = egl.fGetPlatformDisplayEXT(
LOCAL_EGL_PLATFORM_ANGLE_ANGLE, displayType, attrib_list);
if (display == EGL_NO_DISPLAY) {
@ -155,61 +160,50 @@ static EGLDisplay GetAndInitWARPDisplay(GLLibraryEGL& egl, void* displayType) {
gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
MOZ_CRASH("GFX: Unexpected GL error.");
}
return EGL_NO_DISPLAY;
return nullptr;
}
if (!egl.fInitialize(display, nullptr, nullptr)) return EGL_NO_DISPLAY;
return display;
return EglDisplay::Create(egl, display, true);
}
static EGLDisplay GetAndInitDisplayForWebRender(GLLibraryEGL& egl,
void* displayType) {
#ifdef XP_WIN
const EGLint attrib_list[] = {LOCAL_EGL_NONE};
RefPtr<ID3D11Device> d3d11Device =
gfx::DeviceManagerDx::Get()->GetCompositorDevice();
if (!d3d11Device) {
gfxCriticalNote << "Failed to get compositor device for EGLDisplay";
return EGL_NO_DISPLAY;
}
EGLDeviceEXT eglDevice = egl.fCreateDeviceANGLE(
LOCAL_EGL_D3D11_DEVICE_ANGLE, reinterpret_cast<void*>(d3d11Device.get()),
nullptr);
std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
ID3D11Device* const d3d11Device) {
EGLDeviceEXT eglDevice =
fCreateDeviceANGLE(LOCAL_EGL_D3D11_DEVICE_ANGLE, d3d11Device, nullptr);
if (!eglDevice) {
gfxCriticalNote << "Failed to get EGLDeviceEXT of D3D11Device";
return EGL_NO_DISPLAY;
return nullptr;
}
// Create an EGLDisplay using the EGLDevice
EGLDisplay display = egl.fGetPlatformDisplayEXT(LOCAL_EGL_PLATFORM_DEVICE_EXT,
eglDevice, attrib_list);
const EGLint attrib_list[] = {LOCAL_EGL_NONE};
const auto display = fGetPlatformDisplayEXT(LOCAL_EGL_PLATFORM_DEVICE_EXT,
eglDevice, attrib_list);
if (!display) {
gfxCriticalNote << "Failed to get EGLDisplay of D3D11Device";
return EGL_NO_DISPLAY;
return nullptr;
}
if (display == EGL_NO_DISPLAY) {
const EGLint err = egl.fGetError();
if (!display) {
const EGLint err = fGetError();
if (err != LOCAL_EGL_SUCCESS) {
gfxCriticalError() << "Unexpected GL error: " << gfx::hexa(err);
MOZ_CRASH("GFX: Unexpected GL error.");
}
return EGL_NO_DISPLAY;
return nullptr;
}
if (!egl.fInitialize(display, nullptr, nullptr)) {
const EGLint err = egl.fGetError();
const auto ret = EglDisplay::Create(*this, display, false);
if (!ret) {
const EGLint err = fGetError();
if (err != LOCAL_EGL_SUCCESS) {
gfxCriticalError()
<< "Failed to initialize EGLDisplay for WebRender error: "
<< gfx::hexa(err);
}
return EGL_NO_DISPLAY;
return nullptr;
}
return display;
#else
return EGL_NO_DISPLAY;
#endif
return ret;
}
static bool IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
@ -234,15 +228,6 @@ static bool IsAccelAngleSupported(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
return (angleSupport == nsIGfxInfo::FEATURE_STATUS_OK);
}
static EGLDisplay GetAndInitDisplay(GLLibraryEGL& egl, void* displayType) {
EGLDisplay display = egl.fGetDisplay(displayType);
if (display == EGL_NO_DISPLAY) return EGL_NO_DISPLAY;
if (!egl.fInitialize(display, nullptr, nullptr)) return EGL_NO_DISPLAY;
return display;
}
class AngleErrorReporting {
public:
AngleErrorReporting() : mFailureId(nullptr) {
@ -282,13 +267,9 @@ class AngleErrorReporting {
AngleErrorReporting gAngleErrorReporter;
static EGLDisplay GetAndInitDisplayForAccelANGLE(
static std::shared_ptr<EglDisplay> GetAndInitDisplayForAccelANGLE(
GLLibraryEGL& egl, nsACString* const out_failureId) {
EGLDisplay ret = 0;
if (wr::RenderThread::IsInRenderThread()) {
return GetAndInitDisplayForWebRender(egl, EGL_DEFAULT_DISPLAY);
}
MOZ_RELEASE_ASSERT(!wr::RenderThread::IsInRenderThread());
gfx::FeatureState& d3d11ANGLE =
gfx::gfxConfig::GetFeature(gfx::Feature::D3D11_HW_ANGLE);
@ -314,6 +295,7 @@ static EGLDisplay GetAndInitDisplayForAccelANGLE(
return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
}
std::shared_ptr<EglDisplay> ret;
if (d3d11ANGLE.IsEnabled()) {
ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
}
@ -329,36 +311,6 @@ static EGLDisplay GetAndInitDisplayForAccelANGLE(
return ret;
}
bool GLLibraryEGL::ReadbackEGLImage(EGLImage image,
gfx::DataSourceSurface* out_surface) {
StaticMutexAutoUnlock lock(sMutex);
if (!mReadbackGL) {
nsCString discardFailureId;
mReadbackGL = gl::GLContextProvider::CreateHeadless({}, &discardFailureId);
}
ScopedTexture destTex(mReadbackGL);
const GLuint target = mReadbackGL->GetPreferredEGLImageTextureTarget();
ScopedBindTexture autoTex(mReadbackGL, destTex.Texture(), target);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_NEAREST);
mReadbackGL->fTexParameteri(target, LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_NEAREST);
mReadbackGL->fEGLImageTargetTexture2D(target, image);
layers::ShaderConfigOGL config =
layers::ShaderConfigFromTargetAndFormat(target, out_surface->GetFormat());
int shaderConfig = config.mFeatures;
mReadbackGL->ReadTexImageHelper()->ReadTexImage(
out_surface, 0, target, out_surface->GetSize(), shaderConfig);
return true;
}
// -
#if defined(XP_UNIX)
@ -379,30 +331,16 @@ Maybe<SymbolLoader> GLLibraryEGL::GetSymbolLoader() const {
// -
/* static */
bool GLLibraryEGL::EnsureInitialized(bool forceAccel,
nsACString* const out_failureId) {
if (!sEGLLibrary) {
sEGLLibrary = new GLLibraryEGL();
RefPtr<GLLibraryEGL> GLLibraryEGL::Create(nsACString* const out_failureId) {
RefPtr<GLLibraryEGL> ret = new GLLibraryEGL;
if (!ret->Init(out_failureId)) {
return nullptr;
}
return sEGLLibrary->DoEnsureInitialized(forceAccel, out_failureId);
return ret;
}
bool GLLibraryEGL::DoEnsureInitialized() {
nsCString failureId;
return DoEnsureInitialized(false, &failureId);
}
bool GLLibraryEGL::DoEnsureInitialized(bool forceAccel,
nsACString* const out_failureId) {
if (mInitialized && !mSymbols.fTerminate) {
*out_failureId = "FEATURE_FAILURE_EGL_DESTROYED"_ns;
MOZ_ASSERT(false);
return false;
}
if (mInitialized) {
return true;
}
bool GLLibraryEGL::Init(nsACString* const out_failureId) {
MOZ_RELEASE_ASSERT(!mSymbols.fTerminate);
mozilla::ScopedGfxFeatureReporter reporter("EGL");
@ -540,9 +478,12 @@ bool GLLibraryEGL::DoEnsureInitialized(bool forceAccel,
*(PRFuncPtr*)&mSymbols.fQueryString = internalFunc;
}
}
const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
InitClientExtensions();
// -
InitLibExtensions();
const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
const auto fnLoadSymbols = [&](const SymLoadStruct* symbols) {
if (pfnLoader.LoadSymbols(symbols)) return true;
@ -552,232 +493,217 @@ bool GLLibraryEGL::DoEnsureInitialized(bool forceAccel,
};
// Check the ANGLE support the system has
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
mIsANGLE = IsExtensionSupported(ANGLE_platform_angle);
mIsANGLE = IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle);
// Client exts are ready. (But not display exts!)
if (mIsANGLE) {
MOZ_ASSERT(IsExtensionSupported(ANGLE_platform_angle_d3d));
MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d));
const SymLoadStruct angleSymbols[] = {SYMBOL(GetPlatformDisplayEXT),
END_OF_SYMBOLS};
if (!fnLoadSymbols(angleSymbols)) {
gfxCriticalError() << "Failed to load ANGLE symbols!";
return false;
}
MOZ_ASSERT(IsExtensionSupported(ANGLE_platform_angle_d3d));
MOZ_ASSERT(IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d));
const SymLoadStruct createDeviceSymbols[] = {
SYMBOL(CreateDeviceANGLE), SYMBOL(ReleaseDeviceANGLE), END_OF_SYMBOLS};
if (!fnLoadSymbols(createDeviceSymbols)) {
NS_ERROR(
"EGL supports ANGLE_device_creation without exposing its functions!");
MarkExtensionUnsupported(ANGLE_device_creation);
MarkExtensionUnsupported(EGLLibExtension::ANGLE_device_creation);
}
}
mEGLDisplay = CreateDisplay(forceAccel, gfxInfo, out_failureId);
if (!mEGLDisplay) {
return false;
}
InitDisplayExtensions();
////////////////////////////////////
// Alright, load display exts.
if (IsExtensionSupported(KHR_lock_surface)) {
const SymLoadStruct lockSymbols[] = {
SYMBOL(LockSurfaceKHR), SYMBOL(UnlockSurfaceKHR), END_OF_SYMBOLS};
if (!fnLoadSymbols(lockSymbols)) {
NS_ERROR("EGL supports KHR_lock_surface without exposing its functions!");
MarkExtensionUnsupported(KHR_lock_surface);
// ANDROID_get_native_client_buffer isn't necessarily enumerated in lib exts,
// but it is one.
{
const SymLoadStruct symbols[] = {SYMBOL(GetNativeClientBufferANDROID),
END_OF_SYMBOLS};
if (fnLoadSymbols(symbols)) {
mAvailableExtensions[UnderlyingValue(
EGLLibExtension::ANDROID_get_native_client_buffer)] = true;
}
}
if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
const SymLoadStruct d3dSymbols[] = {SYMBOL(QuerySurfacePointerANGLE),
END_OF_SYMBOLS};
if (!fnLoadSymbols(d3dSymbols)) {
NS_ERROR(
"EGL supports ANGLE_surface_d3d_texture_2d_share_handle without "
"exposing its functions!");
MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);
}
}
// -
// Load possible display ext symbols.
if (IsExtensionSupported(KHR_fence_sync)) {
const SymLoadStruct syncSymbols[] = {
{
const SymLoadStruct symbols[] = {SYMBOL(QuerySurfacePointerANGLE),
END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
{
const SymLoadStruct symbols[] = {
SYMBOL(CreateSyncKHR), SYMBOL(DestroySyncKHR),
SYMBOL(ClientWaitSyncKHR), SYMBOL(GetSyncAttribKHR), END_OF_SYMBOLS};
if (!fnLoadSymbols(syncSymbols)) {
NS_ERROR("EGL supports KHR_fence_sync without exposing its functions!");
MarkExtensionUnsupported(KHR_fence_sync);
}
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base)) {
const SymLoadStruct imageSymbols[] = {
SYMBOL(CreateImageKHR), SYMBOL(DestroyImageKHR), END_OF_SYMBOLS};
if (!fnLoadSymbols(imageSymbols)) {
NS_ERROR("EGL supports KHR_image(_base) without exposing its functions!");
MarkExtensionUnsupported(KHR_image);
MarkExtensionUnsupported(KHR_image_base);
MarkExtensionUnsupported(KHR_image_pixmap);
}
} else {
MarkExtensionUnsupported(KHR_image_pixmap);
{
const SymLoadStruct symbols[] = {SYMBOL(CreateImageKHR),
SYMBOL(DestroyImageKHR), END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(ANDROID_native_fence_sync)) {
const SymLoadStruct nativeFenceSymbols[] = {SYMBOL(DupNativeFenceFDANDROID),
END_OF_SYMBOLS};
if (!fnLoadSymbols(nativeFenceSymbols)) {
NS_ERROR(
"EGL supports ANDROID_native_fence_sync without exposing its "
"functions!");
MarkExtensionUnsupported(ANDROID_native_fence_sync);
}
{
const SymLoadStruct symbols[] = {SYMBOL(DupNativeFenceFDANDROID),
END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(ANDROID_get_native_client_buffer)) {
const SymLoadStruct nativeClientBufferSymbols[] = {
SYMBOL(GetNativeClientBufferANDROID), END_OF_SYMBOLS};
if (!fnLoadSymbols(nativeClientBufferSymbols)) {
NS_ERROR(
"EGL supports ANDROID_get_native_client_buffer without exposing its "
"functions!");
MarkExtensionUnsupported(ANDROID_get_native_client_buffer);
}
{
const SymLoadStruct symbols[] = {SYMBOL(CreateStreamKHR),
SYMBOL(DestroyStreamKHR),
SYMBOL(QueryStreamKHR), END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(KHR_stream)) {
const SymLoadStruct streamSymbols[] = {
SYMBOL(CreateStreamKHR), SYMBOL(DestroyStreamKHR),
SYMBOL(QueryStreamKHR), END_OF_SYMBOLS};
if (!fnLoadSymbols(streamSymbols)) {
NS_ERROR("EGL supports KHR_stream without exposing its functions!");
MarkExtensionUnsupported(KHR_stream);
}
{
const SymLoadStruct symbols[] = {SYMBOL(StreamConsumerGLTextureExternalKHR),
SYMBOL(StreamConsumerAcquireKHR),
SYMBOL(StreamConsumerReleaseKHR),
END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(KHR_stream_consumer_gltexture)) {
const SymLoadStruct streamConsumerSymbols[] = {
SYMBOL(StreamConsumerGLTextureExternalKHR),
SYMBOL(StreamConsumerAcquireKHR), SYMBOL(StreamConsumerReleaseKHR),
END_OF_SYMBOLS};
if (!fnLoadSymbols(streamConsumerSymbols)) {
NS_ERROR(
"EGL supports KHR_stream_consumer_gltexture without exposing its "
"functions!");
MarkExtensionUnsupported(KHR_stream_consumer_gltexture);
}
{
const SymLoadStruct symbols[] = {SYMBOL(QueryDisplayAttribEXT),
SYMBOL(QueryDeviceAttribEXT),
END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(EXT_device_query)) {
const SymLoadStruct queryDisplaySymbols[] = {SYMBOL(QueryDisplayAttribEXT),
SYMBOL(QueryDeviceAttribEXT),
END_OF_SYMBOLS};
if (!fnLoadSymbols(queryDisplaySymbols)) {
NS_ERROR("EGL supports EXT_device_query without exposing its functions!");
MarkExtensionUnsupported(EXT_device_query);
}
}
if (IsExtensionSupported(NV_stream_consumer_gltexture_yuv)) {
const SymLoadStruct nvStreamSymbols[] = {
{
const SymLoadStruct symbols[] = {
SYMBOL(StreamConsumerGLTextureExternalAttribsNV), END_OF_SYMBOLS};
if (!fnLoadSymbols(nvStreamSymbols)) {
NS_ERROR(
"EGL supports NV_stream_consumer_gltexture_yuv without exposing its "
"functions!");
MarkExtensionUnsupported(NV_stream_consumer_gltexture_yuv);
}
(void)fnLoadSymbols(symbols);
}
if (IsExtensionSupported(ANGLE_stream_producer_d3d_texture)) {
const SymLoadStruct nvStreamSymbols[] = {
{
const SymLoadStruct symbols[] = {
SYMBOL(CreateStreamProducerD3DTextureANGLE),
SYMBOL(StreamPostD3DTextureANGLE), END_OF_SYMBOLS};
if (!fnLoadSymbols(nvStreamSymbols)) {
NS_ERROR(
"EGL supports ANGLE_stream_producer_d3d_texture without exposing its "
"functions!");
MarkExtensionUnsupported(ANGLE_stream_producer_d3d_texture);
(void)fnLoadSymbols(symbols);
}
{
const SymLoadStruct symbols[] = {
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
{{"eglSwapBuffersWithDamageEXT"}}},
END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
{
const SymLoadStruct symbols[] = {
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
{{"eglSwapBuffersWithDamageKHR"}}},
END_OF_SYMBOLS};
(void)fnLoadSymbols(symbols);
}
return true;
}
// -
template <size_t N>
static void MarkExtensions(const char* rawExtString, bool shouldDumpExts,
const char* extType, const char* const (&names)[N],
std::bitset<N>* const out) {
MOZ_ASSERT(rawExtString);
const nsDependentCString extString(rawExtString);
std::vector<nsCString> extList;
SplitByChar(extString, ' ', &extList);
if (shouldDumpExts) {
printf_stderr("%u EGL %s extensions: (*: recognized)\n",
(uint32_t)extList.size(), extType);
}
MarkBitfieldByStrings(extList, shouldDumpExts, names, out);
}
// -
// static
std::shared_ptr<EglDisplay> EglDisplay::Create(GLLibraryEGL& lib,
const EGLDisplay display,
const bool isWarp) {
// Retrieve the EglDisplay if it already exists
{
const auto itr = lib.mActiveDisplays.find(display);
if (itr != lib.mActiveDisplays.end()) {
const auto ret = itr->second.lock();
if (ret) {
return ret;
}
}
}
if (IsExtensionSupported(KHR_surfaceless_context)) {
const auto vendor = fQueryString(mEGLDisplay, LOCAL_EGL_VENDOR);
if (!lib.fInitialize(display, nullptr, nullptr)) {
return nullptr;
}
const auto ret =
std::make_shared<EglDisplay>(PrivateUseOnly{}, lib, display, isWarp);
lib.mActiveDisplays.insert({display, ret});
return ret;
}
EglDisplay::EglDisplay(const PrivateUseOnly&, GLLibraryEGL& lib,
const EGLDisplay disp, const bool isWarp)
: mLib(&lib), mDisplay(disp), mIsWARP(isWarp) {
const bool shouldDumpExts = GLContext::ShouldDumpExts();
auto rawExtString =
(const char*)mLib->fQueryString(mDisplay, LOCAL_EGL_EXTENSIONS);
if (!rawExtString) {
NS_WARNING("Failed to query EGL display extensions!.");
rawExtString = "";
}
MarkExtensions(rawExtString, shouldDumpExts, "display", sEGLExtensionNames,
&mAvailableExtensions);
// -
if (!HasKHRImageBase()) {
MarkExtensionUnsupported(EGLExtension::KHR_image_pixmap);
}
if (IsExtensionSupported(EGLExtension::KHR_surfaceless_context)) {
const auto vendor =
(const char*)mLib->fQueryString(mDisplay, LOCAL_EGL_VENDOR);
// Bug 1464610: Mali T720 (Amazon Fire 8 HD) claims to support this
// extension, but if you actually eglMakeCurrent() with EGL_NO_SURFACE, it
// fails to render anything when a real surface is provided later on. We
// only have the EGL vendor available here, so just avoid using this
// extension on all Mali devices.
if (strcmp((const char*)vendor, "ARM") == 0) {
MarkExtensionUnsupported(KHR_surfaceless_context);
if (strcmp(vendor, "ARM") == 0) {
MarkExtensionUnsupported(EGLExtension::KHR_surfaceless_context);
}
}
if (IsExtensionSupported(EXT_swap_buffers_with_damage)) {
const SymLoadStruct symbols[] = {
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
{{"eglSwapBuffersWithDamageEXT"}}},
END_OF_SYMBOLS};
if (!fnLoadSymbols(symbols)) {
NS_ERROR(
"EGL supports EXT_swap_buffers_with_damage without exposing its "
"functions!");
MarkExtensionUnsupported(EXT_swap_buffers_with_damage);
}
}
if (IsExtensionSupported(KHR_swap_buffers_with_damage)) {
const SymLoadStruct symbols[] = {
{(PRFuncPtr*)&mSymbols.fSwapBuffersWithDamage,
{{"eglSwapBuffersWithDamageKHR"}}},
END_OF_SYMBOLS};
if (!fnLoadSymbols(symbols)) {
NS_ERROR(
"EGL supports KHR_swap_buffers_with_damage without exposing its "
"functions!");
MarkExtensionUnsupported(KHR_swap_buffers_with_damage);
}
}
mInitialized = true;
reporter.SetSuccessful();
return true;
}
#undef SYMBOL
#undef END_OF_SYMBOLS
void GLLibraryEGL::Shutdown() {
if (this != sEGLLibrary) {
return;
}
if (mEGLDisplay) {
fTerminate(mEGLDisplay);
mEGLDisplay = EGL_NO_DISPLAY;
}
sEGLLibrary = nullptr;
mSymbols = {};
EglDisplay::~EglDisplay() {
fTerminate();
mLib->mActiveDisplays.erase(mDisplay);
}
bool GLLibraryEGL::IsAlive() const {
return mSymbols.fGetCurrentContext != nullptr;
// -
std::shared_ptr<EglDisplay> GLLibraryEGL::DefaultDisplay(
nsACString* const out_failureId) {
auto ret = mDefaultDisplay.lock();
if (ret) return ret;
ret = CreateDisplay(false, out_failureId);
mDefaultDisplay = ret;
return ret;
}
EGLDisplay GLLibraryEGL::CreateDisplay(bool forceAccel,
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
nsACString* const out_failureId) {
MOZ_ASSERT(!mInitialized);
std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
const bool forceAccel, nsACString* const out_failureId) {
const nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
EGLDisplay chosenDisplay = nullptr;
std::shared_ptr<EglDisplay> ret;
if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
if (IsExtensionSupported(EGLLibExtension::ANGLE_platform_angle_d3d)) {
nsCString accelAngleFailureId;
bool accelAngleSupport =
IsAccelAngleSupported(gfxInfo, &accelAngleFailureId);
@ -795,11 +721,11 @@ EGLDisplay GLLibraryEGL::CreateDisplay(bool forceAccel,
// Hardware accelerated ANGLE path (supported or force accel)
if (shouldTryAccel) {
chosenDisplay = GetAndInitDisplayForAccelANGLE(*this, out_failureId);
ret = GetAndInitDisplayForAccelANGLE(*this, out_failureId);
}
// Report the acceleration status to telemetry
if (!chosenDisplay) {
if (!ret) {
if (accelAngleFailureId.IsEmpty()) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_ACCL_FAILURE_ID,
"FEATURE_FAILURE_ACCL_ANGLE_UNKNOWN"_ns);
@ -813,16 +739,15 @@ EGLDisplay GLLibraryEGL::CreateDisplay(bool forceAccel,
}
// Fallback to a WARP display if ANGLE fails, or if WARP is forced
if (!chosenDisplay && shouldTryWARP) {
chosenDisplay = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY);
if (!chosenDisplay) {
if (!ret && shouldTryWARP) {
ret = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY);
if (!ret) {
if (out_failureId->IsEmpty()) {
*out_failureId = "FEATURE_FAILURE_WARP_FALLBACK"_ns;
}
NS_ERROR("Fallback WARP context failed to initialize.");
return nullptr;
}
mIsWARP = true;
}
} else {
void* nativeDisplay = EGL_DEFAULT_DISPLAY;
@ -837,38 +762,21 @@ EGLDisplay GLLibraryEGL::CreateDisplay(bool forceAccel,
}
}
#endif
chosenDisplay = GetAndInitDisplay(*this, nativeDisplay);
ret = GetAndInitDisplay(*this, nativeDisplay);
}
if (!chosenDisplay) {
if (!ret) {
if (out_failureId->IsEmpty()) {
*out_failureId = "FEATURE_FAILURE_NO_DISPLAY"_ns;
}
NS_WARNING("Failed to initialize a display.");
return nullptr;
}
return chosenDisplay;
return ret;
}
template <size_t N>
static void MarkExtensions(const char* rawExtString, bool shouldDumpExts,
const char* extType, std::bitset<N>* const out) {
MOZ_ASSERT(rawExtString);
const nsDependentCString extString(rawExtString);
std::vector<nsCString> extList;
SplitByChar(extString, ' ', &extList);
if (shouldDumpExts) {
printf_stderr("%u EGL %s extensions: (*: recognized)\n",
(uint32_t)extList.size(), extType);
}
MarkBitfieldByStrings(extList, shouldDumpExts, sEGLExtensionNames, out);
}
void GLLibraryEGL::InitClientExtensions() {
void GLLibraryEGL::InitLibExtensions() {
const bool shouldDumpExts = GLContext::ShouldDumpExts();
const char* rawExtString = nullptr;
@ -883,42 +791,26 @@ void GLLibraryEGL::InitClientExtensions() {
if (!rawExtString) {
if (shouldDumpExts) {
printf_stderr("No EGL client extensions.\n");
printf_stderr("No EGL lib extensions.\n");
}
return;
}
MarkExtensions(rawExtString, shouldDumpExts, "client", &mAvailableExtensions);
}
void GLLibraryEGL::InitDisplayExtensions() {
MOZ_ASSERT(mEGLDisplay);
const bool shouldDumpExts = GLContext::ShouldDumpExts();
const auto rawExtString =
(const char*)fQueryString(mEGLDisplay, LOCAL_EGL_EXTENSIONS);
if (!rawExtString) {
NS_WARNING("Failed to query EGL display extensions!.");
return;
}
MarkExtensions(rawExtString, shouldDumpExts, "display",
MarkExtensions(rawExtString, shouldDumpExts, "lib", sEGLLibraryExtensionNames,
&mAvailableExtensions);
}
void GLLibraryEGL::DumpEGLConfig(EGLConfig cfg) {
int attrval;
int err;
#define ATTR(_x) \
do { \
fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
if ((err = fGetError()) != 0x3000) { \
printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
} else { \
printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
} \
void EglDisplay::DumpEGLConfig(EGLConfig cfg) const {
#define ATTR(_x) \
do { \
int attrval = 0; \
mLib->fGetConfigAttrib(mDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
const auto err = mLib->fGetError(); \
if (err != 0x3000) { \
printf_stderr(" %s: ERROR (0x%04x)\n", #_x, err); \
} else { \
printf_stderr(" %s: %d (0x%04x)\n", #_x, attrval, attrval); \
} \
} while (0)
printf_stderr("EGL Config: %d [%p]\n", (int)(intptr_t)cfg, cfg);
@ -960,18 +852,16 @@ void GLLibraryEGL::DumpEGLConfig(EGLConfig cfg) {
#undef ATTR
}
void GLLibraryEGL::DumpEGLConfigs() {
void EglDisplay::DumpEGLConfigs() const {
int nc = 0;
fGetConfigs(mEGLDisplay, nullptr, 0, &nc);
EGLConfig* ec = new EGLConfig[nc];
fGetConfigs(mEGLDisplay, ec, nc, &nc);
mLib->fGetConfigs(mDisplay, nullptr, 0, &nc);
std::vector<EGLConfig> ec(nc);
mLib->fGetConfigs(mDisplay, ec.data(), ec.size(), &nc);
for (int i = 0; i < nc; ++i) {
printf_stderr("========= EGL Config %d ========\n", i);
DumpEGLConfig(ec[i]);
}
delete[] ec;
}
static bool ShouldTrace() {

View File

@ -10,12 +10,15 @@
#endif
#include "GLLibraryLoader.h"
#include "mozilla/EnumTypeTraits.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ThreadLocal.h"
#include "GeckoProfiler.h"
#include <bitset>
#include <memory>
#include <unordered_map>
#include <vector>
#if defined(MOZ_X11)
@ -24,6 +27,8 @@
# define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
#endif
struct ID3D11Device;
extern "C" {
struct AHardwareBuffer;
}
@ -51,68 +56,101 @@ PRLibrary* LoadApitraceLibrary();
void BeforeEGLCall(const char* funcName);
void AfterEGLCall(const char* funcName);
class EglDisplay;
/**
* Known GL extensions that can be queried by
* IsExtensionSupported. The results of this are cached, and as
* such it's safe to use this even in performance critical code.
* If you add to this array, remember to add to the string names
* in GLLibraryEGL.cpp.
*/
enum class EGLLibExtension {
ANDROID_get_native_client_buffer,
ANGLE_device_creation,
ANGLE_device_creation_d3d11,
ANGLE_platform_angle,
ANGLE_platform_angle_d3d,
Max
};
/**
* Known GL extensions that can be queried by
* IsExtensionSupported. The results of this are cached, and as
* such it's safe to use this even in performance critical code.
* If you add to this array, remember to add to the string names
* in GLLibraryEGL.cpp.
*/
enum class EGLExtension {
KHR_image_base,
KHR_image_pixmap,
KHR_gl_texture_2D_image,
ANGLE_surface_d3d_texture_2d_share_handle,
EXT_create_context_robustness,
KHR_image,
KHR_fence_sync,
ANDROID_native_fence_sync,
EGL_ANDROID_image_crop,
ANGLE_d3d_share_handle_client_buffer,
KHR_create_context,
KHR_stream,
KHR_stream_consumer_gltexture,
EXT_device_query,
NV_stream_consumer_gltexture_yuv,
ANGLE_stream_producer_d3d_texture,
KHR_surfaceless_context,
KHR_create_context_no_error,
MOZ_create_context_provoking_vertex_dont_care,
EXT_swap_buffers_with_damage,
KHR_swap_buffers_with_damage,
EXT_buffer_age,
Max
};
// -
class GLLibraryEGL final {
protected:
~GLLibraryEGL() = default;
friend class EglDisplay;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL)
void InitClientExtensions();
void InitDisplayExtensions();
/**
* Known GL extensions that can be queried by
* IsExtensionSupported. The results of this are cached, and as
* such it's safe to use this even in performance critical code.
* If you add to this array, remember to add to the string names
* in GLLibraryEGL.cpp.
*/
enum EGLExtensions {
KHR_image_base,
KHR_image_pixmap,
KHR_gl_texture_2D_image,
KHR_lock_surface,
ANGLE_surface_d3d_texture_2d_share_handle,
EXT_create_context_robustness,
KHR_image,
KHR_fence_sync,
ANDROID_native_fence_sync,
EGL_ANDROID_image_crop,
ANDROID_get_native_client_buffer,
ANGLE_platform_angle,
ANGLE_platform_angle_d3d,
ANGLE_d3d_share_handle_client_buffer,
KHR_create_context,
KHR_stream,
KHR_stream_consumer_gltexture,
EXT_device_query,
NV_stream_consumer_gltexture_yuv,
ANGLE_stream_producer_d3d_texture,
ANGLE_device_creation,
ANGLE_device_creation_d3d11,
KHR_surfaceless_context,
KHR_create_context_no_error,
MOZ_create_context_provoking_vertex_dont_care,
EXT_swap_buffers_with_damage,
KHR_swap_buffers_with_damage,
EXT_buffer_age,
Extensions_Max
};
bool IsExtensionSupported(EGLExtensions aKnownExtension) const {
return mAvailableExtensions[aKnownExtension];
}
void MarkExtensionUnsupported(EGLExtensions aKnownExtension) {
mAvailableExtensions[aKnownExtension] = false;
}
protected:
std::bitset<Extensions_Max> mAvailableExtensions;
private:
PRLibrary* mEGLLibrary = nullptr;
PRLibrary* mGLLibrary = nullptr;
bool mIsANGLE = false;
std::bitset<UnderlyingValue(EGLLibExtension::Max)> mAvailableExtensions;
std::weak_ptr<EglDisplay> mDefaultDisplay;
std::unordered_map<EGLDisplay, std::weak_ptr<EglDisplay>> mActiveDisplays;
public:
////
static RefPtr<GLLibraryEGL> Create(nsACString* const out_failureId);
private:
~GLLibraryEGL() = default;
bool Init(nsACString* const out_failureId);
void InitLibExtensions();
public:
Maybe<SymbolLoader> GetSymbolLoader() const;
std::shared_ptr<EglDisplay> CreateDisplay(bool forceAccel,
nsACString* const out_failureId);
std::shared_ptr<EglDisplay> CreateDisplay(ID3D11Device*);
std::shared_ptr<EglDisplay> DefaultDisplay(nsACString* const out_failureId);
bool IsExtensionSupported(EGLLibExtension aKnownExtension) const {
return mAvailableExtensions[UnderlyingValue(aKnownExtension)];
}
void MarkExtensionUnsupported(EGLLibExtension aKnownExtension) {
mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false;
}
bool IsANGLE() const { return mIsANGLE; }
// -
// PFN wrappers
#ifdef MOZ_WIDGET_ANDROID
# define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
@ -140,293 +178,276 @@ class GLLibraryEGL final {
# define AFTER_CALL
#endif
#define WRAP(X) \
{ \
PROFILE_CALL \
BEFORE_CALL \
const auto ret = mSymbols.X; \
AFTER_CALL \
return ret; \
#define WRAP(X) \
PROFILE_CALL \
BEFORE_CALL \
const auto ret = mSymbols.X; \
AFTER_CALL \
return ret
public:
EGLDisplay fGetDisplay(void* display_id) const {
WRAP(fGetDisplay(display_id));
}
#define VOID_WRAP(X) \
{ \
PROFILE_CALL \
BEFORE_CALL \
mSymbols.X; \
AFTER_CALL \
EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display,
const EGLint* attrib_list) const {
WRAP(fGetPlatformDisplayEXT(platform, native_display, attrib_list));
}
EGLDisplay fGetDisplay(void* display_id) const WRAP(fGetDisplay(display_id))
EGLSurface fGetCurrentSurface(EGLint id) const {
WRAP(fGetCurrentSurface(id));
}
EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display,
const EGLint* attrib_list) const
WRAP(fGetPlatformDisplayEXT(platform, native_display, attrib_list))
EGLContext fGetCurrentContext() const { WRAP(fGetCurrentContext()); }
EGLBoolean fTerminate(EGLDisplay display) const
WRAP(fTerminate(display))
EGLBoolean fBindAPI(EGLenum api) const { WRAP(fBindAPI(api)); }
EGLSurface fGetCurrentSurface(EGLint id) const
WRAP(fGetCurrentSurface(id))
EGLint fGetError() const { WRAP(fGetError()); }
EGLContext fGetCurrentContext() const WRAP(fGetCurrentContext())
EGLBoolean fWaitNative(EGLint engine) const { WRAP(fWaitNative(engine)); }
EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw,
EGLSurface read, EGLContext ctx) const
WRAP(fMakeCurrent(dpy, draw, read, ctx))
EGLCastToRelevantPtr fGetProcAddress(const char* procname) const {
WRAP(fGetProcAddress(procname));
}
EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const
WRAP(fDestroyContext(dpy, ctx))
// ANGLE_device_creation
EGLDeviceEXT fCreateDeviceANGLE(EGLint device_type, void* native_device,
const EGLAttrib* attrib_list) const {
WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list));
}
EGLContext
fCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context,
const EGLint* attrib_list) const
WRAP(fCreateContext(dpy, config, share_context, attrib_list))
EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device) {
WRAP(fReleaseDeviceANGLE(device));
}
EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const
WRAP(fDestroySurface(dpy, surface))
// ANDROID_get_native_client_buffer
EGLClientBuffer fGetNativeClientBufferANDROID(
const struct AHardwareBuffer* buffer) {
WRAP(fGetNativeClientBufferANDROID(buffer));
}
EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLNativeWindowType win,
const EGLint* attrib_list) const
WRAP(fCreateWindowSurface(dpy, config, win, attrib_list))
private:
EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); }
EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
const EGLint* attrib_list) const
WRAP(fCreatePbufferSurface(dpy, config, attrib_list))
EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
EGLContext ctx) const {
WRAP(fMakeCurrent(dpy, draw, read, ctx));
}
EGLSurface
fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer, EGLConfig config,
const EGLint* attrib_list) const
WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
attrib_list))
EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const {
WRAP(fDestroyContext(dpy, ctx));
}
EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
EGLNativePixmapType pixmap,
const EGLint* attrib_list) const
WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list))
EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config,
EGLContext share_context,
const EGLint* attrib_list) const {
WRAP(fCreateContext(dpy, config, share_context, attrib_list));
}
EGLBoolean fBindAPI(EGLenum api) const WRAP(fBindAPI(api))
EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const {
WRAP(fDestroySurface(dpy, surface));
}
EGLBoolean
fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const
WRAP(fInitialize(dpy, major, minor))
public:
EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLNativeWindowType win,
const EGLint* attrib_list) const {
WRAP(fCreateWindowSurface(dpy, config, win, attrib_list));
}
EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list,
EGLConfig* configs, EGLint config_size,
EGLint* num_config) const
WRAP(fChooseConfig(dpy, attrib_list, configs, config_size, num_config))
private:
EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
const EGLint* attrib_list) const {
WRAP(fCreatePbufferSurface(dpy, config, attrib_list));
}
EGLint fGetError() const WRAP(fGetError())
EGLSurface fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer,
EGLConfig config,
const EGLint* attrib_list) const {
WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
attrib_list));
}
EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
EGLint attribute, EGLint* value) const
WRAP(fGetConfigAttrib(dpy, config, attribute, value))
EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
EGLNativePixmapType pixmap,
const EGLint* attrib_list) const {
WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list));
}
EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs,
EGLint config_size, EGLint* num_config) const
WRAP(fGetConfigs(dpy, configs, config_size, num_config))
EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const {
WRAP(fInitialize(dpy, major, minor));
}
EGLBoolean fWaitNative(EGLint engine) const WRAP(fWaitNative(engine))
EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list,
EGLConfig* configs, EGLint config_size,
EGLint* num_config) const {
WRAP(fChooseConfig(dpy, attrib_list, configs, config_size, num_config));
}
EGLCastToRelevantPtr fGetProcAddress(const char* procname) const
WRAP(fGetProcAddress(procname))
EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
EGLint attribute, EGLint* value) const {
WRAP(fGetConfigAttrib(dpy, config, attribute, value));
}
EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const
WRAP(fSwapBuffers(dpy, surface))
EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size,
EGLint* num_config) const {
WRAP(fGetConfigs(dpy, configs, config_size, num_config));
}
EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface,
EGLNativePixmapType target) const
WRAP(fCopyBuffers(dpy, surface, target))
EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const {
WRAP(fSwapBuffers(dpy, surface));
}
const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const
WRAP(fQueryString(dpy, name))
EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface,
EGLNativePixmapType target) const {
WRAP(fCopyBuffers(dpy, surface, target));
}
EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx,
EGLint attribute, EGLint* value) const
WRAP(fQueryContext(dpy, ctx, attribute, value))
public:
const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const {
WRAP(fQueryString(dpy, name));
}
EGLBoolean
fBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const
WRAP(fBindTexImage(dpy, surface, buffer))
private:
EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
EGLint* value) const {
WRAP(fQueryContext(dpy, ctx, attribute, value));
}
EGLBoolean
fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const
WRAP(fReleaseTexImage(dpy, surface, buffer))
EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface,
EGLint buffer) const {
WRAP(fBindTexImage(dpy, surface, buffer));
}
EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const
WRAP(fSwapInterval(dpy, interval))
EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface,
EGLint buffer) const {
WRAP(fReleaseTexImage(dpy, surface, buffer));
}
EGLImage
fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer, const EGLint* attrib_list) const
WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list))
EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const {
WRAP(fSwapInterval(dpy, interval));
}
EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const
WRAP(fDestroyImageKHR(dpy, image))
EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer,
const EGLint* attrib_list) const {
WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list));
}
EGLBoolean fLockSurface(EGLDisplay dpy, EGLSurface surface,
const EGLint* attrib_list) const
WRAP(fLockSurfaceKHR(dpy, surface, attrib_list))
EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const {
WRAP(fDestroyImageKHR(dpy, image));
}
EGLBoolean fUnlockSurface(EGLDisplay dpy, EGLSurface surface) const
WRAP(fUnlockSurfaceKHR(dpy, surface))
EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute,
EGLint* value) const {
WRAP(fQuerySurface(dpy, surface, attribute, value));
}
EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface,
EGLint attribute, EGLint* value) const
WRAP(fQuerySurface(dpy, surface, attribute, value))
EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface,
EGLint attribute, void** value) const {
WRAP(fQuerySurfacePointerANGLE(dpy, surface, attribute, value));
}
EGLBoolean
fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface,
EGLint attribute, void** value) const
WRAP(fQuerySurfacePointerANGLE(dpy, surface, attribute, value))
EGLSync fCreateSync(EGLDisplay dpy, EGLenum type,
const EGLint* attrib_list) const {
WRAP(fCreateSyncKHR(dpy, type, attrib_list));
}
EGLSync
fCreateSync(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) const
WRAP(fCreateSyncKHR(dpy, type, attrib_list))
EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const {
WRAP(fDestroySyncKHR(dpy, sync));
}
EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const
WRAP(fDestroySyncKHR(dpy, sync))
EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags,
EGLTime timeout) const {
WRAP(fClientWaitSyncKHR(dpy, sync, flags, timeout));
}
EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags,
EGLTime timeout) const
WRAP(fClientWaitSyncKHR(dpy, sync, flags, timeout))
EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute,
EGLint* value) const {
WRAP(fGetSyncAttribKHR(dpy, sync, attribute, value));
}
EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync,
EGLint attribute, EGLint* value) const
WRAP(fGetSyncAttribKHR(dpy, sync, attribute, value))
EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const {
WRAP(fDupNativeFenceFDANDROID(dpy, sync));
}
EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const
WRAP(fDupNativeFenceFDANDROID(dpy, sync))
// KHR_stream
EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy,
const EGLint* attrib_list) const {
WRAP(fCreateStreamKHR(dpy, attrib_list));
}
// KHR_stream
EGLStreamKHR
fCreateStreamKHR(EGLDisplay dpy, const EGLint* attrib_list) const
WRAP(fCreateStreamKHR(dpy, attrib_list))
EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const {
WRAP(fDestroyStreamKHR(dpy, stream));
}
EGLBoolean
fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP(fDestroyStreamKHR(dpy, stream))
EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
EGLenum attribute, EGLint* value) const {
WRAP(fQueryStreamKHR(dpy, stream, attribute, value));
}
EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream,
EGLenum attribute, EGLint* value) const
WRAP(fQueryStreamKHR(dpy, stream, attribute, value))
// KHR_stream_consumer_gltexture
EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
EGLStreamKHR stream) const {
WRAP(fStreamConsumerGLTextureExternalKHR(dpy, stream));
}
// KHR_stream_consumer_gltexture
EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,
EGLStreamKHR stream) const
WRAP(fStreamConsumerGLTextureExternalKHR(dpy, stream))
EGLBoolean fStreamConsumerAcquireKHR(EGLDisplay dpy,
EGLStreamKHR stream) const {
WRAP(fStreamConsumerAcquireKHR(dpy, stream));
}
EGLBoolean
fStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP(fStreamConsumerAcquireKHR(dpy, stream))
EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy,
EGLStreamKHR stream) const {
WRAP(fStreamConsumerReleaseKHR(dpy, stream));
}
EGLBoolean
fStreamConsumerReleaseKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP(fStreamConsumerReleaseKHR(dpy, stream))
// EXT_device_query
EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute,
EGLAttrib* value) const {
WRAP(fQueryDisplayAttribEXT(dpy, attribute, value));
}
// EXT_device_query
EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute,
EGLAttrib* value) const
WRAP(fQueryDisplayAttribEXT(dpy, attribute, value))
public:
EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute,
EGLAttrib* value) const {
WRAP(fQueryDeviceAttribEXT(device, attribute, value));
}
EGLBoolean
fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute,
EGLAttrib* value) const
WRAP(fQueryDeviceAttribEXT(device, attribute, value))
private:
// NV_stream_consumer_gltexture_yuv
EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
WRAP(fStreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list));
}
// NV_stream_consumer_gltexture_yuv
EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
EGLDisplay dpy, EGLStreamKHR stream,
const EGLAttrib* attrib_list) const
WRAP(fStreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list))
// ANGLE_stream_producer_d3d_texture
EGLBoolean fCreateStreamProducerD3DTextureANGLE(
EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
WRAP(fCreateStreamProducerD3DTextureANGLE(dpy, stream, attrib_list));
}
// ANGLE_stream_producer_d3d_texture
EGLBoolean
fCreateStreamProducerD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream,
const EGLAttrib* attrib_list) const
WRAP(fCreateStreamProducerD3DTextureANGLE(dpy, stream, attrib_list))
EGLBoolean fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream,
void* texture,
const EGLAttrib* attrib_list) const {
WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list));
}
EGLBoolean
fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream,
void* texture,
const EGLAttrib* attrib_list) const
WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list))
// EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
EGLBoolean fSwapBuffersWithDamage(EGLDisplay dpy, EGLSurface surface,
const EGLint* rects, EGLint n_rects) {
WRAP(fSwapBuffersWithDamage(dpy, surface, rects, n_rects));
}
// ANGLE_device_creation
EGLDeviceEXT fCreateDeviceANGLE(EGLint device_type, void* native_device,
const EGLAttrib* attrib_list) const
WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list))
EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device)
WRAP(fReleaseDeviceANGLE(device))
// EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
EGLBoolean fSwapBuffersWithDamage(EGLDisplay dpy, EGLSurface surface,
const EGLint* rects, EGLint n_rects)
WRAP(fSwapBuffersWithDamage(dpy, surface, rects, n_rects))
// ANDROID_get_native_client_buffer
EGLClientBuffer
fGetNativeClientBufferANDROID(const struct AHardwareBuffer* buffer)
WRAP(fGetNativeClientBufferANDROID(buffer))
#undef WRAP
#undef VOID_WRAP
#undef PROFILE_CALL
#undef BEFORE_CALL
#undef AFTER_CALL
#undef MOZ_FUNCTION_NAME
////
EGLDisplay Display() const {
MOZ_ASSERT(mInitialized);
return mEGLDisplay;
}
bool IsANGLE() const {
MOZ_ASSERT(mInitialized);
return mIsANGLE;
}
bool IsWARP() const {
MOZ_ASSERT(mInitialized);
return mIsWARP;
}
bool HasKHRImageBase() const {
return IsExtensionSupported(KHR_image) ||
IsExtensionSupported(KHR_image_base);
}
bool HasKHRImagePixmap() const {
return IsExtensionSupported(KHR_image) ||
IsExtensionSupported(KHR_image_pixmap);
}
bool HasKHRImageTexture2D() const {
return IsExtensionSupported(KHR_gl_texture_2D_image);
}
bool HasANGLESurfaceD3DTexture2DShareHandle() const {
return IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle);
}
bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
inline static GLLibraryEGL* Get() { return sEGLLibrary; }
static bool EnsureInitialized(bool forceAccel,
nsACString* const out_failureId);
void Shutdown();
bool IsAlive() const;
void DumpEGLConfig(EGLConfig cfg);
void DumpEGLConfigs();
Maybe<SymbolLoader> GetSymbolLoader() const;
////
private:
struct {
@ -489,11 +510,6 @@ class GLLibraryEGL final {
EGLClientBuffer buffer,
const EGLint* attrib_list);
EGLBoolean(GLAPIENTRY* fDestroyImageKHR)(EGLDisplay dpy, EGLImage image);
// New extension which allow us to lock texture and get raw image pointer
EGLBoolean(GLAPIENTRY* fLockSurfaceKHR)(EGLDisplay dpy, EGLSurface surface,
const EGLint* attrib_list);
EGLBoolean(GLAPIENTRY* fUnlockSurfaceKHR)(EGLDisplay dpy,
EGLSurface surface);
EGLBoolean(GLAPIENTRY* fQuerySurface)(EGLDisplay dpy, EGLSurface surface,
EGLint attribute, EGLint* value);
EGLBoolean(GLAPIENTRY* fQuerySurfacePointerANGLE)(EGLDisplay dpy,
@ -551,26 +567,252 @@ class GLLibraryEGL final {
EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)(
const struct AHardwareBuffer* buffer);
} mSymbols = {};
private:
bool DoEnsureInitialized();
bool DoEnsureInitialized(bool forceAccel, nsACString* const out_failureId);
EGLDisplay CreateDisplay(bool forceAccel, const nsCOMPtr<nsIGfxInfo>& gfxInfo,
nsACString* const out_failureId);
bool mInitialized = false;
PRLibrary* mEGLLibrary = nullptr;
mutable PRLibrary* mGLLibrary = nullptr;
EGLDisplay mEGLDisplay = EGL_NO_DISPLAY;
RefPtr<GLContext> mReadbackGL;
bool mIsANGLE = false;
bool mIsWARP = false;
static StaticMutex sMutex;
static StaticRefPtr<GLLibraryEGL> sEGLLibrary;
};
bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl);
class EglDisplay final {
public:
const RefPtr<GLLibraryEGL> mLib;
const EGLDisplay mDisplay;
const bool mIsWARP;
private:
std::bitset<UnderlyingValue(EGLExtension::Max)> mAvailableExtensions;
struct PrivateUseOnly final {};
public:
static std::shared_ptr<EglDisplay> Create(GLLibraryEGL&, EGLDisplay,
bool isWarp);
// Only `public` for make_shared.
EglDisplay(const PrivateUseOnly&, GLLibraryEGL&, EGLDisplay, bool isWarp);
public:
~EglDisplay();
bool IsExtensionSupported(EGLExtension aKnownExtension) const {
return mAvailableExtensions[UnderlyingValue(aKnownExtension)];
}
void MarkExtensionUnsupported(EGLExtension aKnownExtension) {
mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false;
}
void DumpEGLConfig(EGLConfig) const;
void DumpEGLConfigs() const;
void Shutdown();
// -
bool HasKHRImageBase() const {
return IsExtensionSupported(EGLExtension::KHR_image) ||
IsExtensionSupported(EGLExtension::KHR_image_base);
}
bool HasKHRImagePixmap() const {
return IsExtensionSupported(EGLExtension::KHR_image) ||
IsExtensionSupported(EGLExtension::KHR_image_pixmap);
}
// -
EGLBoolean fTerminate() { return mLib->fTerminate(mDisplay); }
EGLBoolean fMakeCurrent(EGLSurface draw, EGLSurface read,
EGLContext ctx) const {
return mLib->fMakeCurrent(mDisplay, draw, read, ctx);
}
EGLBoolean fDestroyContext(EGLContext ctx) const {
return mLib->fDestroyContext(mDisplay, ctx);
}
EGLContext fCreateContext(EGLConfig config, EGLContext share_context,
const EGLint* attrib_list) const {
return mLib->fCreateContext(mDisplay, config, share_context, attrib_list);
}
EGLBoolean fDestroySurface(EGLSurface surface) const {
return mLib->fDestroySurface(mDisplay, surface);
}
EGLSurface fCreateWindowSurface(EGLConfig config, EGLNativeWindowType win,
const EGLint* attrib_list) const {
return mLib->fCreateWindowSurface(mDisplay, config, win, attrib_list);
}
EGLSurface fCreatePbufferSurface(EGLConfig config,
const EGLint* attrib_list) const {
return mLib->fCreatePbufferSurface(mDisplay, config, attrib_list);
}
EGLSurface fCreatePbufferFromClientBuffer(EGLenum buftype,
EGLClientBuffer buffer,
EGLConfig config,
const EGLint* attrib_list) const {
return mLib->fCreatePbufferFromClientBuffer(mDisplay, buftype, buffer,
config, attrib_list);
}
EGLBoolean fChooseConfig(const EGLint* attrib_list, EGLConfig* configs,
EGLint config_size, EGLint* num_config) const {
return mLib->fChooseConfig(mDisplay, attrib_list, configs, config_size,
num_config);
}
EGLBoolean fGetConfigAttrib(EGLConfig config, EGLint attribute,
EGLint* value) const {
return mLib->fGetConfigAttrib(mDisplay, config, attribute, value);
}
EGLBoolean fGetConfigs(EGLConfig* configs, EGLint config_size,
EGLint* num_config) const {
return mLib->fGetConfigs(mDisplay, configs, config_size, num_config);
}
EGLBoolean fSwapBuffers(EGLSurface surface) const {
return mLib->fSwapBuffers(mDisplay, surface);
}
EGLBoolean fBindTexImage(EGLSurface surface, EGLint buffer) const {
return mLib->fBindTexImage(mDisplay, surface, buffer);
}
EGLBoolean fReleaseTexImage(EGLSurface surface, EGLint buffer) const {
return mLib->fReleaseTexImage(mDisplay, surface, buffer);
}
EGLBoolean fSwapInterval(EGLint interval) const {
return mLib->fSwapInterval(mDisplay, interval);
}
EGLImage fCreateImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer,
const EGLint* attribList) const {
MOZ_ASSERT(HasKHRImageBase());
return mLib->fCreateImage(mDisplay, ctx, target, buffer, attribList);
}
EGLBoolean fDestroyImage(EGLImage image) const {
MOZ_ASSERT(HasKHRImageBase());
return mLib->fDestroyImage(mDisplay, image);
}
EGLBoolean fQuerySurface(EGLSurface surface, EGLint attribute,
EGLint* value) const {
return mLib->fQuerySurface(mDisplay, surface, attribute, value);
}
EGLBoolean fQuerySurfacePointerANGLE(EGLSurface surface, EGLint attribute,
void** value) const {
MOZ_ASSERT(IsExtensionSupported(
EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle));
return mLib->fQuerySurfacePointerANGLE(mDisplay, surface, attribute, value);
}
EGLSync fCreateSync(EGLenum type, const EGLint* attrib_list) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
return mLib->fCreateSync(mDisplay, type, attrib_list);
}
EGLBoolean fDestroySync(EGLSync sync) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
return mLib->fDestroySync(mDisplay, sync);
}
EGLint fClientWaitSync(EGLSync sync, EGLint flags, EGLTime timeout) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
return mLib->fClientWaitSync(mDisplay, sync, flags, timeout);
}
EGLBoolean fGetSyncAttrib(EGLSync sync, EGLint attribute,
EGLint* value) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync));
return mLib->fGetSyncAttrib(mDisplay, sync, attribute, value);
}
EGLint fDupNativeFenceFDANDROID(EGLSync sync) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync));
return mLib->fDupNativeFenceFDANDROID(mDisplay, sync);
}
// EXT_device_query
EGLBoolean fQueryDisplayAttribEXT(EGLint attribute, EGLAttrib* value) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::EXT_device_query));
return mLib->fQueryDisplayAttribEXT(mDisplay, attribute, value);
}
// KHR_stream
EGLStreamKHR fCreateStreamKHR(const EGLint* attrib_list) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
return mLib->fCreateStreamKHR(mDisplay, attrib_list);
}
EGLBoolean fDestroyStreamKHR(EGLStreamKHR stream) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
return mLib->fDestroyStreamKHR(mDisplay, stream);
}
EGLBoolean fQueryStreamKHR(EGLStreamKHR stream, EGLenum attribute,
EGLint* value) const {
MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream));
return mLib->fQueryStreamKHR(mDisplay, stream, attribute, value);
}
// KHR_stream_consumer_gltexture
EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream) const {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
return mLib->fStreamConsumerGLTextureExternalKHR(mDisplay, stream);
}
EGLBoolean fStreamConsumerAcquireKHR(EGLStreamKHR stream) const {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
return mLib->fStreamConsumerAcquireKHR(mDisplay, stream);
}
EGLBoolean fStreamConsumerReleaseKHR(EGLStreamKHR stream) const {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
return mLib->fStreamConsumerReleaseKHR(mDisplay, stream);
}
// NV_stream_consumer_gltexture_yuv
EGLBoolean fStreamConsumerGLTextureExternalAttribsNV(
EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv));
return mLib->fStreamConsumerGLTextureExternalAttribsNV(mDisplay, stream,
attrib_list);
}
// ANGLE_stream_producer_d3d_texture
EGLBoolean fCreateStreamProducerD3DTextureANGLE(
EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
return mLib->fCreateStreamProducerD3DTextureANGLE(mDisplay, stream,
attrib_list);
}
EGLBoolean fStreamPostD3DTextureANGLE(EGLStreamKHR stream, void* texture,
const EGLAttrib* attrib_list) const {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
return mLib->fStreamPostD3DTextureANGLE(mDisplay, stream, texture,
attrib_list);
}
// EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
EGLBoolean fSwapBuffersWithDamage(EGLSurface surface, const EGLint* rects,
EGLint n_rects) {
MOZ_ASSERT(
IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage) ||
IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage));
return mLib->fSwapBuffersWithDamage(mDisplay, surface, rects, n_rects);
}
};
} /* namespace gl */
} /* namespace mozilla */

View File

@ -10,14 +10,13 @@
#include "GfxTexturesReporter.h"
#include "mozilla/StaticPrefs_gfx.h"
using namespace mozilla;
using namespace mozilla::gl;
NS_IMPL_ISUPPORTS(GfxTexturesReporter, nsIMemoryReporter)
Atomic<size_t> GfxTexturesReporter::sAmount(0);
Atomic<size_t> GfxTexturesReporter::sPeakAmount(0);
Atomic<size_t> GfxTexturesReporter::sTileWasteAmount(0);
mozilla::Atomic<size_t> GfxTexturesReporter::sAmount(0);
mozilla::Atomic<size_t> GfxTexturesReporter::sPeakAmount(0);
mozilla::Atomic<size_t> GfxTexturesReporter::sTileWasteAmount(0);
static std::string FormatBytes(size_t amount) {
std::stringstream stream;

View File

@ -137,10 +137,6 @@ class SharedSurface {
virtual bool NeedsIndirectReads() const { return false; }
virtual Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() = 0;
virtual bool ReadbackBySharedHandle(gfx::DataSourceSurface* out_surface) {
return false;
}
};
// -

View File

@ -15,17 +15,14 @@ namespace mozilla {
namespace gl {
// Returns `EGL_NO_SURFACE` (`0`) on error.
static EGLSurface CreatePBufferSurface(GLLibraryEGL* egl, EGLDisplay display,
EGLConfig config,
static EGLSurface CreatePBufferSurface(EglDisplay* egl, EGLConfig config,
const gfx::IntSize& size) {
const EGLint attribs[] = {LOCAL_EGL_WIDTH, size.width, LOCAL_EGL_HEIGHT,
size.height, LOCAL_EGL_NONE};
DebugOnly<EGLint> preCallErr = egl->fGetError();
MOZ_ASSERT(preCallErr == LOCAL_EGL_SUCCESS);
EGLSurface surface = egl->fCreatePbufferSurface(display, config, attribs);
EGLint err = egl->fGetError();
if (err != LOCAL_EGL_SUCCESS) {
EGLSurface surface = egl->fCreatePbufferSurface(config, attribs);
if (!surface) {
EGLint err = egl->mLib->fGetError();
gfxCriticalError() << "Failed to create Pbuffer surface error: "
<< gfx::hexa(err) << " Size : " << size;
return 0;
@ -41,27 +38,25 @@ SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc& desc) {
const auto& egl = gle->mEgl;
MOZ_ASSERT(egl);
MOZ_ASSERT(egl->IsExtensionSupported(
GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle));
EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle));
const auto& config = gle->mConfig;
MOZ_ASSERT(config);
EGLDisplay display = egl->Display();
EGLSurface pbuffer = CreatePBufferSurface(egl, display, config, desc.size);
EGLSurface pbuffer = CreatePBufferSurface(egl.get(), config, desc.size);
if (!pbuffer) return nullptr;
// Declare everything before 'goto's.
HANDLE shareHandle = nullptr;
bool ok = egl->fQuerySurfacePointerANGLE(
display, pbuffer, LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
&shareHandle);
pbuffer, LOCAL_EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, &shareHandle);
if (!ok) {
egl->fDestroySurface(egl->Display(), pbuffer);
egl->fDestroySurface(pbuffer);
return nullptr;
}
void* opaqueKeyedMutex = nullptr;
egl->fQuerySurfacePointerANGLE(
display, pbuffer, LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE, &opaqueKeyedMutex);
egl->fQuerySurfacePointerANGLE(pbuffer, LOCAL_EGL_DXGI_KEYED_MUTEX_ANGLE,
&opaqueKeyedMutex);
RefPtr<IDXGIKeyedMutex> keyedMutex =
static_cast<IDXGIKeyedMutex*>(opaqueKeyedMutex);
#ifdef DEBUG
@ -81,13 +76,10 @@ SharedSurface_ANGLEShareHandle::Create(const SharedSurfaceDesc& desc) {
shareHandle, keyedMutex));
}
EGLDisplay SharedSurface_ANGLEShareHandle::Display() const {
return mEGL->Display();
}
SharedSurface_ANGLEShareHandle::SharedSurface_ANGLEShareHandle(
const SharedSurfaceDesc& desc, GLLibraryEGL* egl, EGLSurface pbuffer,
HANDLE shareHandle, const RefPtr<IDXGIKeyedMutex>& keyedMutex)
const SharedSurfaceDesc& desc, const std::weak_ptr<EglDisplay>& egl,
EGLSurface pbuffer, HANDLE shareHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex)
: SharedSurface(desc, nullptr),
mEGL(egl),
mPBuffer(pbuffer),
@ -100,7 +92,10 @@ SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle() {
if (gl && GLContextEGL::Cast(gl)->GetEGLSurfaceOverride() == mPBuffer) {
GLContextEGL::Cast(gl)->SetEGLSurfaceOverride(EGL_NO_SURFACE);
}
mEGL->fDestroySurface(Display(), mPBuffer);
const auto egl = mEGL.lock();
if (egl) {
egl->fDestroySurface(mPBuffer);
}
}
void SharedSurface_ANGLEShareHandle::LockProdImpl() {
@ -228,72 +223,6 @@ class ScopedLockTexture final {
D3D11_MAPPED_SUBRESOURCE mSubresource;
};
bool SharedSurface_ANGLEShareHandle::ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) {
MOZ_ASSERT(out_surface);
RefPtr<ID3D11Device> device = gfx::DeviceManagerDx::Get()->GetContentDevice();
if (!device) {
return false;
}
RefPtr<ID3D11Texture2D> tex;
HRESULT hr = device->OpenSharedResource(
mShareHandle, __uuidof(ID3D11Texture2D),
(void**)(ID3D11Texture2D**)getter_AddRefs(tex));
if (FAILED(hr)) {
return false;
}
bool succeeded = false;
ScopedLockTexture scopedLock(tex, &succeeded);
if (!succeeded) {
return false;
}
const uint8_t* data =
reinterpret_cast<uint8_t*>(scopedLock.mSubresource.pData);
uint32_t srcStride = scopedLock.mSubresource.RowPitch;
gfx::DataSourceSurface::ScopedMap map(out_surface,
gfx::DataSourceSurface::WRITE);
if (!map.IsMapped()) {
return false;
}
if (map.GetStride() == srcStride) {
memcpy(map.GetData(), data,
out_surface->GetSize().height * map.GetStride());
} else {
const uint8_t bytesPerPixel = BytesPerPixel(out_surface->GetFormat());
for (int32_t i = 0; i < out_surface->GetSize().height; i++) {
memcpy(map.GetData() + i * map.GetStride(), data + i * srcStride,
bytesPerPixel * out_surface->GetSize().width);
}
}
DXGI_FORMAT srcFormat = scopedLock.mDesc.Format;
MOZ_ASSERT(srcFormat == DXGI_FORMAT_B8G8R8A8_UNORM ||
srcFormat == DXGI_FORMAT_B8G8R8X8_UNORM ||
srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM);
bool isSrcRGB = srcFormat == DXGI_FORMAT_R8G8B8A8_UNORM;
gfx::SurfaceFormat destFormat = out_surface->GetFormat();
MOZ_ASSERT(destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
destFormat == gfx::SurfaceFormat::R8G8B8A8 ||
destFormat == gfx::SurfaceFormat::B8G8R8X8 ||
destFormat == gfx::SurfaceFormat::B8G8R8A8);
bool isDestRGB = destFormat == gfx::SurfaceFormat::R8G8B8X8 ||
destFormat == gfx::SurfaceFormat::R8G8B8A8;
if (isSrcRGB != isDestRGB) {
SwapRAndBComponents(out_surface);
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Factory
@ -305,8 +234,10 @@ SurfaceFactory_ANGLEShareHandle::Create(GLContext& gl) {
const auto& gle = *GLContextEGL::Cast(&gl);
const auto& egl = gle.mEgl;
auto ext = GLLibraryEGL::ANGLE_surface_d3d_texture_2d_share_handle;
if (!egl->IsExtensionSupported(ext)) return nullptr;
if (!egl->IsExtensionSupported(
EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle)) {
return nullptr;
}
if (XRE_IsContentProcess()) {
gfxPlatform::GetPlatform()->EnsureDevicesInitialized();

View File

@ -7,6 +7,7 @@
#define SHARED_SURFACE_ANGLE_H_
#include <windows.h>
#include <memory>
#include "SharedSurface.h"
struct IDXGIKeyedMutex;
@ -16,11 +17,11 @@ namespace mozilla {
namespace gl {
class GLContext;
class GLLibraryEGL;
class EglDisplay;
class SharedSurface_ANGLEShareHandle final : public SharedSurface {
public:
GLLibraryEGL* const mEGL;
const std::weak_ptr<EglDisplay> mEGL;
const EGLSurface mPBuffer;
const HANDLE mShareHandle;
const RefPtr<IDXGIKeyedMutex> mKeyedMutex;
@ -29,12 +30,11 @@ class SharedSurface_ANGLEShareHandle final : public SharedSurface {
const SharedSurfaceDesc&);
private:
SharedSurface_ANGLEShareHandle(const SharedSurfaceDesc&, GLLibraryEGL* egl,
SharedSurface_ANGLEShareHandle(const SharedSurfaceDesc&,
const std::weak_ptr<EglDisplay>& egl,
EGLSurface pbuffer, HANDLE shareHandle,
const RefPtr<IDXGIKeyedMutex>& keyedMutex);
EGLDisplay Display() const;
public:
virtual ~SharedSurface_ANGLEShareHandle();
@ -47,9 +47,6 @@ class SharedSurface_ANGLEShareHandle final : public SharedSurface {
virtual void ProducerReadReleaseImpl() override;
Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
virtual bool ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) override;
};
class SurfaceFactory_ANGLEShareHandle final : public SurfaceFactory {

View File

@ -26,7 +26,7 @@ namespace gl {
static bool HasEglImageExtensions(const GLContextEGL& gl) {
const auto& egl = *(gl.mEgl);
return egl.HasKHRImageBase() &&
egl.IsExtensionSupported(GLLibraryEGL::KHR_gl_texture_2D_image) &&
egl.IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
(gl.IsExtensionSupported(GLContext::OES_EGL_image_external) ||
gl.IsExtensionSupported(GLContext::OES_EGL_image));
}
@ -57,8 +57,8 @@ UniquePtr<SharedSurface_EGLImage> SharedSurface_EGLImage::Create(
if (!fb) return nullptr;
const auto buffer = reinterpret_cast<EGLClientBuffer>(fb->ColorTex());
const auto image = egl.fCreateImage(egl.Display(), context,
LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
const auto image =
egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr);
if (!image) return nullptr;
return AsUnique(new SharedSurface_EGLImage(desc, std::move(fb), image));
@ -74,12 +74,12 @@ SharedSurface_EGLImage::SharedSurface_EGLImage(const SharedSurfaceDesc& desc,
SharedSurface_EGLImage::~SharedSurface_EGLImage() {
const auto& gle = GLContextEGL::Cast(mDesc.gl);
const auto& egl = gle->mEgl;
egl->fDestroyImage(egl->Display(), mImage);
egl->fDestroyImage(mImage);
if (mSync) {
// We can't call this unless we have the ext, but we will always have
// the ext if we have something to destroy.
egl->fDestroySync(egl->Display(), mSync);
egl->fDestroySync(mSync);
mSync = 0;
}
}
@ -91,15 +91,15 @@ void SharedSurface_EGLImage::ProducerReleaseImpl() {
MutexAutoLock lock(mMutex);
gl->MakeCurrent();
if (egl->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) &&
if (egl->IsExtensionSupported(EGLExtension::KHR_fence_sync) &&
gl->IsExtensionSupported(GLContext::OES_EGL_sync)) {
if (mSync) {
MOZ_RELEASE_ASSERT(false, "GFX: Non-recycleable should not Fence twice.");
MOZ_ALWAYS_TRUE(egl->fDestroySync(egl->Display(), mSync));
MOZ_ALWAYS_TRUE(egl->fDestroySync(mSync));
mSync = 0;
}
mSync = egl->fCreateSync(egl->Display(), LOCAL_EGL_SYNC_FENCE, nullptr);
mSync = egl->fCreateSync(LOCAL_EGL_SYNC_FENCE, nullptr);
if (mSync) {
gl->fFlush();
return;
@ -116,7 +116,7 @@ void SharedSurface_EGLImage::ProducerReadAcquireImpl() {
// Wait on the fence, because presumably we're going to want to read this
// surface
if (mSync) {
egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER);
egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
}
}
@ -125,15 +125,6 @@ Maybe<layers::SurfaceDescriptor> SharedSurface_EGLImage::ToSurfaceDescriptor() {
mDesc.size, true));
}
bool SharedSurface_EGLImage::ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) {
const auto& gle = GLContextEGL::Cast(mDesc.gl);
const auto& egl = gle->mEgl;
MOZ_ASSERT(out_surface);
MOZ_ASSERT(NS_IsMainThread());
return egl->ReadbackEGLImage(mImage, out_surface);
}
////////////////////////////////////////////////////////////////////////
#ifdef MOZ_WIDGET_ANDROID
@ -180,7 +171,9 @@ SharedSurface_SurfaceTexture::~SharedSurface_SurfaceTexture() {
// to the surface.
UnlockProd();
}
GLContextProviderEGL::DestroyEGLSurface(mEglSurface);
const auto& gle = GLContextEGL::Cast(mDesc.gl);
const auto& egl = gle->mEgl;
egl->fDestroySurface(mEglSurface);
java::SurfaceAllocator::DisposeSurface(mSurface);
}

View File

@ -51,9 +51,6 @@ class SharedSurface_EGLImage final : public SharedSurface {
virtual void ProducerReadReleaseImpl() override{};
Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
virtual bool ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) override;
};
class SurfaceFactory_EGLImage final : public SurfaceFactory {

View File

@ -65,38 +65,6 @@ SharedSurface_GLXDrawable::ToSurfaceDescriptor() {
return Some(layers::SurfaceDescriptorX11(mXlibSurface, sameProcess));
}
bool SharedSurface_GLXDrawable::ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) {
MOZ_ASSERT(out_surface);
RefPtr<gfx::DataSourceSurface> dataSurf =
new gfx::DataSourceSurfaceCairo(mXlibSurface->CairoSurface());
gfx::DataSourceSurface::ScopedMap mapSrc(dataSurf,
gfx::DataSourceSurface::READ);
if (!mapSrc.IsMapped()) {
return false;
}
gfx::DataSourceSurface::ScopedMap mapDest(out_surface,
gfx::DataSourceSurface::WRITE);
if (!mapDest.IsMapped()) {
return false;
}
if (mapDest.GetStride() == mapSrc.GetStride()) {
memcpy(mapDest.GetData(), mapSrc.GetData(),
out_surface->GetSize().height * mapDest.GetStride());
} else {
for (int32_t i = 0; i < dataSurf->GetSize().height; i++) {
memcpy(mapDest.GetData() + i * mapDest.GetStride(),
mapSrc.GetData() + i * mapSrc.GetStride(),
std::min(mapSrc.GetStride(), mapDest.GetStride()));
}
}
return true;
}
SurfaceFactory_GLXDrawable::SurfaceFactory_GLXDrawable(GLContext& gl)
: SurfaceFactory({&gl, SharedSurfaceType::GLXDrawable,
layers::TextureType::X11, true}) {}

View File

@ -34,9 +34,6 @@ class SharedSurface_GLXDrawable final : public SharedSurface {
virtual void UnlockProdImpl() override;
Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
virtual bool ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) override;
};
class SurfaceFactory_GLXDrawable final : public SurfaceFactory {

View File

@ -95,30 +95,5 @@ SharedSurface_IOSurface::ToSurfaceDescriptor() {
mIOSurf->GetYUVColorSpace()));
}
bool SharedSurface_IOSurface::ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) {
MOZ_ASSERT(out_surface);
mIOSurf->Lock();
size_t bytesPerRow = mIOSurf->GetBytesPerRow();
size_t ioWidth = mIOSurf->GetDevicePixelWidth();
size_t ioHeight = mIOSurf->GetDevicePixelHeight();
const unsigned char* ioData = (unsigned char*)mIOSurf->GetBaseAddress();
gfx::DataSourceSurface::ScopedMap map(out_surface,
gfx::DataSourceSurface::WRITE);
if (!map.IsMapped()) {
mIOSurf->Unlock();
return false;
}
for (size_t i = 0; i < ioHeight; i++) {
memcpy(map.GetData() + i * map.GetStride(), ioData + i * bytesPerRow,
ioWidth * 4);
}
mIOSurf->Unlock();
return true;
}
} // namespace gl
} // namespace mozilla

View File

@ -39,9 +39,6 @@ class SharedSurface_IOSurface final : public SharedSurface {
virtual bool NeedsIndirectReads() const override { return true; }
Maybe<layers::SurfaceDescriptor> ToSurfaceDescriptor() override;
virtual bool ReadbackBySharedHandle(
gfx::DataSourceSurface* out_surface) override;
};
class SurfaceFactory_IOSurface : public SurfaceFactory {

View File

@ -146,8 +146,8 @@ bool TextureImageEGL::BindTexImage() {
const auto& gle = GLContextEGL::Cast(mGLContext);
const auto& egl = gle->mEgl;
EGLBoolean success = egl->fBindTexImage(egl->Display(), (EGLSurface)mSurface,
LOCAL_EGL_BACK_BUFFER);
EGLBoolean success =
egl->fBindTexImage((EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
if (success == LOCAL_EGL_FALSE) return false;
@ -160,8 +160,8 @@ bool TextureImageEGL::ReleaseTexImage() {
const auto& gle = GLContextEGL::Cast(mGLContext);
const auto& egl = gle->mEgl;
EGLBoolean success = egl->fReleaseTexImage(
egl->Display(), (EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
EGLBoolean success =
egl->fReleaseTexImage((EGLSurface)mSurface, LOCAL_EGL_BACK_BUFFER);
if (success == LOCAL_EGL_FALSE) return false;
@ -174,7 +174,7 @@ void TextureImageEGL::DestroyEGLSurface(void) {
const auto& gle = GLContextEGL::Cast(mGLContext);
const auto& egl = gle->mEgl;
egl->fDestroySurface(egl->Display(), mSurface);
egl->fDestroySurface(mSurface);
mSurface = nullptr;
}

View File

@ -24,6 +24,7 @@ if CONFIG['MOZ_GL_PROVIDER']:
gl_provider = CONFIG['MOZ_GL_PROVIDER']
EXPORTS += [
'AndroidSurfaceTexture.h',
'DecomposeIntoNoRepeatTriangles.h',
'ForceDiscreteGPUHelperCGL.h',
'GfxTexturesReporter.h',
@ -70,10 +71,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
EXPORTS += [
'AndroidNativeWindow.h',
'AndroidSurfaceTexture.h',
]
UNIFIED_SOURCES += [
'AndroidSurfaceTexture.cpp',
]
if gl_provider == 'CGL':
@ -126,6 +123,7 @@ if CONFIG['MOZ_WAYLAND']:
]
UNIFIED_SOURCES += [
'AndroidSurfaceTexture.cpp',
'DecomposeIntoNoRepeatTriangles.cpp',
'GfxTexturesReporter.cpp',
'GLBlitHelper.cpp',

View File

@ -14,7 +14,6 @@
#include "mozilla/UniquePtr.h"
#include "YCbCrUtils.h"
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::gfx;

View File

@ -130,6 +130,7 @@ EXPORTS.mozilla.layers += [
'basic/TextureHostBasic.h',
'BSPTree.h',
'BufferTexture.h',
'BuildConstants.h',
'CanvasDrawEventRecorder.h',
'CanvasRenderer.h',
'client/CanvasClient.h',

View File

@ -751,7 +751,7 @@ void AndroidHardwareBufferTextureHost::DestroyEGLImage() {
if (mEGLImage && gl()) {
const auto& gle = gl::GLContextEGL::Cast(gl());
const auto& egl = gle->mEgl;
egl->fDestroyImage(egl->Display(), mEGLImage);
egl->fDestroyImage(mEGLImage);
mEGLImage = EGL_NO_IMAGE;
}
}
@ -790,11 +790,10 @@ void AndroidHardwareBufferTextureHost::PrepareTextureSource(
LOCAL_EGL_NONE,
};
EGLClientBuffer clientBuffer = egl->fGetNativeClientBufferANDROID(
EGLClientBuffer clientBuffer = egl->mLib->fGetNativeClientBufferANDROID(
mAndroidHardwareBuffer->GetNativeBuffer());
mEGLImage =
egl->fCreateImage(egl->Display(), EGL_NO_CONTEXT,
LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
mEGLImage = egl->fCreateImage(
EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
}
GLenum textureTarget = LOCAL_GL_TEXTURE_EXTERNAL;
@ -995,7 +994,8 @@ void EGLImageTextureSource::BindTexture(GLenum aTextureUnit,
const auto& gle = GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
return egl->HasKHRImageBase() && egl->HasKHRImageTexture2D() &&
return egl->HasKHRImageBase() &&
egl->IsExtensionSupported(EGLExtension::KHR_gl_texture_2D_image) &&
gl->IsExtensionSupported(GLContext::OES_EGL_image);
}();
MOZ_ASSERT(supportsEglImage, "EGLImage not supported or disabled in runtime");
@ -1058,13 +1058,14 @@ bool EGLImageTextureHost::Lock() {
if (!gl || !gl->MakeCurrent()) {
return false;
}
const auto& gle = GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
auto* egl = gl::GLLibraryEGL::Get();
EGLint status = LOCAL_EGL_CONDITION_SATISFIED;
if (mSync) {
MOZ_ASSERT(egl->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
status = egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER);
MOZ_ASSERT(egl->IsExtensionSupported(EGLExtension::KHR_fence_sync));
status = egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
}
if (status != LOCAL_EGL_CONDITION_SATISFIED) {

View File

@ -582,8 +582,8 @@ GLuint DCLayerTree::CreateEGLSurfaceForCompositionSurface(
// Construct an EGLImage wrapper around the D3D texture for ANGLE.
const EGLint attribs[] = {LOCAL_EGL_NONE};
mEGLImage = egl->fCreateImage(egl->Display(), EGL_NO_CONTEXT,
LOCAL_EGL_D3D11_TEXTURE_ANGLE, buffer, attribs);
mEGLImage = egl->fCreateImage(EGL_NO_CONTEXT, LOCAL_EGL_D3D11_TEXTURE_ANGLE,
buffer, attribs);
// Get the current FBO and RBO id, so we can restore them later
GLint currentFboId, currentRboId;
@ -625,7 +625,7 @@ void DCLayerTree::DestroyEGLSurface() {
if (mEGLImage) {
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
egl->fDestroyImage(egl->Display(), mEGLImage);
egl->fDestroyImage(mEGLImage);
mEGLImage = EGL_NO_IMAGE;
}
}

View File

@ -79,11 +79,10 @@ bool RenderAndroidHardwareBufferTextureHost::EnsureLockable(
LOCAL_EGL_NONE,
};
EGLClientBuffer clientBuffer = egl->fGetNativeClientBufferANDROID(
EGLClientBuffer clientBuffer = egl->mLib->fGetNativeClientBufferANDROID(
mAndroidHardwareBuffer->GetNativeBuffer());
mEGLImage =
egl->fCreateImage(egl->Display(), EGL_NO_CONTEXT,
LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
mEGLImage = egl->fCreateImage(
EGL_NO_CONTEXT, LOCAL_EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attrs);
}
MOZ_ASSERT(mEGLImage);
@ -148,7 +147,7 @@ void RenderAndroidHardwareBufferTextureHost::DestroyEGLImage() {
MOZ_ASSERT(mGL);
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
egl->fDestroyImage(egl->Display(), mEGLImage);
egl->fDestroyImage(mEGLImage);
mEGLImage = EGL_NO_IMAGE;
}

View File

@ -75,20 +75,24 @@ RenderCompositorANGLE::~RenderCompositorANGLE() {
}
ID3D11Device* RenderCompositorANGLE::GetDeviceOfEGLDisplay() {
auto* egl = gl::GLLibraryEGL::Get();
const auto& gl = RenderThread::Get()->SharedGL();
if (!gl) {
return nullptr;
}
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
MOZ_ASSERT(egl);
if (!egl || !egl->IsExtensionSupported(gl::GLLibraryEGL::EXT_device_query)) {
if (!egl || !egl->IsExtensionSupported(gl::EGLExtension::EXT_device_query)) {
return nullptr;
}
// Fetch the D3D11 device.
EGLDeviceEXT eglDevice = nullptr;
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT,
(EGLAttrib*)&eglDevice);
egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
MOZ_ASSERT(eglDevice);
ID3D11Device* device = nullptr;
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
if (!device) {
gfxCriticalNote << "Failed to get D3D11Device from EGLDisplay";
return nullptr;
@ -97,9 +101,8 @@ ID3D11Device* RenderCompositorANGLE::GetDeviceOfEGLDisplay() {
}
bool RenderCompositorANGLE::ShutdownEGLLibraryIfNecessary() {
const RefPtr<gl::GLLibraryEGL> egl = gl::GLLibraryEGL::Get();
if (!egl) {
// egl is not initialized yet;
const auto& displayDevice = GetDeviceOfEGLDisplay();
if (!displayDevice) {
return true;
}
@ -112,11 +115,10 @@ bool RenderCompositorANGLE::ShutdownEGLLibraryIfNecessary() {
// 0. It is ensured by GPUProcessManager during handling DeviceReset.
// GPUChild::RecvNotifyDeviceReset() destroys all CompositorSessions before
// re-creating them.
if (device.get() != GetDeviceOfEGLDisplay() &&
if (device.get() != displayDevice &&
RenderThread::Get()->RendererCount() == 0) {
// Shutdown GLLibraryEGL for updating EGLDisplay.
RenderThread::Get()->ClearSharedGL();
egl->Shutdown();
}
return true;
}
@ -141,7 +143,7 @@ bool RenderCompositorANGLE::Initialize() {
// formart
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
if (!gl::CreateConfig(egl, &mEGLConfig, /* bpp */ 32,
if (!gl::CreateConfig(*egl, &mEGLConfig, /* bpp */ 32,
/* enableDepthBuffer */ true, gl->IsGLES())) {
gfxCriticalNote << "Failed to create EGLConfig for WebRender";
}
@ -660,11 +662,10 @@ bool RenderCompositorANGLE::CreateEGLSurface() {
const auto& gle = gl::GLContextEGL::Cast(gl);
const auto& egl = gle->mEgl;
const EGLSurface surface = egl->fCreatePbufferFromClientBuffer(
egl->Display(), LOCAL_EGL_D3D_TEXTURE_ANGLE, buffer, mEGLConfig,
pbuffer_attribs);
LOCAL_EGL_D3D_TEXTURE_ANGLE, buffer, mEGLConfig, pbuffer_attribs);
EGLint err = egl->fGetError();
if (err != LOCAL_EGL_SUCCESS) {
if (!surface) {
EGLint err = egl->mLib->fGetError();
gfxCriticalError() << "Failed to create Pbuffer of back buffer error: "
<< gfx::hexa(err) << " Size : " << size;
return false;
@ -681,7 +682,7 @@ void RenderCompositorANGLE::DestroyEGLSurface() {
const auto& gle = gl::GLContextEGL::Cast(gl());
const auto& egl = gle->mEgl;
gle->SetEGLSurfaceOverride(EGL_NO_SURFACE);
egl->fDestroySurface(egl->Display(), mEGLSurface);
egl->fDestroySurface(mEGLSurface);
mEGLSurface = nullptr;
}
}

View File

@ -11,6 +11,7 @@
#include "GLContextProvider.h"
#include "GLLibraryEGL.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/layers/BuildConstants.h"
#include "mozilla/webrender/RenderThread.h"
#include "mozilla/widget/CompositorWidget.h"
@ -117,42 +118,45 @@ RenderedFrameId RenderCompositorEGL::EndFrame(
void RenderCompositorEGL::Pause() { DestroyEGLSurface(); }
bool RenderCompositorEGL::Resume() {
#ifdef MOZ_WIDGET_ANDROID
// Destroy EGLSurface if it exists.
DestroyEGLSurface();
mEGLSurface = CreateEGLSurface();
gl::GLContextEGL::Cast(gl())->SetEGLSurfaceOverride(mEGLSurface);
if (kIsAndroid) {
// Destroy EGLSurface if it exists.
DestroyEGLSurface();
mEGLSurface = CreateEGLSurface();
gl::GLContextEGL::Cast(gl())->SetEGLSurfaceOverride(mEGLSurface);
// Query the new surface size as this may have changed. We cannot use
// mWidget->GetClientSize() due to a race condition between nsWindow::Resize()
// being called and the frame being rendered after the surface is resized.
EGLNativeWindowType window = mWidget->AsAndroid()->GetEGLNativeWindow();
JNIEnv* const env = jni::GetEnvForThread();
ANativeWindow* const nativeWindow =
ANativeWindow_fromSurface(env, reinterpret_cast<jobject>(window));
const int32_t width = ANativeWindow_getWidth(nativeWindow);
const int32_t height = ANativeWindow_getHeight(nativeWindow);
mEGLSurfaceSize = LayoutDeviceIntSize(width, height);
ANativeWindow_release(nativeWindow);
#elif defined(MOZ_WAYLAND)
// Destroy EGLSurface if it exists and create a new one. We will set the
// swap interval after MakeCurrent() has been called.
DestroyEGLSurface();
mEGLSurface = CreateEGLSurface();
if (mEGLSurface != EGL_NO_SURFACE) {
// We have a new EGL surface, which on wayland needs to be configured for
// non-blocking buffer swaps. We need MakeCurrent() to set our current EGL
// context before we call eglSwapInterval, which is why we do it here rather
// than where the surface was created.
const auto& gle = gl::GLContextEGL::Cast(gl());
const auto& egl = gle->mEgl;
MakeCurrent();
// Make eglSwapBuffers() non-blocking on wayland.
egl->fSwapInterval(egl->Display(), 0);
} else {
RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE);
#ifdef MOZ_WIDGET_ANDROID
// Query the new surface size as this may have changed. We cannot use
// mWidget->GetClientSize() due to a race condition between
// nsWindow::Resize() being called and the frame being rendered after the
// surface is resized.
EGLNativeWindowType window = mWidget->AsAndroid()->GetEGLNativeWindow();
JNIEnv* const env = jni::GetEnvForThread();
ANativeWindow* const nativeWindow =
ANativeWindow_fromSurface(env, reinterpret_cast<jobject>(window));
const int32_t width = ANativeWindow_getWidth(nativeWindow);
const int32_t height = ANativeWindow_getHeight(nativeWindow);
mEGLSurfaceSize = LayoutDeviceIntSize(width, height);
ANativeWindow_release(nativeWindow);
#endif // MOZ_WIDGET_ANDROID
} else if (kIsWayland) {
// Destroy EGLSurface if it exists and create a new one. We will set the
// swap interval after MakeCurrent() has been called.
DestroyEGLSurface();
mEGLSurface = CreateEGLSurface();
if (mEGLSurface != EGL_NO_SURFACE) {
// We have a new EGL surface, which on wayland needs to be configured for
// non-blocking buffer swaps. We need MakeCurrent() to set our current EGL
// context before we call eglSwapInterval, which is why we do it here
// rather than where the surface was created.
const auto& gle = gl::GLContextEGL::Cast(gl());
const auto& egl = gle->mEgl;
MakeCurrent();
// Make eglSwapBuffers() non-blocking on wayland.
egl->fSwapInterval(0);
} else {
RenderThread::Get()->HandleWebRenderError(WebRenderError::NEW_SURFACE);
}
}
#endif
return true;
}
@ -172,7 +176,7 @@ void RenderCompositorEGL::DestroyEGLSurface() {
// Release EGLSurface of back buffer before calling ResizeBuffers().
if (mEGLSurface) {
gle->SetEGLSurfaceOverride(EGL_NO_SURFACE);
egl->fDestroySurface(egl->Display(), mEGLSurface);
egl->fDestroySurface(mEGLSurface);
mEGLSurface = nullptr;
}
}

View File

@ -64,12 +64,11 @@ bool RenderDXGITextureHostOGL::EnsureD3D11Texture2D() {
// Fetch the D3D11 device.
EGLDeviceEXT eglDevice = nullptr;
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT,
(EGLAttrib*)&eglDevice);
egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
MOZ_ASSERT(eglDevice);
ID3D11Device* device = nullptr;
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
// There's a chance this might fail if we end up on d3d9 angle for some
// reason.
if (!device) {
@ -122,9 +121,9 @@ bool RenderDXGITextureHostOGL::EnsureLockable(wr::ImageRendering aRendering) {
// NV_stream_consumer_gltexture_yuv and ANGLE_stream_producer_d3d_texture
// could support nv12 and rgb d3d texture format.
if (!egl->IsExtensionSupported(
gl::GLLibraryEGL::NV_stream_consumer_gltexture_yuv) ||
gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
!egl->IsExtensionSupported(
gl::GLLibraryEGL::ANGLE_stream_producer_d3d_texture)) {
gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
gfxCriticalNote
<< "RenderDXGITextureHostOGL egl extensions are not suppored";
return false;
@ -137,7 +136,7 @@ bool RenderDXGITextureHostOGL::EnsureLockable(wr::ImageRendering aRendering) {
mTexture->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mKeyedMutex));
// Create the EGLStream.
mStream = egl->fCreateStreamKHR(egl->Display(), nullptr);
mStream = egl->fCreateStreamKHR(nullptr);
MOZ_ASSERT(mStream);
bool ok = true;
@ -152,10 +151,9 @@ bool RenderDXGITextureHostOGL::EnsureLockable(wr::ImageRendering aRendering) {
mTextureHandle[0], aRendering);
// Cache new rendering filter.
mCachedRendering = aRendering;
ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
egl->Display(), mStream, nullptr));
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(egl->Display(),
mStream, nullptr));
ok &=
bool(egl->fStreamConsumerGLTextureExternalAttribsNV(mStream, nullptr));
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
} else {
// The nv12/p016 format.
@ -181,14 +179,13 @@ bool RenderDXGITextureHostOGL::EnsureLockable(wr::ImageRendering aRendering) {
// Cache new rendering filter.
mCachedRendering = aRendering;
ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
egl->Display(), mStream, consumerAttributes));
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(egl->Display(),
mStream, nullptr));
mStream, consumerAttributes));
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStream, nullptr));
}
// Insert the d3d texture.
ok &= bool(egl->fStreamPostD3DTextureANGLE(egl->Display(), mStream,
(void*)mTexture.get(), nullptr));
ok &= bool(
egl->fStreamPostD3DTextureANGLE(mStream, (void*)mTexture.get(), nullptr));
if (!ok) {
gfxCriticalNote << "RenderDXGITextureHostOGL init stream failed";
@ -197,8 +194,7 @@ bool RenderDXGITextureHostOGL::EnsureLockable(wr::ImageRendering aRendering) {
}
// Now, we could get the gl handle from the stream.
egl->fStreamConsumerAcquireKHR(egl->Display(), mStream);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStream));
return true;
}
@ -267,13 +263,14 @@ void RenderDXGITextureHostOGL::DeleteTextureHandle() {
if (mGL->MakeCurrent()) {
mGL->fDeleteTextures(2, mTextureHandle);
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
if (mSurface) {
egl->fDestroySurface(egl->Display(), mSurface);
egl->fDestroySurface(mSurface);
}
if (mStream) {
egl->fDestroyStreamKHR(egl->Display(), mStream);
egl->fDestroyStreamKHR(mStream);
}
}
@ -357,9 +354,9 @@ bool RenderDXGIYCbCrTextureHostOGL::EnsureLockable(
// use EGLStream to get the converted gl handle from d3d R8 texture.
if (!egl->IsExtensionSupported(
gl::GLLibraryEGL::NV_stream_consumer_gltexture_yuv) ||
gl::EGLExtension::NV_stream_consumer_gltexture_yuv) ||
!egl->IsExtensionSupported(
gl::GLLibraryEGL::ANGLE_stream_producer_d3d_texture)) {
gl::EGLExtension::ANGLE_stream_producer_d3d_texture)) {
gfxCriticalNote
<< "RenderDXGIYCbCrTextureHostOGL egl extensions are not suppored";
return false;
@ -367,12 +364,11 @@ bool RenderDXGIYCbCrTextureHostOGL::EnsureLockable(
// Fetch the D3D11 device.
EGLDeviceEXT eglDevice = nullptr;
egl->fQueryDisplayAttribEXT(egl->Display(), LOCAL_EGL_DEVICE_EXT,
(EGLAttrib*)&eglDevice);
egl->fQueryDisplayAttribEXT(LOCAL_EGL_DEVICE_EXT, (EGLAttrib*)&eglDevice);
MOZ_ASSERT(eglDevice);
ID3D11Device* device = nullptr;
egl->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
// There's a chance this might fail if we end up on d3d9 angle for some
// reason.
if (!device) {
@ -412,21 +408,19 @@ bool RenderDXGIYCbCrTextureHostOGL::EnsureLockable(
mCachedRendering = aRendering;
// Create the EGLStream.
mStreams[i] = egl->fCreateStreamKHR(egl->Display(), nullptr);
mStreams[i] = egl->fCreateStreamKHR(nullptr);
MOZ_ASSERT(mStreams[i]);
ok &= bool(egl->fStreamConsumerGLTextureExternalAttribsNV(
egl->Display(), mStreams[i], nullptr));
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(egl->Display(),
mStreams[i], nullptr));
ok &= bool(
egl->fStreamConsumerGLTextureExternalAttribsNV(mStreams[i], nullptr));
ok &= bool(egl->fCreateStreamProducerD3DTextureANGLE(mStreams[i], nullptr));
// Insert the R8 texture.
ok &= bool(egl->fStreamPostD3DTextureANGLE(
egl->Display(), mStreams[i], (void*)mTextures[i].get(), nullptr));
mStreams[i], (void*)mTextures[i].get(), nullptr));
// Now, we could get the R8 gl handle from the stream.
egl->fStreamConsumerAcquireKHR(egl->Display(), mStreams[i]);
MOZ_ASSERT(egl->fGetError() == LOCAL_EGL_SUCCESS);
MOZ_ALWAYS_TRUE(egl->fStreamConsumerAcquireKHR(mStreams[i]));
}
if (!ok) {
@ -523,21 +517,22 @@ void RenderDXGIYCbCrTextureHostOGL::DeleteTextureHandle() {
if (mGL->MakeCurrent()) {
mGL->fDeleteTextures(3, mTextureHandles);
}
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
for (int i = 0; i < 3; ++i) {
mTextureHandles[i] = 0;
mTextures[i] = nullptr;
mKeyedMutexs[i] = nullptr;
if (mSurfaces[i]) {
egl->fDestroySurface(egl->Display(), mSurfaces[i]);
mSurfaces[i] = 0;
}
if (mStreams[i]) {
egl->fDestroyStreamKHR(egl->Display(), mStreams[i]);
mStreams[i] = 0;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
for (int i = 0; i < 3; ++i) {
mTextureHandles[i] = 0;
mTextures[i] = nullptr;
mKeyedMutexs[i] = nullptr;
if (mSurfaces[i]) {
egl->fDestroySurface(mSurfaces[i]);
mSurfaces[i] = 0;
}
if (mStreams[i]) {
egl->fDestroyStreamKHR(mStreams[i]);
mStreams[i] = 0;
}
}
}
}

View File

@ -59,8 +59,8 @@ wr::WrExternalImage RenderEGLImageTextureHost::Lock(
if (mSync) {
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
MOZ_ASSERT(egl->IsExtensionSupported(gl::GLLibraryEGL::KHR_fence_sync));
status = egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER);
MOZ_ASSERT(egl->IsExtensionSupported(gl::EGLExtension::KHR_fence_sync));
status = egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
// We do not need to delete sync here. It is deleted by
// SharedSurface_EGLImage.
mSync = 0;

View File

@ -27,6 +27,9 @@
#ifdef XP_WIN
# include "GLLibraryEGL.h"
# include "mozilla/widget/WinCompositorWindowThread.h"
# include "mozilla/gfx/DeviceManagerDx.h"
//# include "nsWindowsHelpers.h"
//# include <d3d11.h>
#endif
#ifdef MOZ_WIDGET_ANDROID
@ -991,26 +994,40 @@ WebRenderProgramCache::~WebRenderProgramCache() {
#ifdef XP_WIN
static already_AddRefed<gl::GLContext> CreateGLContextANGLE() {
nsCString discardFailureId;
if (!gl::GLLibraryEGL::EnsureInitialized(/* forceAccel */ true,
&discardFailureId)) {
gfxCriticalNote << "Failed to load EGL library: " << discardFailureId.get();
const RefPtr<ID3D11Device> d3d11Device =
gfx::DeviceManagerDx::Get()->GetCompositorDevice();
if (!d3d11Device) {
gfxCriticalNote << "Failed to get compositor device for EGLDisplay";
return nullptr;
}
nsCString failureId;
const auto lib = gl::DefaultEglLibrary(&failureId);
if (!lib) {
gfxCriticalNote << "Failed to load EGL library: " << failureId.get();
return nullptr;
}
const auto egl = lib->CreateDisplay(d3d11Device.get());
if (!egl) {
gfxCriticalNote << "Failed to create EGL display: " << failureId.get();
return nullptr;
}
auto* egl = gl::GLLibraryEGL::Get();
gl::CreateContextFlags flags = gl::CreateContextFlags::PREFER_ES3 |
gl::CreateContextFlags::PREFER_ROBUSTNESS;
if (egl->IsExtensionSupported(
gl::GLLibraryEGL::MOZ_create_context_provoking_vertex_dont_care)) {
gl::EGLExtension::MOZ_create_context_provoking_vertex_dont_care)) {
flags |= gl::CreateContextFlags::PROVOKING_VERTEX_DONT_CARE;
}
// Create GLContext with dummy EGLSurface, the EGLSurface is not used.
// Instread we override it with EGLSurface of SwapChain's back buffer.
RefPtr<gl::GLContext> gl =
gl::GLContextProviderEGL::CreateHeadless({flags}, &discardFailureId);
const auto dummySize = mozilla::gfx::IntSize(16, 16);
auto gl = gl::GLContextEGL::CreateEGLPBufferOffscreenContext(
egl, {flags}, dummySize, &failureId);
if (!gl || !gl->IsANGLE()) {
gfxCriticalNote << "Failed ANGLE GL context creation for WebRender: "
<< gfx::hexa(gl.get());
@ -1029,12 +1046,6 @@ static already_AddRefed<gl::GLContext> CreateGLContextANGLE() {
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WAYLAND)
static already_AddRefed<gl::GLContext> CreateGLContextEGL() {
nsCString discardFailureId;
if (!gl::GLLibraryEGL::EnsureInitialized(/* forceAccel */ true,
&discardFailureId)) {
gfxCriticalNote << "Failed to load EGL library: " << discardFailureId.get();
return nullptr;
}
// Create GLContext with dummy EGLSurface.
RefPtr<gl::GLContext> gl =
gl::GLContextProviderEGL::CreateForCompositorWidget(

View File

@ -10,6 +10,7 @@ with Files('**'):
EXPORTS.mozilla.webrender += [
'RenderBufferTextureHost.h',
'RenderCompositor.h',
'RenderCompositorEGL.h',
'RenderCompositorOGL.h',
'RenderCompositorSWGL.h',
'RenderEGLImageTextureHost.h',
@ -30,6 +31,7 @@ UNIFIED_SOURCES += [
'Moz2DImageRenderer.cpp',
'RenderBufferTextureHost.cpp',
'RenderCompositor.cpp',
'RenderCompositorEGL.cpp',
'RenderCompositorOGL.cpp',
'RenderCompositorSWGL.cpp',
'RenderEGLImageTextureHost.cpp',
@ -59,12 +61,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
EXPORTS.mozilla.webrender += [
'RenderAndroidHardwareBufferTextureHost.h',
'RenderAndroidSurfaceTextureHostOGL.h',
'RenderCompositorEGL.h',
]
UNIFIED_SOURCES += [
'RenderAndroidHardwareBufferTextureHost.cpp',
'RenderAndroidSurfaceTextureHostOGL.cpp',
'RenderCompositorEGL.cpp',
]
if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
@ -84,11 +84,9 @@ if CONFIG['MOZ_ENABLE_D3D10_LAYER']:
if CONFIG['MOZ_WAYLAND']:
EXPORTS.mozilla.webrender += [
'RenderCompositorEGL.h',
'RenderDMABUFTextureHostOGL.h',
]
SOURCES += [
'RenderCompositorEGL.cpp',
'RenderDMABUFTextureHostOGL.cpp',
]

View File

@ -184,7 +184,9 @@ already_AddRefed<DMABufSurface> DMABufSurface::CreateDMABufSurface(
}
void DMABufSurface::FenceDelete() {
auto* egl = gl::GLLibraryEGL::Get();
if (!mGL) return;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
if (mSyncFd > 0) {
close(mSyncFd);
@ -192,7 +194,7 @@ void DMABufSurface::FenceDelete() {
}
if (mSync) {
egl->fDestroySync(egl->Display(), mSync);
egl->fDestroySync(mSync);
mSync = nullptr;
}
}
@ -201,16 +203,16 @@ void DMABufSurface::FenceSet() {
if (!mGL || !mGL->MakeCurrent()) {
return;
}
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
auto* egl = gl::GLLibraryEGL::Get();
if (egl->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync) &&
egl->IsExtensionSupported(GLLibraryEGL::ANDROID_native_fence_sync)) {
if (egl->IsExtensionSupported(EGLExtension::KHR_fence_sync) &&
egl->IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync)) {
FenceDelete();
mSync = egl->fCreateSync(egl->Display(),
LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
mSync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
if (mSync) {
mSyncFd = egl->fDupNativeFenceFDANDROID(egl->Display(), mSync);
mSyncFd = egl->fDupNativeFenceFDANDROID(mSync);
mGL->fFlush();
return;
}
@ -222,7 +224,10 @@ void DMABufSurface::FenceSet() {
}
void DMABufSurface::FenceWait() {
auto* egl = gl::GLLibraryEGL::Get();
if (!mGL) return;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
if (!mSync && mSyncFd > 0) {
FenceImportFromFd();
}
@ -230,16 +235,18 @@ void DMABufSurface::FenceWait() {
// Wait on the fence, because presumably we're going to want to read this
// surface
if (mSync) {
egl->fClientWaitSync(egl->Display(), mSync, 0, LOCAL_EGL_FOREVER);
egl->fClientWaitSync(mSync, 0, LOCAL_EGL_FOREVER);
}
}
bool DMABufSurface::FenceImportFromFd() {
auto* egl = gl::GLLibraryEGL::Get();
if (!mGL) return false;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, mSyncFd,
LOCAL_EGL_NONE};
mSync = egl->fCreateSync(egl->Display(), LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID,
attribs);
mSync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
close(mSyncFd);
mSyncFd = -1;
@ -431,6 +438,10 @@ bool DMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) {
bool DMABufSurfaceRGBA::Serialize(
mozilla::layers::SurfaceDescriptor& aOutDescriptor) {
if (!mGL) return false;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> width;
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> height;
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> format;
@ -536,10 +547,12 @@ bool DMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext, int aPlane) {
#undef ADD_PLANE_ATTRIBS
attribs.AppendElement(LOCAL_EGL_NONE);
auto* egl = gl::GLLibraryEGL::Get();
mEGLImage = egl->fCreateImage(egl->Display(), LOCAL_EGL_NO_CONTEXT,
LOCAL_EGL_LINUX_DMA_BUF_EXT, nullptr,
attribs.Elements());
if (!mGL) return false;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
mEGLImage =
egl->fCreateImage(LOCAL_EGL_NO_CONTEXT, LOCAL_EGL_LINUX_DMA_BUF_EXT,
nullptr, attribs.Elements());
if (mEGLImage == LOCAL_EGL_NO_IMAGE) {
NS_WARNING("EGLImageKHR creation failed");
return false;
@ -564,6 +577,10 @@ bool DMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext, int aPlane) {
void DMABufSurfaceRGBA::ReleaseTextures() {
FenceDelete();
if (!mGL) return;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
if (mTexture && mGL->MakeCurrent()) {
mGL->fDeleteTextures(1, &mTexture);
mTexture = 0;
@ -571,8 +588,7 @@ void DMABufSurfaceRGBA::ReleaseTextures() {
}
if (mEGLImage) {
auto* egl = gl::GLLibraryEGL::Get();
egl->fDestroyImage(egl->Display(), mEGLImage);
egl->fDestroyImage(mEGLImage);
mEGLImage = nullptr;
}
}
@ -899,6 +915,10 @@ void DMABufSurfaceYUV::ImportSurfaceDescriptor(
bool DMABufSurfaceYUV::Serialize(
mozilla::layers::SurfaceDescriptor& aOutDescriptor) {
if (!mGL) return false;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> width;
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> height;
AutoTArray<uint32_t, DMABUF_BUFFER_PLANES> format;
@ -931,29 +951,14 @@ bool DMABufSurfaceYUV::Serialize(
return true;
}
#if 0
already_AddRefed<gl::GLContext> MyCreateGLContextEGL() {
nsCString discardFailureId;
if (!gl::GLLibraryEGL::EnsureInitialized(true, &discardFailureId)) {
gfxCriticalNote << "Failed to load EGL library: " << discardFailureId.get();
return nullptr;
}
// Create GLContext with dummy EGLSurface.
RefPtr<gl::GLContext> gl =
gl::GLContextProviderEGL::CreateForCompositorWidget(nullptr, true, true);
if (!gl || !gl->MakeCurrent()) {
gfxCriticalNote << "Failed GL context creation for WebRender: "
<< gfx::hexa(gl.get());
return nullptr;
}
return gl.forget();
}
#endif
bool DMABufSurfaceYUV::CreateTexture(GLContext* aGLContext, int aPlane) {
MOZ_ASSERT(!mEGLImage[aPlane] && !mTexture[aPlane],
"EGLImage/Texture is already created!");
if (!mGL) return false;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
nsTArray<EGLint> attribs;
attribs.AppendElement(LOCAL_EGL_WIDTH);
attribs.AppendElement(mWidth[aPlane]);
@ -972,10 +977,9 @@ bool DMABufSurfaceYUV::CreateTexture(GLContext* aGLContext, int aPlane) {
#undef ADD_PLANE_ATTRIBS_NV12
attribs.AppendElement(LOCAL_EGL_NONE);
auto* egl = gl::GLLibraryEGL::Get();
mEGLImage[aPlane] = egl->fCreateImage(egl->Display(), LOCAL_EGL_NO_CONTEXT,
LOCAL_EGL_LINUX_DMA_BUF_EXT, nullptr,
attribs.Elements());
mEGLImage[aPlane] =
egl->fCreateImage(LOCAL_EGL_NO_CONTEXT, LOCAL_EGL_LINUX_DMA_BUF_EXT,
nullptr, attribs.Elements());
if (mEGLImage[aPlane] == LOCAL_EGL_NO_IMAGE) {
NS_WARNING("EGLImageKHR creation failed");
return false;
@ -1008,6 +1012,10 @@ void DMABufSurfaceYUV::ReleaseTextures() {
}
}
if (!mGL) return;
const auto& gle = gl::GLContextEGL::Cast(mGL);
const auto& egl = gle->mEgl;
if (textureActive && mGL->MakeCurrent()) {
mGL->fDeleteTextures(DMABUF_BUFFER_PLANES, mTexture);
for (int i = 0; i < DMABUF_BUFFER_PLANES; i++) {
@ -1018,8 +1026,7 @@ void DMABufSurfaceYUV::ReleaseTextures() {
for (int i = 0; i < mBufferPlaneCount; i++) {
if (mEGLImage[i]) {
auto* egl = gl::GLLibraryEGL::Get();
egl->fDestroyImage(egl->Display(), mEGLImage[i]);
egl->fDestroyImage(mEGLImage[i]);
mEGLImage[i] = nullptr;
}
}