Qt 4.8
qglpixelbuffer_x11.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 #include <qlibrary.h>
42 #include <qdebug.h>
43 #include <private/qgl_p.h>
44 #include <private/qt_x11_p.h>
45 #include <private/qpaintengine_opengl_p.h>
46 
47 #include <qx11info_x11.h>
48 #include <GL/glx.h>
49 #include <qimage.h>
50 
51 #include "qglpixelbuffer.h"
52 #include "qglpixelbuffer_p.h"
53 
54 #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
55 #include <dlfcn.h>
56 #endif
57 
59 
60 #ifndef GLX_VERSION_1_3
61 #define GLX_RGBA_BIT 0x00000002
62 #define GLX_PBUFFER_BIT 0x00000004
63 #define GLX_DRAWABLE_TYPE 0x8010
64 #define GLX_RENDER_TYPE 0x8011
65 #define GLX_RGBA_TYPE 0x8014
66 #define GLX_PBUFFER_HEIGHT 0x8040
67 #define GLX_PBUFFER_WIDTH 0x8041
68 #endif
69 
70 #ifndef GLX_ARB_multisample
71 #define GLX_SAMPLE_BUFFERS_ARB 100000
72 #define GLX_SAMPLES_ARB 100001
73 #endif
74 
75 typedef GLXFBConfig* (*_glXChooseFBConfig) (Display *dpy, int screen, const int *attrib_list, int *nelements);
76 typedef int (*_glXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config, int attribute, int *value);
77 typedef GLXPbuffer (*_glXCreatePbuffer) (Display *dpy, GLXFBConfig config, const int *attrib_list);
78 typedef void (*_glXDestroyPbuffer) (Display *dpy, GLXPbuffer pbuf);
79 typedef GLXContext (*_glXCreateNewContext) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
80 typedef Bool (*_glXMakeContextCurrent) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
81 
88 
89 #define glXChooseFBConfig qt_glXChooseFBConfig
90 #define glXCreateNewContext qt_glXCreateNewContext
91 #define glXCreatePbuffer qt_glXCreatePbuffer
92 #define glXDestroyPbuffer qt_glXDestroyPbuffer
93 #define glXGetFBConfigAttrib qt_glXGetFBConfigAttrib
94 #define glXMakeContextCurrent qt_glXMakeContextCurrent
95 
96 extern void* qglx_getProcAddress(const char* procName); // in qgl_x11.cpp
97 
99 {
100  static int resolved = false;
101  if (resolved && qt_glXMakeContextCurrent)
102  return true;
103  else if (resolved)
104  return false;
105 
112 
113  resolved = qt_glXMakeContextCurrent ? true : false;
114  return resolved;
115 }
116 
117 static void qt_format_to_attrib_list(const QGLFormat &f, int attribs[])
118 {
119  int i = 0;
120  attribs[i++] = GLX_RENDER_TYPE;
121  attribs[i++] = GLX_RGBA_BIT;
122  attribs[i++] = GLX_DRAWABLE_TYPE;
123  attribs[i++] = GLX_PBUFFER_BIT;
124  attribs[i++] = GLX_RED_SIZE;
125  attribs[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
126  attribs[i++] = GLX_GREEN_SIZE;
127  attribs[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
128  attribs[i++] = GLX_BLUE_SIZE;
129  attribs[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
130  if (f.doubleBuffer()) {
131  attribs[i++] = GLX_DOUBLEBUFFER;
132  attribs[i++] = true;
133  }
134  if (f.depth()) {
135  attribs[i++] = GLX_DEPTH_SIZE;
136  attribs[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
137  }
138  if (f.stereo()) {
139  attribs[i++] = GLX_STEREO;
140  attribs[i++] = true;
141  }
142  if (f.stencil()) {
143  attribs[i++] = GLX_STENCIL_SIZE;
144  attribs[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
145  }
146  if (f.alpha()) {
147  attribs[i++] = GLX_ALPHA_SIZE;
148  attribs[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
149  }
150  if (f.accum()) {
151  attribs[i++] = GLX_ACCUM_RED_SIZE;
152  attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
153  attribs[i++] = GLX_ACCUM_GREEN_SIZE;
154  attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
155  attribs[i++] = GLX_ACCUM_BLUE_SIZE;
156  attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
157  if (f.alpha()) {
158  attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
159  attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
160  }
161  }
162  if (f.sampleBuffers()) {
163  attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
164  attribs[i++] = 1;
165  attribs[i++] = GLX_SAMPLES_ARB;
166  attribs[i++] = f.samples() == -1 ? 4 : f.samples();
167  }
168 
169  attribs[i] = XNone;
170 }
171 
172 bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
173 {
175  qWarning("QGLPixelBuffer: pbuffers are not supported on this system.");
176  return false;
177  }
178 
179  int attribs[40];
180  int num_configs = 0;
181 
182  qt_format_to_attrib_list(f, attribs);
183 
184  int screen = X11->defaultScreen;
185  if (shareWidget)
186  screen = shareWidget->x11Info().screen();
187 
188  GLXFBConfig *configs = glXChooseFBConfig(X11->display, screen, attribs, &num_configs);
189  if (configs && num_configs) {
190  int res;
191  glXGetFBConfigAttrib(X11->display, configs[0], GLX_LEVEL, &res);
192  format.setPlane(res);
193  glXGetFBConfigAttrib(X11->display, configs[0], GLX_DOUBLEBUFFER, &res);
194  format.setDoubleBuffer(res);
195  glXGetFBConfigAttrib(X11->display, configs[0], GLX_DEPTH_SIZE, &res);
196  format.setDepth(res);
197  if (format.depth())
198  format.setDepthBufferSize(res);
199  glXGetFBConfigAttrib(X11->display, configs[0], GLX_RGBA, &res);
200  format.setRgba(res);
201  glXGetFBConfigAttrib(X11->display, configs[0], GLX_RED_SIZE, &res);
202  format.setRedBufferSize(res);
203  glXGetFBConfigAttrib(X11->display, configs[0], GLX_GREEN_SIZE, &res);
204  format.setGreenBufferSize(res);
205  glXGetFBConfigAttrib(X11->display, configs[0], GLX_BLUE_SIZE, &res);
206  format.setBlueBufferSize(res);
207  glXGetFBConfigAttrib(X11->display, configs[0], GLX_ALPHA_SIZE, &res);
208  format.setAlpha(res);
209  if (format.alpha())
210  format.setAlphaBufferSize(res);
211  glXGetFBConfigAttrib(X11->display, configs[0], GLX_ACCUM_RED_SIZE, &res);
212  format.setAccum(res);
213  if (format.accum())
214  format.setAccumBufferSize(res);
215  glXGetFBConfigAttrib(X11->display, configs[0], GLX_STENCIL_SIZE, &res);
216  format.setStencil(res);
217  if (format.stencil())
218  format.setStencilBufferSize(res);
219  glXGetFBConfigAttrib(X11->display, configs[0], GLX_STEREO, &res);
220  format.setStereo(res);
221  glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLE_BUFFERS_ARB, &res);
222  format.setSampleBuffers(res);
223  if (format.sampleBuffers()) {
224  glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLES_ARB, &res);
225  format.setSamples(res);
226  }
227 
228  int pb_attribs[] = {GLX_PBUFFER_WIDTH, size.width(), GLX_PBUFFER_HEIGHT, size.height(), XNone};
229  GLXContext shareContext = 0;
230  if (shareWidget && shareWidget->d_func()->glcx)
231  shareContext = (GLXContext) shareWidget->d_func()->glcx->d_func()->cx;
232 
233  pbuf = glXCreatePbuffer(QX11Info::display(), configs[0], pb_attribs);
234  ctx = glXCreateNewContext(QX11Info::display(), configs[0], GLX_RGBA_TYPE, shareContext, true);
235 
236  XFree(configs);
237  if (!pbuf || !ctx) {
238  qWarning("QGLPixelBuffer: Unable to create a pbuffer/context - giving up.");
239  return false;
240  }
241  return true;
242  } else {
243  qWarning("QGLPixelBuffer: Unable to find a context/format match - giving up.");
244  return false;
245  }
246 }
247 
249 {
251  return true;
252 }
253 
255 {
256  return false;
257 }
258 
260 {
261 }
262 
264 {
265  bool ret = qt_resolve_pbuffer_extensions();
266 
267  if (!ret)
268  return false;
269 
270  int attribs[40];
271  int num_configs = 0;
272 
274 
275  GLXFBConfig *configs = glXChooseFBConfig(X11->display, X11->defaultScreen, attribs, &num_configs);
276  GLXPbuffer pbuf = 0;
277  GLXContext ctx = 0;
278 
279  if (configs && num_configs) {
280  int pb_attribs[] = {GLX_PBUFFER_WIDTH, 128, GLX_PBUFFER_HEIGHT, 128, XNone};
281  pbuf = glXCreatePbuffer(X11->display, configs[0], pb_attribs);
282  ctx = glXCreateNewContext(X11->display, configs[0], GLX_RGBA_TYPE, 0, true);
283  XFree(configs);
284  glXDestroyContext(X11->display, ctx);
285  glXDestroyPbuffer(X11->display, pbuf);
286  }
287  return pbuf && ctx;
288 }
289 
static void qt_format_to_attrib_list(const QGLFormat &f, int attribs[])
static _glXGetFBConfigAttrib qt_glXGetFBConfigAttrib
#define GLX_SAMPLES_ARB
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int greenBufferSize() const
Returns the green buffer size.
Definition: qgl.cpp:1070
#define GLX_RGBA_BIT
const QX11Info & x11Info() const
Returns information about the configuration of the X display used to display the widget.
#define glXGetFBConfigAttrib
static _glXDestroyPbuffer qt_glXDestroyPbuffer
GLXContext(* _glXCreateNewContext)(Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct)
static bool hasOpenGLPbuffers()
Returns true if the OpenGL pbuffer extension is present on this system; otherwise returns false...
int redBufferSize() const
Returns the red buffer size.
Definition: qgl.cpp:1035
#define X11
Definition: qt_x11_p.h:724
static _glXChooseFBConfig qt_glXChooseFBConfig
#define glXChooseFBConfig
#define GLX_SAMPLE_BUFFERS_ARB
bool sampleBuffers() const
Returns true if multisample buffer support is enabled; otherwise returns false.
Definition: qgl.h:658
#define GLX_PBUFFER_BIT
int width() const
Returns the width.
Definition: qsize.h:126
int alphaBufferSize() const
Returns the alpha buffer size.
Definition: qgl.cpp:1132
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
#define GLX_PBUFFER_WIDTH
#define GLX_DRAWABLE_TYPE
bool depth() const
Returns true if the depth buffer is enabled; otherwise returns false.
Definition: qgl.h:618
int accumBufferSize() const
Returns the accumulation buffer size.
Definition: qgl.cpp:1159
The QGLFormat class specifies the display format of an OpenGL rendering context.
Definition: qgl.h:175
#define GLX_RENDER_TYPE
int depthBufferSize() const
Returns the depth buffer size.
Definition: qgl.cpp:1000
static _glXCreateNewContext qt_glXCreateNewContext
static bool qt_resolve_pbuffer_extensions()
#define GLX_PBUFFER_HEIGHT
bool stencil() const
Returns true if the stencil buffer is enabled; otherwise returns false.
Definition: qgl.h:638
Q_CORE_EXPORT void qWarning(const char *,...)
GLXPbuffer(* _glXCreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attrib_list)
bool accum() const
Returns true if the accumulation buffer is enabled; otherwise returns false.
Definition: qgl.h:633
#define glXDestroyPbuffer
#define glXCreatePbuffer
static _glXCreatePbuffer qt_glXCreatePbuffer
bool bindToDynamicTexture(GLuint texture)
Generates and binds a 2D GL texture that is the same size as the pbuffer, and returns the texture&#39;s I...
struct _XDisplay Display
Definition: qwindowdefs.h:115
void * qglx_getProcAddress(const char *procName)
Definition: qgl_x11.cpp:350
The QGLWidget class is a widget for rendering OpenGL graphics.
Definition: qgl.h:474
Bool(* _glXMakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
#define ctx
Definition: qgl.cpp:6094
static QGLFormat defaultFormat()
Definition: qgl.cpp:1518
#define GLX_RGBA_TYPE
bool alpha() const
Returns true if the alpha buffer in the framebuffer is enabled; otherwise returns false...
Definition: qgl.h:628
int height() const
Returns the height.
Definition: qsize.h:129
int blueBufferSize() const
Returns the blue buffer size.
Definition: qgl.cpp:1105
bool doubleBuffer() const
Returns true if double buffering is enabled; otherwise returns false.
Definition: qgl.h:613
bool init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
GLXFBConfig *(* _glXChooseFBConfig)(Display *dpy, int screen, const int *attrib_list, int *nelements)
static _glXMakeContextCurrent qt_glXMakeContextCurrent
int(* _glXGetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value)
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
int stencilBufferSize() const
Returns the stencil buffer size.
Definition: qgl.cpp:1185
bool stereo() const
Returns true if stereo buffering is enabled; otherwise returns false.
Definition: qgl.h:643
int samples() const
Returns the number of samples per pixel when multisampling is enabled.
Definition: qgl.cpp:824
void releaseFromDynamicTexture()
Releases the pbuffer from any previously bound texture.
static Display * display()
Returns the default display for the application.
#define glXCreateNewContext
int screen() const
Returns the number of the screen currently in use.
void(* _glXDestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)