source: trunk/src/opengl/qglpixelbuffer_x11.cpp@ 503

Last change on this file since 503 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 11.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtOpenGL module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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
58QT_BEGIN_NAMESPACE
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
75typedef GLXFBConfig* (*_glXChooseFBConfig) (Display *dpy, int screen, const int *attrib_list, int *nelements);
76typedef int (*_glXGetFBConfigAttrib) (Display *dpy, GLXFBConfig config, int attribute, int *value);
77typedef GLXPbuffer (*_glXCreatePbuffer) (Display *dpy, GLXFBConfig config, const int *attrib_list);
78typedef void (*_glXDestroyPbuffer) (Display *dpy, GLXPbuffer pbuf);
79typedef GLXContext (*_glXCreateNewContext) (Display *dpy, GLXFBConfig config, int render_type, GLXContext share_list, Bool direct);
80typedef Bool (*_glXMakeContextCurrent) (Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx);
81
82static _glXChooseFBConfig qt_glXChooseFBConfig = 0;
83static _glXCreateNewContext qt_glXCreateNewContext = 0;
84static _glXCreatePbuffer qt_glXCreatePbuffer = 0;
85static _glXDestroyPbuffer qt_glXDestroyPbuffer = 0;
86static _glXGetFBConfigAttrib qt_glXGetFBConfigAttrib = 0;
87static _glXMakeContextCurrent qt_glXMakeContextCurrent = 0;
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
96static bool qt_resolve_pbuffer_extensions()
97{
98 static int resolved = false;
99 if (resolved && qt_glXMakeContextCurrent)
100 return true;
101 else if (resolved)
102 return false;
103
104#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
105 void *handle = dlopen(NULL, RTLD_LAZY);
106 if (handle) {
107 qt_glXChooseFBConfig = (_glXChooseFBConfig) dlsym(handle, "glXChooseFBConfig");
108 qt_glXCreateNewContext = (_glXCreateNewContext) dlsym(handle, "glXCreateNewContext");
109 qt_glXCreatePbuffer = (_glXCreatePbuffer) dlsym(handle, "glXCreatePbuffer");
110 qt_glXDestroyPbuffer = (_glXDestroyPbuffer) dlsym(handle, "glXDestroyPbuffer");
111 qt_glXGetFBConfigAttrib = (_glXGetFBConfigAttrib) dlsym(handle, "glXGetFBConfigAttrib");
112 qt_glXMakeContextCurrent = (_glXMakeContextCurrent) dlsym(handle, "glXMakeContextCurrent");
113 dlclose(handle);
114 }
115 if (!qt_glXChooseFBConfig)
116#endif
117 {
118 extern const QString qt_gl_library_name();
119 QLibrary gl(qt_gl_library_name());
120 qt_glXChooseFBConfig = (_glXChooseFBConfig) gl.resolve("glXChooseFBConfig");
121 qt_glXCreateNewContext = (_glXCreateNewContext) gl.resolve("glXCreateNewContext");
122 qt_glXCreatePbuffer = (_glXCreatePbuffer) gl.resolve("glXCreatePbuffer");
123 qt_glXDestroyPbuffer = (_glXDestroyPbuffer) gl.resolve("glXDestroyPbuffer");
124 qt_glXGetFBConfigAttrib = (_glXGetFBConfigAttrib) gl.resolve("glXGetFBConfigAttrib");
125 qt_glXMakeContextCurrent = (_glXMakeContextCurrent) gl.resolve("glXMakeContextCurrent");
126 }
127
128 resolved = qt_glXMakeContextCurrent ? true : false;
129 return resolved;
130}
131
132static void qt_format_to_attrib_list(const QGLFormat &f, int attribs[])
133{
134 int i = 0;
135 attribs[i++] = GLX_RENDER_TYPE;
136 attribs[i++] = GLX_RGBA_BIT;
137 attribs[i++] = GLX_DRAWABLE_TYPE;
138 attribs[i++] = GLX_PBUFFER_BIT;
139 attribs[i++] = GLX_RED_SIZE;
140 attribs[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
141 attribs[i++] = GLX_GREEN_SIZE;
142 attribs[i++] = f.greenBufferSize() == -1 ? 1 : f.greenBufferSize();
143 attribs[i++] = GLX_BLUE_SIZE;
144 attribs[i++] = f.blueBufferSize() == -1 ? 1 : f.blueBufferSize();
145 if (f.doubleBuffer()) {
146 attribs[i++] = GLX_DOUBLEBUFFER;
147 attribs[i++] = true;
148 }
149 if (f.depth()) {
150 attribs[i++] = GLX_DEPTH_SIZE;
151 attribs[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
152 }
153 if (f.stereo()) {
154 attribs[i++] = GLX_STEREO;
155 attribs[i++] = true;
156 }
157 if (f.stencil()) {
158 attribs[i++] = GLX_STENCIL_SIZE;
159 attribs[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
160 }
161 if (f.alpha()) {
162 attribs[i++] = GLX_ALPHA_SIZE;
163 attribs[i++] = f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize();
164 }
165 if (f.accum()) {
166 attribs[i++] = GLX_ACCUM_RED_SIZE;
167 attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
168 attribs[i++] = GLX_ACCUM_GREEN_SIZE;
169 attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
170 attribs[i++] = GLX_ACCUM_BLUE_SIZE;
171 attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
172 if (f.alpha()) {
173 attribs[i++] = GLX_ACCUM_ALPHA_SIZE;
174 attribs[i++] = f.accumBufferSize() == -1 ? 1 : f.accumBufferSize();
175 }
176 }
177 if (f.sampleBuffers()) {
178 attribs[i++] = GLX_SAMPLE_BUFFERS_ARB;
179 attribs[i++] = 1;
180 attribs[i++] = GLX_SAMPLES_ARB;
181 attribs[i++] = f.samples() == -1 ? 4 : f.samples();
182 }
183
184 attribs[i] = XNone;
185}
186
187bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
188{
189 if (!qt_resolve_pbuffer_extensions()) {
190 qWarning("QGLPixelBuffer: pbuffers are not supported on this system.");
191 return false;
192 }
193
194 int attribs[40];
195 int num_configs = 0;
196
197 qt_format_to_attrib_list(f, attribs);
198
199 GLXFBConfig *configs = glXChooseFBConfig(X11->display, X11->defaultScreen, attribs, &num_configs);
200 if (configs && num_configs) {
201 int res;
202 glXGetFBConfigAttrib(X11->display, configs[0], GLX_LEVEL, &res);
203 format.setPlane(res);
204 glXGetFBConfigAttrib(X11->display, configs[0], GLX_DOUBLEBUFFER, &res);
205 format.setDoubleBuffer(res);
206 glXGetFBConfigAttrib(X11->display, configs[0], GLX_DEPTH_SIZE, &res);
207 format.setDepth(res);
208 if (format.depth())
209 format.setDepthBufferSize(res);
210 glXGetFBConfigAttrib(X11->display, configs[0], GLX_RGBA, &res);
211 format.setRgba(res);
212 glXGetFBConfigAttrib(X11->display, configs[0], GLX_RED_SIZE, &res);
213 format.setRedBufferSize(res);
214 glXGetFBConfigAttrib(X11->display, configs[0], GLX_GREEN_SIZE, &res);
215 format.setGreenBufferSize(res);
216 glXGetFBConfigAttrib(X11->display, configs[0], GLX_BLUE_SIZE, &res);
217 format.setBlueBufferSize(res);
218 glXGetFBConfigAttrib(X11->display, configs[0], GLX_ALPHA_SIZE, &res);
219 format.setAlpha(res);
220 if (format.alpha())
221 format.setAlphaBufferSize(res);
222 glXGetFBConfigAttrib(X11->display, configs[0], GLX_ACCUM_RED_SIZE, &res);
223 format.setAccum(res);
224 if (format.accum())
225 format.setAccumBufferSize(res);
226 glXGetFBConfigAttrib(X11->display, configs[0], GLX_STENCIL_SIZE, &res);
227 format.setStencil(res);
228 if (format.stencil())
229 format.setStencilBufferSize(res);
230 glXGetFBConfigAttrib(X11->display, configs[0], GLX_STEREO, &res);
231 format.setStereo(res);
232 glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLE_BUFFERS_ARB, &res);
233 format.setSampleBuffers(res);
234 if (format.sampleBuffers()) {
235 glXGetFBConfigAttrib(X11->display, configs[0], GLX_SAMPLES_ARB, &res);
236 format.setSamples(res);
237 }
238
239 int pb_attribs[] = {GLX_PBUFFER_WIDTH, size.width(), GLX_PBUFFER_HEIGHT, size.height(), XNone};
240 GLXContext shareContext = 0;
241 if (shareWidget && shareWidget->d_func()->glcx)
242 shareContext = (GLXContext) shareWidget->d_func()->glcx->d_func()->cx;
243
244 pbuf = glXCreatePbuffer(QX11Info::display(), configs[0], pb_attribs);
245 ctx = glXCreateNewContext(QX11Info::display(), configs[0], GLX_RGBA_TYPE, shareContext, true);
246
247 XFree(configs);
248 if (!pbuf || !ctx) {
249 qWarning("QGLPixelBuffer: Unable to create a pbuffer/context - giving up.");
250 return false;
251 }
252 return true;
253 } else {
254 qWarning("QGLPixelBuffer: Unable to find a context/format match - giving up.");
255 return false;
256 }
257}
258
259bool QGLPixelBufferPrivate::cleanup()
260{
261 glXDestroyPbuffer(QX11Info::display(), pbuf);
262 return true;
263}
264
265bool QGLPixelBuffer::bindToDynamicTexture(GLuint)
266{
267 return false;
268}
269
270void QGLPixelBuffer::releaseFromDynamicTexture()
271{
272}
273
274bool QGLPixelBuffer::hasOpenGLPbuffers()
275{
276 bool ret = qt_resolve_pbuffer_extensions();
277
278 if (!ret)
279 return false;
280
281 int attribs[40];
282 int num_configs = 0;
283
284 qt_format_to_attrib_list(QGLFormat::defaultFormat(), attribs);
285
286 GLXFBConfig *configs = glXChooseFBConfig(X11->display, X11->defaultScreen, attribs, &num_configs);
287 GLXPbuffer pbuf = 0;
288 GLXContext ctx = 0;
289
290 if (configs && num_configs) {
291 int pb_attribs[] = {GLX_PBUFFER_WIDTH, 128, GLX_PBUFFER_HEIGHT, 128, XNone};
292 pbuf = glXCreatePbuffer(X11->display, configs[0], pb_attribs);
293 ctx = glXCreateNewContext(X11->display, configs[0], GLX_RGBA_TYPE, 0, true);
294 XFree(configs);
295 glXDestroyContext(X11->display, ctx);
296 glXDestroyPbuffer(X11->display, pbuf);
297 }
298 return pbuf && ctx;
299}
300
301QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.