Initialize EGL
authorKristian Høgsberg <krh@bitplanet.net>
Thu, 14 Oct 2010 19:36:59 +0000 (15:36 -0400)
committerJørgen Lind <jorgen.lind@nokia.com>
Tue, 25 Jan 2011 17:54:39 +0000 (18:54 +0100)
src/plugins/platforms/wayland/qwaylandintegration.cpp
src/plugins/platforms/wayland/qwaylandintegration.h
src/plugins/platforms/wayland/wayland.pro

index a728f78..5882ad4 100644 (file)
@@ -1,13 +1,18 @@
+#include "qfontconfigdatabase.h"
+
 #include <QImageReader>
 #include <QWindowSystemInterface>
 #include <QPlatformCursor>
-#include "qwaylandintegration.h"
-#include "qwaylandwindowsurface.h"
-#include "qfontconfigdatabase.h"
+
+#include <QtGui/QPlatformGLContext>
+#include <QtGui/QPlatformWindowFormat>
 
 #include <QtGui/private/qpixmap_raster_p.h>
 #include <QtGui/QPlatformWindow>
 
+#include "qwaylandintegration.h"
+#include "qwaylandwindowsurface.h"
+
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -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<QWaylandWindow *>(this);
+        that->mGLContext = new QWaylandGLContext(mDisplay, widget()->platformWindowFormat());
+    }
+
+    return mGLContext;
+}
+
 QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const
 {
     Q_UNUSED(winId);
index 9f0b371..81819be 100644 (file)
 #include <wayland-client.h>
 #include "qwaylandinputdevice.h"
 
+#define MESA_EGL_NO_X11_HEADERS
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
 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<QPlatformScreen *> mScreens;
     QList<QWaylandInputDevice *> 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;
 };
 
index f5751e2..7a3d0b9 100644 (file)
@@ -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)