From bf009b6d9aa7e87914087adb3772dc071cef455c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 14 Oct 2010 15:36:59 -0400 Subject: [PATCH] Initialize EGL --- .../platforms/wayland/qwaylandintegration.cpp | 161 +++++++++++++++++---- .../platforms/wayland/qwaylandintegration.h | 10 +- src/plugins/platforms/wayland/wayland.pro | 2 +- 3 files changed, 142 insertions(+), 31 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index a728f78..5882ad4 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -1,13 +1,18 @@ +#include "qfontconfigdatabase.h" + #include #include #include -#include "qwaylandintegration.h" -#include "qwaylandwindowsurface.h" -#include "qfontconfigdatabase.h" + +#include +#include #include #include +#include "qwaylandintegration.h" +#include "qwaylandwindowsurface.h" + #include #include @@ -182,16 +187,50 @@ void QWaylandDisplay::drmHandleDevice(void *data, { Q_UNUSED(drm); QWaylandDisplay *qwd = (QWaylandDisplay *) data; + drm_magic_t magic; qwd->mDeviceName = strdup(device); + + qwd->mFd = open(qwd->mDeviceName, O_RDWR); + if (qwd->mFd < 0) { + qWarning("drm open failed: %m"); + return; + } + + if (drmGetMagic(qwd->mFd, &magic)) { + qWarning("DRI2: failed to get drm magic"); + return; + } + + wl_drm_authenticate(qwd->mDrm, magic); } void QWaylandDisplay::drmHandleAuthenticated(void *data, struct wl_drm *drm) { Q_UNUSED(drm); QWaylandDisplay *qwd = (QWaylandDisplay *) data; + EGLint major, minor; + const char *extensions; + + qwd->mEglDisplay = eglGetDRMDisplayMESA(qwd->mFd); + if (qwd->mEglDisplay == NULL) { + qWarning("failed to create display"); + return; + } + + if (!eglInitialize(qwd->mEglDisplay, &major, &minor)) { + qWarning("failed to initialize display"); + qwd->mEglDisplay = NULL; + return; + } - qwd->mAuthenticated = true; + extensions = eglQueryString(qwd->mEglDisplay, EGL_EXTENSIONS); + if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) { + qWarning("EGL_KHR_surfaceless_opengles2 not available"); + eglTerminate(qwd->mEglDisplay); + qwd->mEglDisplay = NULL; + return; + } } const struct wl_drm_listener QWaylandDisplay::drmListener = { @@ -265,13 +304,24 @@ void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, } } -static void initial_roundtrip(void *data) +static void roundtripCallback(void *data) { bool *done = (bool *) data; *done = true; } +static void forceRoundtrip(struct wl_display *display) +{ + bool done; + + wl_display_sync_callback(display, roundtripCallback, &done); + wl_display_iterate(display, WL_DISPLAY_WRITABLE); + done = false; + while (!done) + wl_display_iterate(display, WL_DISPLAY_READABLE); +} + static const char socket_name[] = "\0wayland"; void QWaylandDisplay::eventDispatcher(void) @@ -304,9 +354,6 @@ void QWaylandDisplay::flushRequests(void) QWaylandDisplay::QWaylandDisplay(void) : mWriteNotifier(0) { - drm_magic_t magic; - bool done; - mDisplay = wl_display_create(socket_name, sizeof socket_name); if (mDisplay == NULL) { fprintf(stderr, "failed to create display: %m\n"); @@ -317,28 +364,17 @@ QWaylandDisplay::QWaylandDisplay(void) QWaylandDisplay::displayHandleGlobal, this); /* Process connection events. */ - wl_display_sync_callback(mDisplay, initial_roundtrip, &done); - wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); - done = false; - while (!done) - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); - - mFd = open(mDeviceName, O_RDWR); - if (mFd < 0) { - qWarning("drm open failed: %m\n"); - return; - } - - if (drmGetMagic(mFd, &magic)) { - qWarning("DRI2: failed to get drm magic"); - return; - } + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + if (!mShm || !mDeviceName) + forceRoundtrip(mDisplay); - /* Wait for authenticated event */ - wl_drm_authenticate(mDrm, magic); - wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); - while (!mAuthenticated) - wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); + /* Force a roundtrip to finish the drm authentication so we + * initialize EGL before proceeding */ + forceRoundtrip(mDisplay); + if (mEglDisplay == NULL) + qWarning("EGL not available"); + else + qWarning("EGL initialized"); int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); @@ -417,6 +453,73 @@ void QWaylandWindow::configure(uint32_t time, uint32_t edges, QWindowSystemInterface::handleGeometryChange(widget(), geometry); } +class QWaylandGLContext : public QPlatformGLContext { +public: + QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); + ~QWaylandGLContext(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString&); + QPlatformWindowFormat platformWindowFormat() const { return mFormat; } + +private: + EGLContext mContext; + QPlatformWindowFormat mFormat; + QWaylandDisplay *mDisplay; +}; + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , mContext(0) + , mFormat(format) + , mDisplay(wd) +{ + EGLDisplay eglDisplay; + static const EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + eglBindAPI(EGL_OPENGL_ES_API); + eglDisplay = mDisplay->eglDisplay(); + mContext = eglCreateContext(eglDisplay, NULL, + EGL_NO_CONTEXT, contextAttribs); +} + +QWaylandGLContext::~QWaylandGLContext() +{ + if (mContext) + eglDestroyContext(mDisplay->eglDisplay(), mContext); +} + +void QWaylandGLContext::makeCurrent() +{ +} + +void QWaylandGLContext::doneCurrent() +{ +} + +void QWaylandGLContext::swapBuffers() +{ +} + +void *QWaylandGLContext::getProcAddress(const QString &string) +{ + return (void *) eglGetProcAddress(string.toLatin1().data()); +} + +QPlatformGLContext *QWaylandWindow::glContext() const +{ + if (!mGLContext) { + QWaylandWindow *that = const_cast(this); + that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat()); + } + + return mGLContext; +} + QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const { Q_UNUSED(winId); diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index 9f0b371..81819be 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -50,6 +50,11 @@ #include #include "qwaylandinputdevice.h" +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include +#include + QT_BEGIN_NAMESPACE class QWaylandBuffer; @@ -67,6 +72,7 @@ public: uint32_t stride, struct wl_visual *visual); struct wl_visual *argbVisual(); + EGLDisplay eglDisplay() { return mEglDisplay; } void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); @@ -82,11 +88,11 @@ private: struct wl_shell *mShell; char *mDeviceName; int mFd; - bool mAuthenticated; QList mScreens; QList mInputDevices; QSocketNotifier *mReadNotifier; QSocketNotifier *mWriteNotifier; + EGLDisplay mEglDisplay; static void displayHandleGlobal(struct wl_display *display, uint32_t id, @@ -143,10 +149,12 @@ public: void configure(uint32_t time, uint32_t edges, int32_t x, int32_t y, int32_t width, int32_t height); WId winId() const; + QPlatformGLContext *glContext() const; private: struct wl_surface *mSurface; QWaylandDisplay *mDisplay; + QPlatformGLContext *mGLContext; WId mWindowId; }; diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro index f5751e2..7a3d0b9 100644 --- a/src/plugins/platforms/wayland/wayland.pro +++ b/src/plugins/platforms/wayland/wayland.pro @@ -12,7 +12,7 @@ HEADERS = qwaylandintegration.h \ qwaylandwindowsurface.h INCLUDEPATH += /usr/include/libdrm -LIBS += -lwayland-client -ldrm -lxkbcommon +LIBS += -lwayland-client -ldrm -lxkbcommon -lEGL -lGLESv2 include (../fontdatabases/fontconfig/fontconfig.pri) -- 2.7.4