Add a dri2_xcb backend. This does not use the eglBindWaylandDisplayWL
authorJørgen Lind <jorgen.lind@nokia.com>
Fri, 11 Mar 2011 11:42:58 +0000 (12:42 +0100)
committerJørgen Lind <jorgen.lind@nokia.com>
Fri, 11 Mar 2011 11:42:58 +0000 (12:42 +0100)
extension. So it can be considered an example of how make a
Qt-Compositor without using eglBindWaylandDisplayWL but still using the
drm protocol

examples/qwidget-compositor/qt-compositor.pro
src/qt-compositor/dri2_xcb/README [new file with mode: 0644]
src/qt-compositor/dri2_xcb/dri2_xcb.pri [new file with mode: 0644]
src/qt-compositor/dri2_xcb/dri2xcbbuffer.cpp [new file with mode: 0644]
src/qt-compositor/dri2_xcb/dri2xcbbuffer.h [new file with mode: 0644]
src/qt-compositor/dri2_xcb/dri2xcbhwintegration.cpp [new file with mode: 0644]
src/qt-compositor/dri2_xcb/dri2xcbhwintegration.h [new file with mode: 0644]
src/qt-compositor/private/wlcompositor.cpp
src/qt-compositor/qt-compositor.pri

index 8e3e586..7126ed3 100644 (file)
@@ -7,6 +7,7 @@ INCLUDEPATH += ../../src/qt-compositor/
 # comment out the following CONFIG lines to disable DRM
 CONFIG += wayland_gl
 CONFIG += mesa_egl
+#CONFIG += dri2_xcb
 
 # comment out the following to not use pkg-config in the pri files
 CONFIG += use_pkgconfig
