1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the Qt Compositor.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
20 ** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
21 ** the names of its contributors may be used to endorse or promote
22 ** products derived from this software without specific prior written
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
41 #include "waylandeglintegration.h"
42 #include "wayland_wrapper/wlcompositor.h"
43 #include "wayland_wrapper/wlsurface.h"
44 #include "compositor_api/waylandsurface.h"
45 #include <qpa/qplatformnativeinterface.h>
46 #include <QtGui/QGuiApplication>
47 #include <QtGui/QOpenGLContext>
48 #include <qpa/qplatformscreen.h>
49 #include <QtGui/QWindow>
50 #include <QtCore/QPointer>
55 #include <EGL/eglext.h>
57 #include <GLES2/gl2.h>
58 #include <GLES2/gl2ext.h>
61 GraphicsHardwareIntegration * GraphicsHardwareIntegration::createGraphicsHardwareIntegration(WaylandCompositor *compositor)
63 return new WaylandEglIntegration(compositor);
66 #ifndef EGL_WL_bind_wayland_display
67 typedef EGLBoolean (EGLAPIENTRYP PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
68 typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay dpy, struct wl_display *display);
72 typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
73 typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image);
76 #ifndef GL_OES_EGL_image
77 typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
78 typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
81 class WaylandEglIntegrationPrivate
84 WaylandEglIntegrationPrivate()
85 : egl_display(EGL_NO_DISPLAY)
87 , flipperConnected(false)
88 , egl_bind_wayland_display(0)
89 , egl_unbind_wayland_display(0)
91 , egl_destroy_image(0)
92 , gl_egl_image_target_texture_2d(0)
94 EGLDisplay egl_display;
96 bool flipperConnected;
97 #ifdef EGL_WL_request_client_buffer_format
98 QPointer<WaylandSurface> directRenderSurface;
100 PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display;
101 PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display;
103 PFNEGLCREATEIMAGEKHRPROC egl_create_image;
104 PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image;
106 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d;
108 QPlatformNativeInterface::NativeResourceForContextFunction get_egl_context;
111 WaylandEglIntegration::WaylandEglIntegration(WaylandCompositor *compositor)
112 : GraphicsHardwareIntegration(compositor)
113 , d_ptr(new WaylandEglIntegrationPrivate)
117 void WaylandEglIntegration::initializeHardware(Wayland::Display *waylandDisplay)
119 Q_D(WaylandEglIntegration);
121 QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
122 if (nativeInterface) {
123 d->egl_display = nativeInterface->nativeResourceForWindow("EglDisplay", m_compositor->window());
124 if (d->egl_display) {
125 const char *extensionString = eglQueryString(d->egl_display, EGL_EXTENSIONS);
126 if (extensionString && strstr(extensionString, "EGL_WL_bind_wayland_display"))
128 d->get_egl_context = nativeInterface->nativeResourceFunctionForContext("get_egl_context");
129 if (!d->get_egl_context) {
130 qWarning("Failed to retrieve the get_egl_context function");
132 d->egl_bind_wayland_display =
133 reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL"));
134 d->egl_unbind_wayland_display =
135 reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL"));
136 d->egl_create_image =
137 reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
138 d->egl_destroy_image =
139 reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
140 d->gl_egl_image_target_texture_2d =
141 reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
143 if (d->egl_bind_wayland_display
144 && d->get_egl_context
145 && d->egl_unbind_wayland_display
146 && d->egl_create_image
147 && d->egl_destroy_image
148 && d->gl_egl_image_target_texture_2d) {
149 if (d->egl_bind_wayland_display(d->egl_display, waylandDisplay->handle())) {
157 qWarning("Failed to initialize egl display\n");
161 GLuint WaylandEglIntegration::createTextureFromBuffer(wl_buffer *buffer, QOpenGLContext *context)
163 Q_D(WaylandEglIntegration);
165 qWarning("createTextureFromBuffer() failed\n");
169 QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
170 EGLContext egl_context = d->get_egl_context(context);
172 EGLImageKHR image = d->egl_create_image(d->egl_display, egl_context,
173 EGL_WAYLAND_BUFFER_WL,
177 glGenTextures(1,&textureId);
179 glBindTexture(GL_TEXTURE_2D, textureId);
181 d->gl_egl_image_target_texture_2d(GL_TEXTURE_2D, image);
183 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
184 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
185 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
186 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
188 d->egl_destroy_image(d->egl_display, image);
193 bool WaylandEglIntegration::isYInverted(struct wl_buffer *buffer) const
195 #ifdef EGL_WL_request_client_buffer_format
196 return eglGetBufferYInvertedWL(buffer);
198 return GraphicsHardwareIntegration::isYInverted(buffer);
203 bool WaylandEglIntegration::setDirectRenderSurface(WaylandSurface *surface)
205 Q_D(WaylandEglIntegration);
207 QPlatformScreen *screen = QPlatformScreen::platformScreenForWindow(m_compositor->window());
208 QPlatformScreenPageFlipper *flipper = screen ? screen->pageFlipper() : 0;
209 if (flipper && !d->flipperConnected) {
210 QObject::connect(flipper, SIGNAL(bufferReleased(void*)), m_compositor->handle(), SLOT(releaseBuffer(void*)));
211 d->flipperConnected = true;
213 #ifdef EGL_WL_request_client_buffer_format
214 int buffer_format = surface ? EGL_SCANOUT_FORMAT_WL : EGL_RENDER_FORMAT_WL;
215 struct wl_client *client = 0;
217 client = surface->handle()->base()->resource.client;
219 WaylandSurface *oldSurface = d->directRenderSurface.data();
221 client = oldSurface->handle()->base()->resource.client;
224 eglRequestClientBufferFormatWL(d->egl_display, client, buffer_format);
225 d->directRenderSurface = surface;
232 void *WaylandEglIntegration::lockNativeBuffer(struct wl_buffer *buffer, QOpenGLContext *context) const
234 Q_D(const WaylandEglIntegration);
236 QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
237 EGLContext egl_context = d->get_egl_context(context);
239 EGLImageKHR image = d->egl_create_image(d->egl_display, egl_context,
240 EGL_WAYLAND_BUFFER_WL,
245 void WaylandEglIntegration::unlockNativeBuffer(void *native_buffer, QOpenGLContext *) const
247 Q_D(const WaylandEglIntegration);
248 EGLImageKHR image = static_cast<EGLImageKHR>(native_buffer);
250 d->egl_destroy_image(d->egl_display, image);