зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
953004415b
Коммит
b5d6906473
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче