source: trunk/src/opengl/qgl_mac.mm

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 31.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtOpenGL module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this 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 have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qgl.h"
43
44// There are functions that are deprecated in 10.5, but really there's no way around them
45// for Carbon, so just undefine them.
46#undef DEPRECATED_ATTRIBUTE
47#define DEPRECATED_ATTRIBUTE
48#if defined(Q_WS_MAC)
49#ifndef QT_MAC_USE_COCOA
50#ifdef qDebug
51# undef qDebug
52# include <AGL/agl.h>
53# include <AGL/aglRenderers.h>
54# include <OpenGL/gl.h>
55# ifdef QT_NO_DEBUG
56# define qDebug qt_noop(),1?(void)0:qDebug
57# endif
58#else
59# include <AGL/agl.h>
60# include <AGL/aglRenderers.h>
61# include <OpenGL/gl.h>
62#endif
63#else
64#include <private/qcocoaview_mac_p.h>
65#endif
66
67
68#include <OpenGL/gl.h>
69#include <CoreServices/CoreServices.h>
70#include <private/qfont_p.h>
71#include <private/qfontengine_p.h>
72#include <private/qgl_p.h>
73#include <private/qpaintengine_opengl_p.h>
74#include <private/qt_mac_p.h>
75#include <qpixmap.h>
76#include <qtimer.h>
77#include <qapplication.h>
78#include <qstack.h>
79#include <qdesktopwidget.h>
80#include <qdebug.h>
81
82QT_BEGIN_NAMESPACE
83#ifdef QT_MAC_USE_COCOA
84QT_END_NAMESPACE
85
86QT_FORWARD_DECLARE_CLASS(QWidget)
87QT_FORWARD_DECLARE_CLASS(QWidgetPrivate)
88QT_FORWARD_DECLARE_CLASS(QGLWidgetPrivate)
89
90QT_BEGIN_NAMESPACE
91
92void *qt_current_nsopengl_context()
93{
94 return [NSOpenGLContext currentContext];
95}
96
97static GLint attribValue(NSOpenGLPixelFormat *fmt, NSOpenGLPixelFormatAttribute attrib)
98{
99 GLint res;
100 [fmt getValues:&res forAttribute:attrib forVirtualScreen:0];
101 return res;
102}
103
104static int def(int val, int defVal)
105{
106 return val != -1 ? val : defVal;
107}
108#else
109QRegion qt_mac_get_widget_rgn(const QWidget *widget);
110#endif
111
112extern quint32 *qt_mac_pixmap_get_base(const QPixmap *);
113extern int qt_mac_pixmap_get_bytes_per_line(const QPixmap *);
114extern RgnHandle qt_mac_get_rgn(); //qregion_mac.cpp
115extern void qt_mac_dispose_rgn(RgnHandle); //qregion_mac.cpp
116extern QRegion qt_mac_convert_mac_region(RgnHandle); //qregion_mac.cpp
117extern void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1); //qglobal.cpp
118
119/*
120 QGLTemporaryContext implementation
121*/
122
123class QGLTemporaryContextPrivate
124{
125public:
126#ifndef QT_MAC_USE_COCOA
127 AGLContext ctx;
128#else
129 NSOpenGLContext *ctx;
130#endif
131};
132
133QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
134 : d(new QGLTemporaryContextPrivate)
135{
136 d->ctx = 0;
137#ifndef QT_MAC_USE_COCOA
138 GLint attribs[] = {AGL_RGBA, AGL_NONE};
139 AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs);
140 if (!fmt) {
141 qDebug("QGLTemporaryContext: Couldn't find any RGB visuals");
142 return;
143 }
144 d->ctx = aglCreateContext(fmt, 0);
145 if (!d->ctx)
146 qDebug("QGLTemporaryContext: Unable to create context");
147 else
148 aglSetCurrentContext(d->ctx);
149 aglDestroyPixelFormat(fmt);
150#else
151 QMacCocoaAutoReleasePool pool;
152 NSOpenGLPixelFormatAttribute attribs[] = { 0 };
153 NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
154 if (!fmt) {
155 qWarning("QGLTemporaryContext: Cannot find any visuals");
156 return;
157 }
158
159 d->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
160 if (!d->ctx)
161 qWarning("QGLTemporaryContext: Cannot create context");
162 else
163 [d->ctx makeCurrentContext];
164 [fmt release];
165#endif
166}
167
168QGLTemporaryContext::~QGLTemporaryContext()
169{
170 if (d->ctx) {
171#ifndef QT_MAC_USE_COCOA
172 aglSetCurrentContext(0);
173 aglDestroyContext(d->ctx);
174#else
175 [NSOpenGLContext clearCurrentContext];
176 [d->ctx release];
177#endif
178 }
179}
180
181bool QGLFormat::hasOpenGL()
182{
183 return true;
184}
185
186bool QGLFormat::hasOpenGLOverlays()
187{
188 return false;
189}
190
191bool QGLContext::chooseContext(const QGLContext *shareContext)
192{
193 QMacCocoaAutoReleasePool pool;
194 Q_D(QGLContext);
195 d->cx = 0;
196 d->vi = chooseMacVisual(0);
197 if (!d->vi)
198 return false;
199
200#ifndef QT_MAC_USE_COCOA
201 AGLPixelFormat fmt = (AGLPixelFormat)d->vi;
202 GLint res;
203 aglDescribePixelFormat(fmt, AGL_LEVEL, &res);
204 d->glFormat.setPlane(res);
205 if (deviceIsPixmap())
206 res = 0;
207 else
208 aglDescribePixelFormat(fmt, AGL_DOUBLEBUFFER, &res);
209 d->glFormat.setDoubleBuffer(res);
210 aglDescribePixelFormat(fmt, AGL_DEPTH_SIZE, &res);
211 d->glFormat.setDepth(res);
212 if (d->glFormat.depth())
213 d->glFormat.setDepthBufferSize(res);
214 aglDescribePixelFormat(fmt, AGL_RGBA, &res);
215 d->glFormat.setRgba(res);
216 aglDescribePixelFormat(fmt, AGL_RED_SIZE, &res);
217 d->glFormat.setRedBufferSize(res);
218 aglDescribePixelFormat(fmt, AGL_GREEN_SIZE, &res);
219 d->glFormat.setGreenBufferSize(res);
220 aglDescribePixelFormat(fmt, AGL_BLUE_SIZE, &res);
221 d->glFormat.setBlueBufferSize(res);
222 aglDescribePixelFormat(fmt, AGL_ALPHA_SIZE, &res);
223 d->glFormat.setAlpha(res);
224 if (d->glFormat.alpha())
225 d->glFormat.setAlphaBufferSize(res);
226 aglDescribePixelFormat(fmt, AGL_ACCUM_RED_SIZE, &res);
227 // Bug in Apple OpenGL (rdr://5015603), when we don't have an accumulation
228 // buffer, it still claims that we have a 16-bit one (which is pretty rare).
229 // So, we just assume we can never have a buffer that small.
230 d->glFormat.setAccum(res > 5);
231 if (d->glFormat.accum())
232 d->glFormat.setAccumBufferSize(res);
233 aglDescribePixelFormat(fmt, AGL_STENCIL_SIZE, &res);
234 d->glFormat.setStencil(res);
235 if (d->glFormat.stencil())
236 d->glFormat.setStencilBufferSize(res);
237 aglDescribePixelFormat(fmt, AGL_STEREO, &res);
238 d->glFormat.setStereo(res);
239 aglDescribePixelFormat(fmt, AGL_SAMPLE_BUFFERS_ARB, &res);
240 d->glFormat.setSampleBuffers(res);
241 if (d->glFormat.sampleBuffers()) {
242 aglDescribePixelFormat(fmt, AGL_SAMPLES_ARB, &res);
243 d->glFormat.setSamples(res);
244 }
245#else
246 NSOpenGLPixelFormat *fmt = static_cast<NSOpenGLPixelFormat *>(d->vi);
247
248 d->glFormat = QGLFormat();
249
250 // ### make sure to reset other options
251 d->glFormat.setDoubleBuffer(attribValue(fmt, NSOpenGLPFADoubleBuffer));
252
253 int depthSize = attribValue(fmt, NSOpenGLPFADepthSize);
254 d->glFormat.setDepth(depthSize > 0);
255 if (depthSize > 0)
256 d->glFormat.setDepthBufferSize(depthSize);
257
258 int alphaSize = attribValue(fmt, NSOpenGLPFAAlphaSize);
259 d->glFormat.setAlpha(alphaSize > 0);
260 if (alphaSize > 0)
261 d->glFormat.setAlphaBufferSize(alphaSize);
262
263 int accumSize = attribValue(fmt, NSOpenGLPFAAccumSize);
264 d->glFormat.setAccum(accumSize > 0);
265 if (accumSize > 0)
266 d->glFormat.setAccumBufferSize(accumSize);
267
268 int stencilSize = attribValue(fmt, NSOpenGLPFAStencilSize);
269 d->glFormat.setStencil(stencilSize > 0);
270 if (stencilSize > 0)
271 d->glFormat.setStencilBufferSize(stencilSize);
272
273 d->glFormat.setStereo(attribValue(fmt, NSOpenGLPFAStereo));
274
275 int sampleBuffers = attribValue(fmt, NSOpenGLPFASampleBuffers);
276 d->glFormat.setSampleBuffers(sampleBuffers);
277 if (sampleBuffers > 0)
278 d->glFormat.setSamples(attribValue(fmt, NSOpenGLPFASamples));
279#endif
280 if (shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) {
281 qWarning("QGLContext::chooseContext: Cannot share with invalid context");
282 shareContext = 0;
283 }
284
285 // sharing between rgba and color-index will give wrong colors
286 if (shareContext && (format().rgba() != shareContext->format().rgba()))
287 shareContext = 0;
288
289#ifndef QT_MAC_USE_COCOA
290 AGLContext ctx = aglCreateContext(fmt, (AGLContext) (shareContext ? shareContext->d_func()->cx : 0));
291#else
292 NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:fmt
293 shareContext:(shareContext ? static_cast<NSOpenGLContext *>(shareContext->d_func()->cx)
294 : 0)];
295#endif
296 if (!ctx) {
297#ifndef QT_MAC_USE_COCOA
298 GLenum err = aglGetError();
299 if (err == AGL_BAD_MATCH || err == AGL_BAD_CONTEXT) {
300 if (shareContext && shareContext->d_func()->cx) {
301 qWarning("QGLContext::chooseContext(): Context sharing mismatch!");
302 if (!(ctx = aglCreateContext(fmt, 0)))
303 return false;
304 shareContext = 0;
305 }
306 }
307#else
308 if (shareContext) {
309 ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
310 if (ctx) {
311 qWarning("QGLContext::chooseContext: Context sharing mismatch");
312 shareContext = 0;
313 }
314 }
315#endif
316 if (!ctx) {
317 qWarning("QGLContext::chooseContext: Unable to create QGLContext");
318 return false;
319 }
320 }
321 d->cx = ctx;
322 if (shareContext && shareContext->d_func()->cx) {
323 QGLContext *share = const_cast<QGLContext *>(shareContext);