Qt 4.8
qdri2context.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qdri2context.h"
43 
44 #include "qxcbwindow.h"
45 #include "qxcbconnection.h"
46 
47 #include <QtCore/QDebug>
48 #include <QtGui/QWidget>
49 
50 #include <xcb/dri2.h>
51 #include <xcb/xfixes.h>
52 
53 #define MESA_EGL_NO_X11_HEADERS
54 #define EGL_EGLEXT_PROTOTYPES
55 #include <EGL/egl.h>
56 #include <EGL/eglext.h>
57 
58 #define GL_GLEXT_PROTOTYPES
59 #include <GLES2/gl2.h>
60 #include <GLES2/gl2ext.h>
61 
63 {
64 public:
66  : qXcbWindow(window)
67  , windowFormat(window->widget()->platformWindowFormat())
68  , image(0)
69  {
70  }
71 
72  xcb_window_t xcbWindow() { return qXcbWindow->window(); }
73  xcb_connection_t *xcbConnection() { return qXcbWindow->xcb_connection(); }
74 
77 
78  EGLContext eglContext;
79 
81 
82  GLuint fbo;
83  GLuint rbo;
84  GLuint depth;
85 
87 };
88 
90  : d_ptr(new QDri2ContextPrivate(window))
91 {
93 
94  static const EGLint contextAttribs[] = {
95  EGL_CONTEXT_CLIENT_VERSION, 2,
96  EGL_NONE
97  };
98 
99  eglBindAPI(EGL_OPENGL_ES_API);
100 
101  EGLContext shareContext = EGL_NO_CONTEXT;
102  if (window->widget()->platformWindowFormat().sharedGLContext()) {
103  QDri2Context *context = static_cast<QDri2Context *>(window->widget()->platformWindowFormat().sharedGLContext());
104  shareContext = context->d_func()->eglContext;
105  }
106  d->eglContext = eglCreateContext(EGL_DISPLAY_FROM_XCB(d->qXcbWindow), NULL,
107  shareContext, contextAttribs);
108 
109  if (d->eglContext == EGL_NO_CONTEXT) {
110  qDebug() << "No eglContext!" << eglGetError();
111  }
112 
113  EGLBoolean makeCurrentSuccess = eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,d->eglContext);
114  if (!makeCurrentSuccess) {
115  qDebug() << "eglMakeCurrent failed!" << eglGetError();
116  }
117 
118  xcb_dri2_create_drawable (d->xcbConnection(), d->xcbWindow());
119 
120  glGenFramebuffers(1,&d->fbo);
123 
124  glGenRenderbuffers(1, &d->rbo);
126 
127  glGenRenderbuffers(1,&d->depth);
129 
130  resize(d->qXcbWindow->widget()->geometry().size());
131 
135 
136  //restore the old current context
138  if (currentContext)
140 }
141 
143 {
144  //cleanup
145 }
146 
148 {
150  Q_D(QDri2Context);
151 
152  eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,d->eglContext);
154 
155 }
156 
158 {
160  Q_D(QDri2Context);
161  eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT);
162 }
163 
165 {
166  Q_D(QDri2Context);
167  xcb_rectangle_t rectangle;
168  rectangle.x = 0;
169  rectangle.y = 0;
170  rectangle.width = d->qXcbWindow->widget()->geometry().width();
171  rectangle.height = d->qXcbWindow->widget()->geometry().height();
172 
173  xcb_xfixes_region_t xfixesRegion = xcb_generate_id(d->xcbConnection());
174  xcb_xfixes_create_region(d->xcbConnection(), xfixesRegion,
175  1, &rectangle);
176 
177  xcb_dri2_copy_region_cookie_t cookie = xcb_dri2_copy_region_unchecked(d->xcbConnection(),
178  d->qXcbWindow->window(),
179  xfixesRegion,
180  XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT,
181  XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT);
182 
183  xcb_dri2_copy_region_reply_t *reply = xcb_dri2_copy_region_reply(d->xcbConnection(),cookie,NULL);
184 
185  //cleanup
186  delete reply;
187  xcb_xfixes_destroy_region(d->xcbConnection(), xfixesRegion);
188 
189 }
190 
191 void * QDri2Context::getProcAddress(const QString &procName)
192 {
193  return (void *)eglGetProcAddress(qPrintable(procName));
194 }
195 
196 void QDri2Context::resize(const QSize &size)
197 {
198  Q_D(QDri2Context);
199  d->size= size;
200 
202 
203  xcb_dri2_dri2_buffer_t *backBfr = backBuffer();
204 
205  if (d->image) {
206  qDebug() << "destroing image";
207  eglDestroyImageKHR(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),d->image);
208  }
209 
210  EGLint imgAttribs[] = {
211  EGL_WIDTH, d->size.width(),
212  EGL_HEIGHT, d->size.height(),
213  EGL_DRM_BUFFER_STRIDE_MESA, backBfr->pitch /4,
214  EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
215  EGL_NONE
216  };
217 
218  d->image = eglCreateImageKHR(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),
219  EGL_NO_CONTEXT,
220  EGL_DRM_BUFFER_MESA,
221  (EGLClientBuffer) backBfr->name,
222  imgAttribs);
223 
226  d->image);
227 
229  glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8_OES,d->size.width(), d->size.height());
230 
231 }
232 
234 {
235  Q_D(const QDri2Context);
236  return d->windowFormat;
237 }
238 
239 xcb_dri2_dri2_buffer_t * QDri2Context::backBuffer()
240 {
241  Q_D(QDri2Context);
242 
243  unsigned int backBufferAttachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT;
244  xcb_dri2_get_buffers_cookie_t cookie = xcb_dri2_get_buffers_unchecked (d->xcbConnection(),
245  d->xcbWindow(),
246  1, 1, &backBufferAttachment);
247 
248  xcb_dri2_get_buffers_reply_t *reply = xcb_dri2_get_buffers_reply (d->xcbConnection(), cookie, NULL);
249  if (!reply) {
250  qDebug() << "failed to get buffers reply";
251  return 0;
252  }
253 
254  xcb_dri2_dri2_buffer_t *buffers = xcb_dri2_get_buffers_buffers (reply);
255  if (!buffers) {
256  qDebug() << "failed to get buffers";
257  return 0;
258  }
259 
260  Q_ASSERT(reply->count == 1);
261 
262  delete reply;
263 
264  return buffers;
265 }
266 
268 {
269  Q_D(const QDri2Context);
270  return d->eglContext;
271 }
static const QPlatformGLContext * currentContext()
Returns the last context which called makeCurrent.
double d
Definition: qnumeric_p.h:62
QPointer< QWidget > widget
QDri2ContextPrivate(QXcbWindow *window)
virtual void doneCurrent()
Reimplement in subclass to release current context.
xcb_connection_t * xcb_connection() const
Definition: qxcbobject.h:56
#define glGenRenderbuffers
The QPlatformWindowFormat class specifies the display format of an OpenGL rendering context and if po...
The QString class provides a Unicode character string.
Definition: qstring.h:83
QPlatformWindowFormat platformWindowFormat() const
QWidget has the function qplatformWindowFormat().
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define glBindFramebuffer
#define Q_D(Class)
Definition: qglobal.h:2482
#define GL_RENDERBUFFER
#define GL_DEPTH_ATTACHMENT
Q_CORE_EXPORT void qDebug(const char *,...)
#define GL_TEXTURE0
Definition: glfunctions.h:61
NSWindow * window
xcb_window_t xcbWindow()
Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
Definition: qegl.cpp:638
void doneCurrent()
Reimplement in subclass to release current context.
#define glGenFramebuffers
void * EGLClientBuffer
Definition: qegl_p.h:70
void * eglContext() const
void makeCurrent()
Reimplement in subclass to do makeCurrent on native GL context.
virtual void makeCurrent()
Reimplement in subclass to do makeCurrent on native GL context.
#define GL_FRAMEBUFFER
void resize(const QSize &size)
#define glBindRenderbuffer
#define glActiveTexture
Definition: glfunctions.h:69
void * EGLImageKHR
Definition: qegl_p.h:165
QPlatformWindowFormat windowFormat
QXcbWindow * qXcbWindow
#define glEGLImageTargetRenderbufferStorageOES
The QPlatformGLContext class provides an abstraction for native GL contexts.
void swapBuffers()
Reimplement in subclass to native swap buffers calls.
xcb_window_t window() const
Definition: qxcbwindow.h:77
QDri2Context(QXcbWindow *window)
#define GL_RENDERER
#define GL_STENCIL_ATTACHMENT
#define GL_COLOR_ATTACHMENT0
#define glFramebufferRenderbuffer
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
Definition: qegl.cpp:625
void * getProcAddress(const QString &procName)
Reimplement in subclass to native getProcAddr calls.
xcb_connection_t * xcbConnection()
#define qPrintable(string)
Definition: qglobal.h:1750
#define glRenderbufferStorage
xcb_dri2_dri2_buffer_t * backBuffer()
QWidget * widget() const
Returnes the widget which belongs to the QPlatformWindow.