mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Bug 1462642 - [Wayland/EGL] Use dummy wl_egl_window instead of PBuffer, r=lsalzman
Wayland on desktop does not support/implement PBuffer. As a workaround we create a dummy wl_egl_window instead and render to it. As a side effect we need to store and release this wl_egl_window along the associated EGLSurface on Wayland. MozReview-Commit-ID: 1NlzZsOzXz9 --HG-- extra : rebase_source : 13f776ad0a9079f7155ba523b61f93441bf7fd5f
This commit is contained in:
parent
b30577d5b8
commit
0d7519b550
@ -134,6 +134,10 @@ protected:
|
||||
static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
|
||||
EGLenum bindToTextureFormat,
|
||||
gfx::IntSize& pbsize);
|
||||
#if defined(MOZ_WAYLAND)
|
||||
static EGLSurface CreateWaylandBufferSurface(EGLConfig config,
|
||||
gfx::IntSize& pbsize);
|
||||
#endif
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
public:
|
||||
EGLSurface CreateCompatibleSurface(void* aWindow);
|
||||
|
@ -63,6 +63,17 @@
|
||||
#include "ScopedGLHelpers.h"
|
||||
#include "TextureImageEGL.h"
|
||||
|
||||
#if defined(MOZ_WAYLAND)
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsDataHashtable.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gdk/gdkwayland.h>
|
||||
#include <wayland-egl.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
namespace mozilla {
|
||||
@ -70,6 +81,35 @@ namespace gl {
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
#if defined(MOZ_WAYLAND)
|
||||
class WaylandGLSurface {
|
||||
public:
|
||||
WaylandGLSurface(struct wl_surface *aWaylandSurface,
|
||||
struct wl_egl_window *aEGLWindow);
|
||||
~WaylandGLSurface();
|
||||
private:
|
||||
struct wl_surface *mWaylandSurface;
|
||||
struct wl_egl_window *mEGLWindow;
|
||||
};
|
||||
|
||||
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 (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
||||
auto entry = sWaylandGLSurface.Lookup(surface);
|
||||
if (entry) {
|
||||
delete entry.Data();
|
||||
entry.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ADD_ATTR_2(_array, _k, _v) do { \
|
||||
(_array).AppendElement(_k); \
|
||||
(_array).AppendElement(_v); \
|
||||
@ -125,6 +165,9 @@ DestroySurface(EGLSurface oldSurface) {
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
sEGLLibrary.fDestroySurface(EGL_DISPLAY(), oldSurface);
|
||||
#if defined(MOZ_WAYLAND)
|
||||
DeleteWaylandGLSurface(oldSurface);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,6 +665,52 @@ TRY_AGAIN_POWER_OF_TWO:
|
||||
return surface;
|
||||
}
|
||||
|
||||
#if defined(MOZ_WAYLAND)
|
||||
WaylandGLSurface::WaylandGLSurface(struct wl_surface *aWaylandSurface,
|
||||
struct wl_egl_window *aEGLWindow)
|
||||
: mWaylandSurface(aWaylandSurface)
|
||||
, mEGLWindow(aEGLWindow)
|
||||
{
|
||||
}
|
||||
|
||||
WaylandGLSurface::~WaylandGLSurface()
|
||||
{
|
||||
wl_egl_window_destroy(mEGLWindow);
|
||||
wl_surface_destroy(mWaylandSurface);
|
||||
}
|
||||
|
||||
EGLSurface
|
||||
GLContextEGL::CreateWaylandBufferSurface(EGLConfig config,
|
||||
mozilla::gfx::IntSize& pbsize)
|
||||
{
|
||||
// Available as of GTK 3.8+
|
||||
static auto sGdkWaylandDisplayGetWlCompositor =
|
||||
(wl_compositor *(*)(GdkDisplay *))
|
||||
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor");
|
||||
|
||||
if (!sGdkWaylandDisplayGetWlCompositor)
|
||||
return nullptr;
|
||||
|
||||
struct wl_compositor *compositor =
|
||||
sGdkWaylandDisplayGetWlCompositor(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 =
|
||||
sEGLLibrary.fCreateWindowSurface(EGL_DISPLAY(), config, eglwindow, 0);
|
||||
|
||||
if (surface) {
|
||||
WaylandGLSurface* waylandData =
|
||||
new WaylandGLSurface(wlsurface, eglwindow);
|
||||
auto entry = sWaylandGLSurface.LookupForAdd(surface);
|
||||
entry.OrInsert([&waylandData](){ return waylandData; });
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
@ -841,7 +930,17 @@ FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
|
||||
bool es3, nsTArray<EGLint>* out)
|
||||
{
|
||||
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
|
||||
#if defined(MOZ_WAYLAND)
|
||||
if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
||||
// 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
|
||||
|
||||
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
|
||||
if (es3) {
|
||||
@ -960,9 +1059,17 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
|
||||
}
|
||||
|
||||
mozilla::gfx::IntSize pbSize(size);
|
||||
EGLSurface surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
|
||||
LOCAL_EGL_NONE,
|
||||
pbSize);
|
||||
EGLSurface surface = nullptr;
|
||||
#if defined(MOZ_WAYLAND)
|
||||
if (GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default())) {
|
||||
surface = GLContextEGL::CreateWaylandBufferSurface(config, pbSize);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
surface = GLContextEGL::CreatePBufferSurfaceTryingPowerOfTwo(config,
|
||||
LOCAL_EGL_NONE,
|
||||
pbSize);
|
||||
}
|
||||
if (!surface) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_POT");
|
||||
NS_WARNING("Failed to create PBuffer for context!");
|
||||
@ -975,6 +1082,9 @@ GLContextEGL::CreateEGLPBufferOffscreenContext(CreateContextFlags flags,
|
||||
if (!gl) {
|
||||
NS_WARNING("Failed to create GLContext from PBuffer");
|
||||
sEGLLibrary.fDestroySurface(sEGLLibrary.Display(), surface);
|
||||
#if defined(MOZ_WAYLAND)
|
||||
DeleteWaylandGLSurface(surface);
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user