diff --git a/src/qt-compositor/dri2_xcb/README b/src/qt-compositor/dri2_xcb/README
new file mode 100644 (file)
index 0000000..e99500d
--- /dev/null
@@ -0,0 +1,3 @@
+This backend requires that you compile the xcb lighthouse plugin with the
+defined: XCB_USE_DRI2. Please see in the xcb.pro file for an easy way to
+enable it.
diff --git a/src/qt-compositor/dri2_xcb/dri2_xcb.pri b/src/qt-compositor/dri2_xcb/dri2_xcb.pri
new file mode 100644 (file)
index 0000000..74d70a9
--- /dev/null
@@ -0,0 +1,12 @@
+INCLUDEPATH += $$PWD/../private
+LIBS += -lxcb -lxcb-dri2 -lEGL
+
+SOURCES += \
+    $$PWD/dri2xcbhwintegration.cpp \
+    $$PWD/dri2xcbbuffer.cpp \
+    $$PWD/../../3rdparty/wayland/wayland-drm-protocol.c \
+
+HEADERS += \
+    $$PWD/dri2xcbhwintegration.h \
+    $$PWD/dri2xcbbuffer.h \
+    $$PWD/../../3rdparty/wayland/wayland-drm-server-protocol.h \
diff --git a/src/qt-compositor/dri2_xcb/dri2xcbbuffer.cpp b/src/qt-compositor/dri2_xcb/dri2xcbbuffer.cpp
new file mode 100644 (file)
index 0000000..c564b24
--- /dev/null
@@ -0,0 +1,46 @@
+#include "dri2xcbbuffer.h"
+
+#include "wlobject.h"
+
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+Dri2XcbBuffer::Dri2XcbBuffer(uint32_t id, uint32_t name, const QSize &size, uint32_t stride, wl_visual *visual, EGLDisplay eglDisplay, Wayland::Compositor *compositor)
+    :m_egl_display(eglDisplay)
+{
+    base()->compositor = compositor->base();
+    base()->visual = visual;
+    base()->height = size.height();
+    base()->width = size.width();
+    base()->attach = 0;
+    base()->damage = 0;
+
+    EGLint attribs[] = {
+        EGL_WIDTH,                      size.width(),
+        EGL_HEIGHT,                     size.height(),
+        EGL_DRM_BUFFER_STRIDE_MESA,     stride /4,
+        EGL_DRM_BUFFER_FORMAT_MESA,     EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
+        EGL_NONE
+    };
+
+    m_image = eglCreateImageKHR(m_egl_display,
+                              EGL_NO_CONTEXT,
+                              EGL_DRM_BUFFER_MESA,
+                              (EGLClientBuffer) name, attribs);
+}
+
+Dri2XcbBuffer::~Dri2XcbBuffer()
+{
+    eglDestroyImageKHR (m_egl_display, m_image);
+}
+
+void dri2XcbBufferDestroy(struct wl_client *client, struct wl_buffer *buffer)
+{
+    delete Wayland::wayland_cast<Dri2XcbBuffer *>(buffer);
+}
+
+EGLImageKHR Dri2XcbBuffer::image() const
+{
+    return m_image;
+}
diff --git a/src/qt-compositor/dri2_xcb/dri2xcbbuffer.h b/src/qt-compositor/dri2_xcb/dri2xcbbuffer.h
new file mode 100644 (file)
index 0000000..23fb259
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef DRI2XCBBUFFER_H
+#define DRI2XCBBUFFER_H
+
+#include "wlobject.h"
+#include "wlcompositor.h"
+
+#include <wayland-server.h>
+
+#include <QtCore/QSize>
+#include <QtCore/QTextStream>
+#include <QtGui/private/qapplication_p.h>
+#include <QtGui/QPlatformNativeInterface>
+
+#define EGL_EGLEXT_PROTOTYPES
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+class Dri2XcbBuffer : public Wayland::Object<struct wl_buffer>
+{
+public:
+    Dri2XcbBuffer(uint32_t id, uint32_t name, const QSize &size, uint32_t stride,
+                  wl_visual *visual, EGLDisplay eglDisplay, Wayland::Compositor *compositor);
+    ~Dri2XcbBuffer();
+
+    EGLImageKHR image() const;
+
+private:
+    EGLImageKHR m_image;
+    EGLDisplay m_egl_display;
+};
+
+void dri2XcbBufferDestroy(struct wl_client *client, struct wl_buffer *buffer);
+
+const static struct wl_buffer_interface dri2_xcb_buffer_interface = {
+    dri2XcbBufferDestroy
+};
+
+#endif // DRI2XCBBUFFER_H
diff --git a/src/qt-compositor/dri2_xcb/dri2xcbhwintegration.cpp b/src/qt-compositor/dri2_xcb/dri2xcbhwintegration.cpp
new file mode 100644 (file)
index 0000000..123ef28
--- /dev/null
@@ -0,0 +1,121 @@
+#include "dri2xcbhwintegration.h"
+
+#include "dri2xcbbuffer.h"
+
+#include "wlobject.h"
+#include "wldisplay.h"
+#include "wlcompositor.h"
+
+#include "wayland-server.h"
+#include "wayland-drm-server-protocol.h"
+
+#include <QtCore/QDebug>
+
+#include <xcb/xcb.h>
+#include <xcb/dri2.h>
+
+class DrmObject : public Wayland::Object<struct wl_object>
+{
+public:
+    DrmObject(Wayland::Compositor *compositor, QWidget *topLevelWidget)
+        :m_compositor(compositor)
+    {
+        QPlatformNativeInterface *nativeInterface = QApplicationPrivate::platformIntegration()->nativeInterface();
+        char *deviceName = static_cast<char *>(nativeInterface->nativeResourceForWidget("GraphicsDevice",topLevelWidget));
+        m_device_name = QByteArray(deviceName);
+
+        m_connection = static_cast<xcb_connection_t *>(nativeInterface->nativeResourceForWidget("Connection",topLevelWidget));
+        m_egl_display = static_cast<EGLDisplay>(nativeInterface->nativeResourceForWidget("EglDisplay",topLevelWidget));
+    }
+    QByteArray deviceName()
+    {
+        return m_device_name;
+    }
+
+    void authenticate(struct wl_client *client, uint32_t id)
+    {
+
+        xcb_screen_iterator_t screenIterator = xcb_setup_roots_iterator(xcb_get_setup(m_connection));
+        xcb_dri2_authenticate_cookie_t authenticateCoockie = xcb_dri2_authenticate_unchecked(m_connection,screenIterator.data->root,id);
+        xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection,authenticateCoockie,NULL);
+
+        if (authenticate && authenticate->authenticated) {
+            wl_client_post_event(client, base(), WL_DRM_AUTHENTICATED);
+        } else {
+            qDebug() << "Failed to authenticate drm :(";
+        }
+
+        delete authenticate;
+    }
+
+    void createBuffer(wl_client *client, uint32_t id, uint32_t name, const QSize &size, uint32_t stride, wl_visual *visual)
+    {
+        Dri2XcbBuffer *buffer = new Dri2XcbBuffer(id,name,size,stride,visual,m_egl_display, m_compositor);
+        Wayland::addClientResource(client,&buffer->base()->resource,id,&wl_buffer_interface,&dri2_xcb_buffer_interface,0);
+    }
+
+private:
+    QByteArray m_device_name;
+    xcb_connection_t *m_connection;
+    xcb_screen_t *m_screen;
+    EGLDisplay m_egl_display;
+    Wayland::Compositor *m_compositor;
+};
+
+void authenticate(struct wl_client *client,
+                     struct wl_drm *drm,
+                     uint32_t id)
+{
+    reinterpret_cast<DrmObject *>(drm)->authenticate(client,id);
+}
+
+void create_buffer(struct wl_client *client,
+                      struct wl_drm *drm,
+                      uint32_t id,
+                      uint32_t name,
+                      int width,
+                      int height,
+                      uint32_t stride,
+                      struct wl_visual *visual)
+{
+    DrmObject *drmObject = reinterpret_cast<DrmObject *>(drm);
+    drmObject->createBuffer(client,id,name,QSize(width,height),stride,visual);
+}
+
+const static struct wl_drm_interface drm_interface = {
+        authenticate,
+        create_buffer
+};
+
+void post_drm_device(struct wl_client *client, struct wl_object *global)
+{
+    DrmObject *drmObject = Wayland::wayland_cast<DrmObject *>(global);
+    qDebug() << drmObject->deviceName().constData();
+    wl_client_post_event(client, global, WL_DRM_DEVICE, drmObject->deviceName().constData());
+}
+
+Dri2XcbHWIntegration::Dri2XcbHWIntegration(WaylandCompositor *compositor)
+    : GraphicsHardwareIntegration(compositor)
+    , m_drm_object(0)
+{
+}
+
+void Dri2XcbHWIntegration::initializeHardware(Wayland::Display *waylandDisplay)
+{
+    //we need a winId now.
+    m_compositor->topLevelWidget()->winId();
+
+
+    m_drm_object = new DrmObject(m_compositor->handle(),m_compositor->topLevelWidget());
+
+    waylandDisplay->addGlobalObject(m_drm_object->base(),&wl_drm_interface,&drm_interface,post_drm_device);
+}
+
+void Dri2XcbHWIntegration::bindBufferToTexture(wl_buffer *buffer, GLuint textureId)
+{
+    Dri2XcbBuffer *dri2Buffer = Wayland::wayland_cast<Dri2XcbBuffer *>(buffer);
+
+    glBindTexture(GL_TEXTURE_2D, textureId);
+
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, dri2Buffer->image());
+}
diff --git a/src/qt-compositor/dri2_xcb/dri2xcbhwintegration.h b/src/qt-compositor/dri2_xcb/dri2xcbhwintegration.h
new file mode 100644 (file)
index 0000000..3fd5dfc
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef DRI2XCBHWINTEGRATION_H
+#define DRI2XCBHWINTEGRATION_H
+
+#include "../graphicshardwareintegration.h"
+
+class DrmObject;
+
+class Dri2XcbHWIntegration : public GraphicsHardwareIntegration
+{
+public:
+    Dri2XcbHWIntegration(WaylandCompositor *compositor);
+
+    void initializeHardware(Wayland::Display *waylandDisplay);
+
+    void bindBufferToTexture(wl_buffer *buffer, GLuint textureId);
+
+private:
+    DrmObject *m_drm_object;
+};
+
+#endif // DRI2XCBHWINTEGRATION_H
index 91740d9..3d9652e 100644 (file)
 #include "../mesa_egl/mesaeglintegration.h"
 #endif
 
