Qt 4.8
qpixmapdata_x11gl_egl.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 QtOpenGL module 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 <QDebug>
43 
44 #include <QtGui/private/qt_x11_p.h>
45 #include <QtGui/private/qegl_p.h>
46 #include <QtGui/private/qeglproperties_p.h>
47 #include <QtGui/private/qeglcontext_p.h>
48 
49 #if !defined(QT_OPENGL_ES_1)
50 #include <QtOpenGL/private/qpaintengineex_opengl2_p.h>
51 #endif
52 
53 #ifndef QT_OPENGL_ES_2
54 #include <QtOpenGL/private/qpaintengine_opengl_p.h>
55 #endif
56 
57 #include <QtOpenGL/private/qgl_p.h>
58 #include <QtOpenGL/private/qgl_egl_p.h>
59 
60 #include "qpixmapdata_x11gl_p.h"
61 
63 
64 
66 {
67 public:
69  : rgbContext(0)
70  , argbContext(0)
71  , sharedQGLContext(0)
72  , sharePixmap(0)
73  {
74  EGLint rgbConfigId;
75  EGLint argbConfigId;
76 
77  do {
79  EGLConfig argbConfig = QEgl::defaultConfig(QInternal::Pixmap, QEgl::OpenGL,
81 
82  eglGetConfigAttrib(QEgl::display(), rgbConfig, EGL_CONFIG_ID, &rgbConfigId);
83  eglGetConfigAttrib(QEgl::display(), argbConfig, EGL_CONFIG_ID, &argbConfigId);
84 
85  rgbContext = new QEglContext;
86  rgbContext->setConfig(rgbConfig);
88 
89  if (!rgbContext->isValid())
90  break;
91 
92  // If the RGB & ARGB configs are the same, use the same egl context for both:
93  if (rgbConfig == argbConfig)
95 
96  // Otherwise, create a separate context to be used for ARGB pixmaps:
97  if (!argbContext) {
99  argbContext->setConfig(argbConfig);
100  bool success = argbContext->createContext(rgbContext);
101  if (!success) {
102  qWarning("QX11GLPixmapData - RGB & ARGB contexts aren't shared");
103  success = argbContext->createContext();
104  if (!success)
105  argbContext = rgbContext; // Might work, worth a shot at least.
106  }
107  }
108 
109  if (!argbContext->isValid())
110  break;
111 
112  // Create the pixmap which will be used to create the egl surface for the share QGLContext
114  rgbPixmapData->resize(8, 8);
115  rgbPixmapData->fill(Qt::red);
116  sharePixmap = new QPixmap(rgbPixmapData);
117  EGLSurface sharePixmapSurface = QEgl::createSurface(sharePixmap, rgbConfig);
118  rgbPixmapData->gl_surface = (void*)sharePixmapSurface;
119 
120  // Create the actual QGLContext which will be used for sharing
122  sharedQGLContext->d_func()->eglContext = rgbContext;
123  sharedQGLContext->d_func()->eglSurface = sharePixmapSurface;
124  sharedQGLContext->d_func()->valid = true;
125  qt_glformat_from_eglconfig(sharedQGLContext->d_func()->glFormat, rgbConfig);
126 
127 
128  valid = rgbContext->makeCurrent(sharePixmapSurface);
129 
130  // If the ARGB & RGB configs are different, check ARGB works too:
131  if (argbConfig != rgbConfig) {
133  argbPixmapData->resize(8, 8);
134  argbPixmapData->fill(Qt::transparent); // Force ARGB
135  QPixmap argbPixmap(argbPixmapData); // destroys pixmap data when goes out of scope
136  EGLSurface argbPixmapSurface = QEgl::createSurface(&argbPixmap, argbConfig);
137  valid = argbContext->makeCurrent(argbPixmapSurface);
139  eglDestroySurface(QEgl::display(), argbPixmapSurface);
140  argbPixmapData->gl_surface = 0;
141  }
142 
143  if (!valid) {
144  qWarning() << "Unable to make pixmap surface current:" << QEgl::errorString();
145  break;
146  }
147 
148  // The pixmap surface destruction hooks are installed by QGLTextureCache, so we
149  // must make sure this is instanciated:
151  } while(0);
152 
153  if (!valid)
154  cleanup();
155  else
156  qDebug("Using QX11GLPixmapData with EGL config %d for ARGB and config %d for RGB", argbConfigId, rgbConfigId);
157 
158  }
159 
161  cleanup();
162  }
163 
164  void cleanup() {
165  if (sharedQGLContext) {
166  delete sharedQGLContext;
167  sharedQGLContext = 0;
168  }
170  delete argbContext;
171  argbContext = 0;
172 
173  if (rgbContext) {
174  delete rgbContext;
175  rgbContext = 0;
176  }
177 
178  // Deleting the QPixmap will fire the pixmap destruction cleanup hooks which in turn
179  // will destroy the egl surface:
180  if (sharePixmap) {
181  delete sharePixmap;
182  sharePixmap = 0;
183  }
184  }
185 
186  bool isValid() { return valid;}
187 
188  // On 16bpp systems, RGB & ARGB pixmaps are different bit-depths and therefore need
189  // different contexts:
192 
193  // The share context wraps the rgbContext and is used as the master of the context share
194  // group. As all other contexts will have the same egl context (or a shared one if rgb != argb)
195  // all QGLContexts will actually be sharing and can be in the same context group.
197 private:
199  bool valid;
200 };
201 
202 static void qt_cleanup_x11gl_share_contexts();
203 
205  {
207  })
208 
210 {
211  qt_x11gl_share_contexts()->cleanup();
212 }
213 
214 
216 {
217  return qt_x11gl_share_contexts();
218 }
219 
221 {
222  static bool checkedForX11GLPixmaps = false;
223  static bool haveX11GLPixmaps = false;
224 
225  if (checkedForX11GLPixmaps)
226  return haveX11GLPixmaps;
227 
228  haveX11GLPixmaps = qt_x11gl_share_contexts()->isValid();
229  checkedForX11GLPixmaps = true;
230 
231  return haveX11GLPixmaps;
232 }
233 
235  : QX11PixmapData(QPixmapData::PixmapType),
236  ctx(0)
237 {
238 }
239 
241 {
242  if (ctx)
243  delete ctx;
244 }
245 
246 
247 void QX11GLPixmapData::fill(const QColor &color)
248 {
249  if (ctx) {
250  ctx->makeCurrent();
251  glFinish();
252  eglWaitClient();
253  }
254 
255  QX11PixmapData::fill(color);
256  XSync(X11->display, False);
257 
258  if (ctx) {
259  ctx->makeCurrent();
260  eglWaitNative(EGL_CORE_NATIVE_ENGINE);
261  }
262 }
263 
264 void QX11GLPixmapData::copy(const QPixmapData *data, const QRect &rect)
265 {
266  if (ctx) {
267  ctx->makeCurrent();
268  glFinish();
269  eglWaitClient();
270  }
271 
272  QX11PixmapData::copy(data, rect);
273  XSync(X11->display, False);
274 
275  if (ctx) {
276  ctx->makeCurrent();
277  eglWaitNative(EGL_CORE_NATIVE_ENGINE);
278  }
279 }
280 
281 bool QX11GLPixmapData::scroll(int dx, int dy, const QRect &rect)
282 {
283  if (ctx) {
284  ctx->makeCurrent();
285  glFinish();
286  eglWaitClient();
287  }
288 
289  bool success = QX11PixmapData::scroll(dx, dy, rect);
290  XSync(X11->display, False);
291 
292  if (ctx) {
293  ctx->makeCurrent();
294  eglWaitNative(EGL_CORE_NATIVE_ENGINE);
295  }
296 
297  return success;
298 }
299 
300 #if !defined(QT_OPENGL_ES_1)
301 Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_pixmap_2_engine)
302 #endif
303 
304 #ifndef QT_OPENGL_ES_2
305 Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_pixmap_engine)
306 #endif
307 
308 
310 {
311  // We need to create the context before beginPaint - do it here:
312  if (!ctx) {
313  ctx = new QGLContext(glFormat());
314  Q_ASSERT(ctx->d_func()->eglContext == 0);
315  ctx->d_func()->eglContext = hasAlphaChannel() ? sharedContexts()->argbContext : sharedContexts()->rgbContext;
316 
317  // While we use a separate QGLContext for each pixmap, the underlying QEglContext is
318  // the same. So we must use a "fake" QGLContext and fool the texture cache into thinking
319  // each pixmap's QGLContext is sharing with this central one. The only place this is
320  // going to fail is where we the underlying EGL RGB and ARGB contexts aren't sharing.
321  ctx->d_func()->sharing = true;
322  QGLContextGroup::addShare(ctx, sharedContexts()->sharedQGLContext);
323 
324  // Update the glFormat for the QGLContext:
325  qt_glformat_from_eglconfig(ctx->d_func()->glFormat, ctx->d_func()->eglContext->config());
326  }
327 
328  QPaintEngine* engine;
329 
330 #if defined(QT_OPENGL_ES_1)
331  engine = qt_gl_pixmap_engine();
332 #elif defined(QT_OPENGL_ES_2)
333  engine = qt_gl_pixmap_2_engine();
334 #else
335  if (qt_gl_preferGL2Engine())
336  engine = qt_gl_pixmap_2_engine();
337  else
338  engine = qt_gl_pixmap_engine();
339 #endif
340 
341 
342 
343  // Support multiple painters on multiple pixmaps simultaniously
344  if (engine->isActive()) {
345  qWarning("Pixmap paint engine already active");
346 
347 #if defined(QT_OPENGL_ES_1)
348  engine = new QOpenGLPaintEngine;
349 #elif defined(QT_OPENGL_ES_2)
350  engine = new QGL2PaintEngineEx;
351 #else
352  if (qt_gl_preferGL2Engine())
353  engine = new QGL2PaintEngineEx;
354  else
355  engine = new QOpenGLPaintEngine;
356 #endif
357 
358  engine->setAutoDestruct(true);
359  return engine;
360  }
361 
362  return engine;
363 }
364 
366 {
367 // qDebug("QX11GLPixmapData::beginPaint()");
368  // TODO: Check to see if the surface is renderable
369  if ((EGLSurface)gl_surface == EGL_NO_SURFACE) {
370  QPixmap tmpPixmap(this);
371  EGLConfig cfg = ctx->d_func()->eglContext->config();
372  Q_ASSERT(cfg != QEGL_NO_CONFIG);
373 
374 // qDebug("QX11GLPixmapData - using EGL Config ID %d", ctx->d_func()->eglContext->configAttrib(EGL_CONFIG_ID));
375  EGLSurface surface = QEgl::createSurface(&tmpPixmap, cfg);
376  if (surface == EGL_NO_SURFACE) {
377  qWarning() << "Error creating EGL surface for pixmap:" << QEgl::errorString();
378  return;
379  }
380  gl_surface = (void*)surface;
381  ctx->d_func()->eglSurface = surface;
382  ctx->d_func()->valid = true;
383  }
385 }
386 
388 {
389  return ctx;
390 }
391 
393 {
394  return QSize(w, h);
395 }
396 
397 
399 {
400  return QGLFormat::defaultFormat(); //###
401 }
402 
void qt_glformat_from_eglconfig(QGLFormat &format, const EGLConfig config)
Definition: qgl_egl.cpp:145
The QColor class provides colors based on RGB, HSV or CMYK values.
Definition: qcolor.h:67
QGLContext * context() const
static void addShare(const QGLContext *context, const QGLContext *share)
Definition: qgl.cpp:5846
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
bool createContext(QEglContext *shareContext=0, const QEglProperties *properties=0)
Definition: qegl.cpp:361
bool isValid() const
Definition: qegl.cpp:116
static QGLTextureCache * instance()
Definition: qgl.cpp:1995
void qAddPostRoutine(QtCleanUpFunction p)
static QGLFormat glFormat()
void resize(int width, int height)
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define X11
Definition: qt_x11_p.h:724
QPaintEngine * paintEngine() const
Q_GUI_EXPORT QString errorString(EGLint code=eglGetError())
Definition: qegl.cpp:743
Q_CORE_EXPORT void qDebug(const char *,...)
bool doneCurrent()
Definition: qegl.cpp:485
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
Q_GUI_EXPORT EGLDisplay display()
Definition: qegl.cpp:589
bool scroll(int dx, int dy, const QRect &rect)
The QGLFormat class specifies the display format of an OpenGL rendering context.
Definition: qgl.h:175
Q_GLOBAL_STATIC_WITH_INITIALIZER(QX11GLSharedContexts, qt_x11gl_share_contexts, { qAddPostRoutine(qt_cleanup_x11gl_share_contexts);}) static void qt_cleanup_x11gl_share_contexts()
The QGLContext class encapsulates an OpenGL rendering context.
Definition: qgl.h:310
bool scroll(int dx, int dy, const QRect &rect)
#define Q_GLOBAL_STATIC(TYPE, NAME)
Declares a global static variable with the given type and name.
Definition: qglobal.h:1968
void copy(const QPixmapData *data, const QRect &rect)
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
void copy(const QPixmapData *data, const QRect &rect)
The QPaintEngine class provides an abstract definition of how QPainter draws to a given device on a g...
Definition: qpaintengine.h:90
bool qt_gl_preferGL2Engine()
Definition: qgl.cpp:218
void fill(const QColor &color)
Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options)
Definition: qegl.cpp:126
#define QEGL_NO_CONFIG
Definition: qegl_p.h:129
friend class QGLContext
void fill(const QColor &color)
Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs=0)
Definition: qegl_x11.cpp:333
bool hasAlphaChannel() const
bool makeCurrent(EGLSurface surface)
Definition: qegl.cpp:433
virtual void beginPaint()
#define ctx
Definition: qgl.cpp:6094
static QGLFormat defaultFormat()
Definition: qgl.cpp:1518
void setConfig(EGLConfig config)
Definition: qeglcontext_p.h:97
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
virtual void makeCurrent()
Makes this context the current OpenGL rendering context.
Definition: qgl_egl.cpp:213
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
static QX11GLSharedContexts * sharedContexts()
static void qt_cleanup_x11gl_share_contexts()