From: Jørgen Lind Date: Fri, 11 Mar 2011 11:42:58 +0000 (+0100) Subject: Add a dri2_xcb backend. This does not use the eglBindWaylandDisplayWL X-Git-Tag: qt-v5.0.0-alpha1~372 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b367c9f285cddbe8a438dcbacc72d6073ab604bd;p=profile%2Fivi%2Fqtwayland.git Add a dri2_xcb backend. This does not use the eglBindWaylandDisplayWL extension. So it can be considered an example of how make a Qt-Compositor without using eglBindWaylandDisplayWL but still using the drm protocol --- diff --git a/examples/qwidget-compositor/qt-compositor.pro b/examples/qwidget-compositor/qt-compositor.pro index 8e3e586..7126ed3 100644 --- a/examples/qwidget-compositor/qt-compositor.pro +++ b/examples/qwidget-compositor/qt-compositor.pro @@ -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 index 0000000..e99500d --- /dev/null +++ b/src/qt-compositor/dri2_xcb/README @@ -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 index 0000000..74d70a9 --- /dev/null +++ b/src/qt-compositor/dri2_xcb/dri2_xcb.pri @@ -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 index 0000000..c564b24 --- /dev/null +++ b/src/qt-compositor/dri2_xcb/dri2xcbbuffer.cpp @@ -0,0 +1,46 @@ +#include "dri2xcbbuffer.h" + +#include "wlobject.h" + +#define EGL_EGLEXT_PROTOTYPES +#include +#include + +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(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 index 0000000..23fb259 --- /dev/null +++ b/src/qt-compositor/dri2_xcb/dri2xcbbuffer.h @@ -0,0 +1,38 @@ +#ifndef DRI2XCBBUFFER_H +#define DRI2XCBBUFFER_H + +#include "wlobject.h" +#include "wlcompositor.h" + +#include + +#include +#include +#include +#include + +#define EGL_EGLEXT_PROTOTYPES +#include +#include + +class Dri2XcbBuffer : public Wayland::Object +{ +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 index 0000000..123ef28 --- /dev/null +++ b/src/qt-compositor/dri2_xcb/dri2xcbhwintegration.cpp @@ -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 + +#include +#include + +class DrmObject : public Wayland::Object +{ +public: + DrmObject(Wayland::Compositor *compositor, QWidget *topLevelWidget) + :m_compositor(compositor) + { + QPlatformNativeInterface *nativeInterface = QApplicationPrivate::platformIntegration()->nativeInterface(); + char *deviceName = static_cast(nativeInterface->nativeResourceForWidget("GraphicsDevice",topLevelWidget)); + m_device_name = QByteArray(deviceName); + + m_connection = static_cast(nativeInterface->nativeResourceForWidget("Connection",topLevelWidget)); + m_egl_display = static_cast(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(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(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(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(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 index 0000000..3fd5dfc --- /dev/null +++ b/src/qt-compositor/dri2_xcb/dri2xcbhwintegration.h @@ -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 diff --git a/src/qt-compositor/private/wlcompositor.cpp b/src/qt-compositor/private/wlcompositor.cpp index 91740d9..3d9652e 100644 --- a/src/qt-compositor/private/wlcompositor.cpp +++ b/src/qt-compositor/private/wlcompositor.cpp @@ -71,6 +71,10 @@ #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"); diff --git a/src/qt-compositor/qt-compositor.pri b/src/qt-compositor/qt-compositor.pri index 7aa2a49..19015fd 100644 --- a/src/qt-compositor/qt-compositor.pri +++ b/src/qt-compositor/qt-compositor.pri @@ -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