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
Родитель 953004415b
Коммит b5d6906473
45 изменённых файлов: 1381 добавлений и 1513 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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__

Просмотреть файл

@ -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?");

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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());
}

Просмотреть файл

@ -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,8 +400,9 @@ bool GLContextEGL::Init() {
return false;
}
mShareWithEGLImage = mEgl->HasKHRImageBase() &&
mEgl->HasKHRImageTexture2D() &&
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,12 +898,13 @@ 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)) {
if (CreateConfig(egl, aConfig, depth, aEnableDepthBuffer, aUseGles)) {
return true;
}
#ifdef MOZ_WIDGET_ANDROID
// Bug 736005
// Android doesn't always support 16 bit so also try 24 bit
@ -931,34 +918,11 @@ static bool CreateConfigScreen(GLLibraryEGL* const egl,
}
#endif
return false;
} else {
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;
}
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();
}
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) {
const auto fnCreate = [&](const bool useGles) -> EGLSurface {
// 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,
auto config = mConfig;
if (!config && !CreateConfigScreen(*mEgl, &config,
/* aEnableDepthBuffer */ false,
/* useGles */ aUseGles)) {
return EGL_NO_SURFACE;
/* useGles */ useGles)) {
return nullptr;
}
MOZ_ASSERT(aWindow);
return egl->fCreateWindowSurface(egl->Display(), config, aWindow, 0);
}
return mEgl->fCreateWindowSurface(
config, reinterpret_cast<EGLNativeWindowType>(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) {
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 */

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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.
*/

Просмотреть файл

@ -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;

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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; }

Просмотреть файл

@ -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,
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};
EGLDisplay display = egl.fGetPlatformDisplayEXT(
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,
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);
}
}
if (IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle)) {
const SymLoadStruct d3dSymbols[] = {SYMBOL(QuerySurfacePointerANGLE),
// 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(d3dSymbols)) {
NS_ERROR(
"EGL supports ANGLE_surface_d3d_texture_2d_share_handle without "
"exposing its functions!");
MarkExtensionUnsupported(ANGLE_surface_d3d_texture_2d_share_handle);
if (fnLoadSymbols(symbols)) {
mAvailableExtensions[UnderlyingValue(
EGLLibExtension::ANDROID_get_native_client_buffer)] = true;
}
}
if (IsExtensionSupported(KHR_fence_sync)) {
const SymLoadStruct syncSymbols[] = {
// -
// Load possible display ext symbols.
{
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);
}
{
const SymLoadStruct symbols[] = {SYMBOL(CreateImageKHR),
SYMBOL(DestroyImageKHR), END_OF_SYMBOLS};
(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);
}
if (IsExtensionSupported(ANDROID_native_fence_sync)) {
const SymLoadStruct nativeFenceSymbols[] = {SYMBOL(DupNativeFenceFDANDROID),
{
const SymLoadStruct symbols[] = {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);
(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);
}
}
if (IsExtensionSupported(KHR_stream)) {
const SymLoadStruct streamSymbols[] = {
SYMBOL(CreateStreamKHR), SYMBOL(DestroyStreamKHR),
{
const SymLoadStruct symbols[] = {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);
(void)fnLoadSymbols(symbols);
}
}
if (IsExtensionSupported(KHR_stream_consumer_gltexture)) {
const SymLoadStruct streamConsumerSymbols[] = {
SYMBOL(StreamConsumerGLTextureExternalKHR),
SYMBOL(StreamConsumerAcquireKHR), SYMBOL(StreamConsumerReleaseKHR),
{
const SymLoadStruct symbols[] = {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);
(void)fnLoadSymbols(symbols);
}
}
if (IsExtensionSupported(EXT_device_query)) {
const SymLoadStruct queryDisplaySymbols[] = {SYMBOL(QueryDisplayAttribEXT),
{
const SymLoadStruct symbols[] = {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);
(void)fnLoadSymbols(symbols);
}
}
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;
}
// -
EGLDisplay GLLibraryEGL::CreateDisplay(bool forceAccel,
const nsCOMPtr<nsIGfxInfo>& gfxInfo,
std::shared_ptr<EglDisplay> GLLibraryEGL::DefaultDisplay(
nsACString* const out_failureId) {
MOZ_ASSERT(!mInitialized);
auto ret = mDefaultDisplay.lock();
if (ret) return ret;
EGLDisplay chosenDisplay = nullptr;
ret = CreateDisplay(false, out_failureId);
mDefaultDisplay = ret;
return ret;
}
if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
std::shared_ptr<EglDisplay> GLLibraryEGL::CreateDisplay(
const bool forceAccel, nsACString* const out_failureId) {
const nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
std::shared_ptr<EglDisplay> ret;
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,38 +791,22 @@ 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;
void EglDisplay::DumpEGLConfig(EGLConfig cfg) const {
#define ATTR(_x) \
do { \
fGetConfigAttrib(mEGLDisplay, cfg, LOCAL_EGL_##_x, &attrval); \
if ((err = fGetError()) != 0x3000) { \
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); \
@ -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() {

Просмотреть файл

@ -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,37 +56,40 @@ PRLibrary* LoadApitraceLibrary();
void BeforeEGLCall(const char* funcName);
void AfterEGLCall(const char* funcName);
class GLLibraryEGL final {
protected:
~GLLibraryEGL() = default;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL)
void InitClientExtensions();
void InitDisplayExtensions();
/**
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 EGLExtensions {
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,
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,
@ -89,30 +97,60 @@ class GLLibraryEGL final {
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
};
Max
};
bool IsExtensionSupported(EGLExtensions aKnownExtension) const {
return mAvailableExtensions[aKnownExtension];
}
// -
void MarkExtensionUnsupported(EGLExtensions aKnownExtension) {
mAvailableExtensions[aKnownExtension] = false;
}
protected:
std::bitset<Extensions_Max> mAvailableExtensions;
class GLLibraryEGL final {
friend class EglDisplay;
public:
////
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL)
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);
@ -141,238 +179,269 @@ class GLLibraryEGL final {
#endif
#define WRAP(X) \
{ \
PROFILE_CALL \
BEFORE_CALL \
const auto ret = mSymbols.X; \
AFTER_CALL \
return ret; \
}
return ret
#define VOID_WRAP(X) \
{ \
PROFILE_CALL \
BEFORE_CALL \
mSymbols.X; \
AFTER_CALL \
public:
EGLDisplay fGetDisplay(void* display_id) const {
WRAP(fGetDisplay(display_id));
}
EGLDisplay fGetDisplay(void* display_id) const WRAP(fGetDisplay(display_id))
EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display,
const EGLint* attrib_list) const
WRAP(fGetPlatformDisplayEXT(platform, native_display, attrib_list))
const EGLint* attrib_list) const {
WRAP(fGetPlatformDisplayEXT(platform, native_display, attrib_list));
}
EGLBoolean fTerminate(EGLDisplay display) const
WRAP(fTerminate(display))
EGLSurface fGetCurrentSurface(EGLint id) const {
WRAP(fGetCurrentSurface(id));
}
EGLSurface fGetCurrentSurface(EGLint id) const
WRAP(fGetCurrentSurface(id))
EGLContext fGetCurrentContext() const { WRAP(fGetCurrentContext()); }
EGLContext fGetCurrentContext() const WRAP(fGetCurrentContext())
EGLBoolean fBindAPI(EGLenum api) const { WRAP(fBindAPI(api)); }
EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw,
EGLSurface read, EGLContext ctx) const
WRAP(fMakeCurrent(dpy, draw, read, ctx))
EGLint fGetError() const { WRAP(fGetError()); }
EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const
WRAP(fDestroyContext(dpy, ctx))
EGLBoolean fWaitNative(EGLint engine) const { WRAP(fWaitNative(engine)); }
EGLContext
fCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context,
const EGLint* attrib_list) const
WRAP(fCreateContext(dpy, config, share_context, attrib_list))
EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const
WRAP(fDestroySurface(dpy, surface))
EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLNativeWindowType win,
const EGLint* attrib_list) const
WRAP(fCreateWindowSurface(dpy, config, win, attrib_list))
EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
const EGLint* attrib_list) const
WRAP(fCreatePbufferSurface(dpy, config, attrib_list))
EGLSurface
fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer, EGLConfig config,
const EGLint* attrib_list) const
WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
attrib_list))
EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
EGLNativePixmapType pixmap,
const EGLint* attrib_list) const
WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list))
EGLBoolean fBindAPI(EGLenum api) const WRAP(fBindAPI(api))
EGLBoolean
fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const
WRAP(fInitialize(dpy, major, minor))
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))
EGLint fGetError() const WRAP(fGetError())
EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
EGLint attribute, EGLint* value) const
WRAP(fGetConfigAttrib(dpy, config, attribute, value))
EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs,
EGLint config_size, EGLint* num_config) const
WRAP(fGetConfigs(dpy, configs, config_size, num_config))
EGLBoolean fWaitNative(EGLint engine) const WRAP(fWaitNative(engine))
EGLCastToRelevantPtr fGetProcAddress(const char* procname) const
WRAP(fGetProcAddress(procname))
EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const
WRAP(fSwapBuffers(dpy, surface))
EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface,
EGLNativePixmapType target) const
WRAP(fCopyBuffers(dpy, surface, target))
const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const
WRAP(fQueryString(dpy, name))
EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx,
EGLint attribute, EGLint* value) const
WRAP(fQueryContext(dpy, ctx, attribute, value))
EGLBoolean
fBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const
WRAP(fBindTexImage(dpy, surface, buffer))
EGLBoolean
fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const
WRAP(fReleaseTexImage(dpy, surface, buffer))
EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const
WRAP(fSwapInterval(dpy, interval))
EGLImage
fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer, const EGLint* attrib_list) const
WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list))
EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const
WRAP(fDestroyImageKHR(dpy, image))
EGLBoolean fLockSurface(EGLDisplay dpy, EGLSurface surface,
const EGLint* attrib_list) const
WRAP(fLockSurfaceKHR(dpy, surface, attrib_list))
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
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))
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))
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))
// 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 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))
EGLBoolean
fStreamConsumerAcquireKHR(EGLDisplay dpy, EGLStreamKHR stream) const
WRAP(fStreamConsumerAcquireKHR(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))
EGLBoolean
fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute,
EGLAttrib* value) const
WRAP(fQueryDeviceAttribEXT(device, attribute, value))
// 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))
EGLBoolean
fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream,
void* texture,
const EGLAttrib* attrib_list) const
WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list))
EGLCastToRelevantPtr fGetProcAddress(const char* procname) const {
WRAP(fGetProcAddress(procname));
}
// ANGLE_device_creation
EGLDeviceEXT fCreateDeviceANGLE(EGLint device_type, void* native_device,
const EGLAttrib* attrib_list) const
WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list))
const EGLAttrib* attrib_list) const {
WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list));
}
EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device)
WRAP(fReleaseDeviceANGLE(device))
EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device) {
WRAP(fReleaseDeviceANGLE(device));
}
// ANDROID_get_native_client_buffer
EGLClientBuffer fGetNativeClientBufferANDROID(
const struct AHardwareBuffer* buffer) {
WRAP(fGetNativeClientBufferANDROID(buffer));
}
private:
EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); }
EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
EGLContext ctx) const {
WRAP(fMakeCurrent(dpy, draw, read, ctx));
}
EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const {
WRAP(fDestroyContext(dpy, ctx));
}
EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config,
EGLContext share_context,
const EGLint* attrib_list) const {
WRAP(fCreateContext(dpy, config, share_context, attrib_list));
}
EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const {
WRAP(fDestroySurface(dpy, surface));
}
public:
EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLNativeWindowType win,
const EGLint* attrib_list) const {
WRAP(fCreateWindowSurface(dpy, config, win, attrib_list));
}
private:
EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
const EGLint* attrib_list) const {
WRAP(fCreatePbufferSurface(dpy, config, attrib_list));
}
EGLSurface fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer,
EGLConfig config,
const EGLint* attrib_list) const {
WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
attrib_list));
}
EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
EGLNativePixmapType pixmap,
const EGLint* attrib_list) const {
WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list));
}
EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const {
WRAP(fInitialize(dpy, major, minor));
}
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));
}
EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
EGLint attribute, EGLint* value) const {
WRAP(fGetConfigAttrib(dpy, config, attribute, value));
}
EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size,
EGLint* num_config) const {
WRAP(fGetConfigs(dpy, configs, config_size, num_config));
}
EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const {
WRAP(fSwapBuffers(dpy, surface));
}
EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface,
EGLNativePixmapType target) const {
WRAP(fCopyBuffers(dpy, surface, target));
}
public:
const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const {
WRAP(fQueryString(dpy, name));
}
private:
EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute,
EGLint* value) const {
WRAP(fQueryContext(dpy, ctx, attribute, value));
}
EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface,
EGLint buffer) const {
WRAP(fBindTexImage(dpy, surface, buffer));
}
EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface,
EGLint buffer) const {
WRAP(fReleaseTexImage(dpy, surface, buffer));
}
EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const {
WRAP(fSwapInterval(dpy, interval));
}
EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer,
const EGLint* attrib_list) const {
WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list));
}
EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const {
WRAP(fDestroyImageKHR(dpy, image));
}
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));
}
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));
}
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));
}
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));
}
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));
}
// 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 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));
}
public:
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));
}
// 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));
}
// 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))
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
@ -380,54 +449,6 @@ class GLLibraryEGL final {
////
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 {
EGLCastToRelevantPtr(GLAPIENTRY* fGetProcAddress)(const char* procname);
@ -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 */

Просмотреть файл

@ -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;

Просмотреть файл

@ -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;
}
};
// -

Просмотреть файл

@ -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();

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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}) {}

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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',

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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;
}
}

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -75,19 +75,23 @@ 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,
egl->mLib->fQueryDeviceAttribEXT(eglDevice, LOCAL_EGL_D3D11_DEVICE_ANGLE,
(EGLAttrib*)&device);
if (!device) {
gfxCriticalNote << "Failed to get D3D11Device from EGLDisplay";
@ -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;
}
}

Просмотреть файл

@ -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,15 +118,17 @@ RenderedFrameId RenderCompositorEGL::EndFrame(
void RenderCompositorEGL::Pause() { DestroyEGLSurface(); }
bool RenderCompositorEGL::Resume() {
#ifdef MOZ_WIDGET_ANDROID
if (kIsAndroid) {
// Destroy EGLSurface if it exists.
DestroyEGLSurface();
mEGLSurface = CreateEGLSurface();
gl::GLContextEGL::Cast(gl())->SetEGLSurfaceOverride(mEGLSurface);
#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.
// 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 =
@ -134,7 +137,8 @@ bool RenderCompositorEGL::Resume() {
const int32_t height = ANativeWindow_getHeight(nativeWindow);
mEGLSurfaceSize = LayoutDeviceIntSize(width, height);
ANativeWindow_release(nativeWindow);
#elif defined(MOZ_WAYLAND)
#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();
@ -142,17 +146,17 @@ bool RenderCompositorEGL::Resume() {
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.
// 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);
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;
}
}

Просмотреть файл

@ -64,11 +64,10 @@ 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,
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.
@ -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,11 +364,10 @@ 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,
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.
@ -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,7 +517,7 @@ 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) {
@ -532,14 +526,15 @@ void RenderDXGIYCbCrTextureHostOGL::DeleteTextureHandle() {
mKeyedMutexs[i] = nullptr;
if (mSurfaces[i]) {
egl->fDestroySurface(egl->Display(), mSurfaces[i]);
egl->fDestroySurface(mSurfaces[i]);
mSurfaces[i] = 0;
}
if (mStreams[i]) {
egl->fDestroyStreamKHR(egl->Display(), mStreams[i]);
egl->fDestroyStreamKHR(mStreams[i]);
mStreams[i] = 0;
}
}
}
}
} // namespace wr

Просмотреть файл

@ -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;

Просмотреть файл

@ -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(

Просмотреть файл

@ -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',
]

Просмотреть файл

@ -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;
}
}