+#ifdef QT_COMPOSITOR_DRI2_XCB
+#include "../dri2_xcb/dri2xcbhwintegration.h"
+#endif
+
 namespace Wayland {
 
 void input_device_attach(struct wl_client *client,
@@ -176,6 +180,9 @@ Compositor::Compositor(WaylandCompositor *qt_compositor)
 #ifdef QT_COMPOSITOR_MESA_EGL
     m_graphics_hw_integration = new MesaEglIntegration(qt_compositor);
 #endif
+#ifdef QT_COMPOSITOR_DRI2_XCB
+    m_graphics_hw_integration = new Dri2XcbHWIntegration(qt_compositor);
+#endif
 
     if (wl_compositor_init(base(), &compositor_interface, m_display->handle())) {
         fprintf(stderr, "Fatal: Error initializing compositor\n");
index 7aa2a49..19015fd 100644 (file)
@@ -10,6 +10,11 @@ include (mesa_egl/mesa_egl.pri)
 DEFINES += QT_COMPOSITOR_MESA_EGL
 }
 
+dri2_xcb {
+include (dri2_xcb/dri2_xcb.pri)
+DEFINES += QT_COMPOSITOR_DRI2_XCB
+}
+
 use_pkgconfig {
     QMAKE_CXXFLAGS += $$system(pkg-config --cflags glesv2)
     #for some reason this is not included in the cflags line