source: trunk/src/opengl/qgl_mac.mm@ 755

Last change on this file since 755 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

File size: 31.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 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);
324 d->sharing = true;
325 share->d_func()->sharing = true;
326 }
327 if (deviceIsPixmap())
328 updatePaintDevice();
329
330 // vblank syncing
331 GLint interval = d->reqFormat.swapInterval();
332 if (interval != -1) {
333#ifndef QT_MAC_USE_COCOA
334 aglSetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval);
335 if (interval != 0)
336 aglEnable((AGLContext)d->cx, AGL_SWAP_INTERVAL);
337 else
338 aglDisable((AGLContext)d->cx, AGL_SWAP_INTERVAL);
339#else
340 [ctx setValues:&interval forParameter:NSOpenGLCPSwapInterval];
341#endif
342 }
343#ifndef QT_MAC_USE_COCOA
344 aglGetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval);
345#else
346 [ctx getValues:&interval forParameter:NSOpenGLCPSwapInterval];
347#endif
348 d->glFormat.setSwapInterval(interval);
349 return true;
350}
351
352void *QGLContextPrivate::tryFormat(const QGLFormat &format)
353{
354 static const int Max = 40;
355#ifndef QT_MAC_USE_COCOA
356 GLint attribs[Max], cnt = 0;
357 bool device_is_pixmap = (paintDevice->devType() == QInternal::Pixmap);
358
359 attribs[cnt++] = AGL_RGBA;
360 attribs[cnt++] = AGL_BUFFER_SIZE;
361 attribs[cnt++] = device_is_pixmap ? static_cast<QPixmap *>(paintDevice)->depth() : 32;
362 attribs[cnt++] = AGL_LEVEL;
363 attribs[cnt++] = format.plane();
364
365 if (format.redBufferSize() != -1) {
366 attribs[cnt++] = AGL_RED_SIZE;
367 attribs[cnt++] = format.redBufferSize();
368 }
369 if (format.greenBufferSize() != -1) {
370 attribs[cnt++] = AGL_GREEN_SIZE;
371 attribs[cnt++] = format.greenBufferSize();
372 }
373 if (format.blueBufferSize() != -1) {
374 attribs[cnt++] = AGL_BLUE_SIZE;
375 attribs[cnt++] = format.blueBufferSize();
376 }
377 if (device_is_pixmap) {
378 attribs[cnt++] = AGL_PIXEL_SIZE;
379 attribs[cnt++] = static_cast<QPixmap *>(paintDevice)->depth();
380 attribs[cnt++] = AGL_OFFSCREEN;
381 if (!format.alpha()) {
382 attribs[cnt++] = AGL_ALPHA_SIZE;
383 attribs[cnt++] = 8;
384 }
385 } else {
386 if (format.doubleBuffer())
387 attribs[cnt++] = AGL_DOUBLEBUFFER;
388 }
389
390 if (format.stereo())
391 attribs[cnt++] = AGL_STEREO;
392 if (format.alpha()) {
393 attribs[cnt++] = AGL_ALPHA_SIZE;
394 attribs[cnt++] = format.alphaBufferSize() == -1 ? 8 : format.alphaBufferSize();
395 }
396 if (format.stencil()) {
397 attribs[cnt++] = AGL_STENCIL_SIZE;
398 attribs[cnt++] = format.stencilBufferSize() == -1 ? 8 : format.stencilBufferSize();
399 }
400 if (format.depth()) {
401 attribs[cnt++] = AGL_DEPTH_SIZE;
402 attribs[cnt++] = format.depthBufferSize() == -1 ? 32 : format.depthBufferSize();
403 }
404 if (format.accum()) {
405 attribs[cnt++] = AGL_ACCUM_RED_SIZE;
406 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
407 attribs[cnt++] = AGL_ACCUM_BLUE_SIZE;
408 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
409 attribs[cnt++] = AGL_ACCUM_GREEN_SIZE;
410 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
411 attribs[cnt++] = AGL_ACCUM_ALPHA_SIZE;
412 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
413 }
414 if (format.sampleBuffers()) {
415 attribs[cnt++] = AGL_SAMPLE_BUFFERS_ARB;
416 attribs[cnt++] = 1;
417 attribs[cnt++] = AGL_SAMPLES_ARB;
418 attribs[cnt++] = format.samples() == -1 ? 4 : format.samples();
419 }
420
421 attribs[cnt] = AGL_NONE;
422 Q_ASSERT(cnt < Max);
423 return aglChoosePixelFormat(0, 0, attribs);
424#else
425 NSOpenGLPixelFormatAttribute attribs[Max];
426 int cnt = 0;
427 int devType = paintDevice->devType();
428 bool device_is_pixmap = (devType == QInternal::Pixmap);
429 int depth = device_is_pixmap ? static_cast<QPixmap *>(paintDevice)->depth() : 32;
430
431 attribs[cnt++] = NSOpenGLPFAColorSize;
432 attribs[cnt++] = depth;
433
434 if (device_is_pixmap) {
435 attribs[cnt++] = NSOpenGLPFAOffScreen;
436 } else {
437 if (format.doubleBuffer())
438 attribs[cnt++] = NSOpenGLPFADoubleBuffer;
439 }
440 if (glFormat.stereo())
441 attribs[cnt++] = NSOpenGLPFAStereo;
442 if (device_is_pixmap || format.alpha()) {
443 attribs[cnt++] = NSOpenGLPFAAlphaSize;
444 attribs[cnt++] = def(format.alphaBufferSize(), 8);
445 }
446 if (format.stencil()) {
447 attribs[cnt++] = NSOpenGLPFAStencilSize;
448 attribs[cnt++] = def(format.stencilBufferSize(), 8);
449 }
450 if (format.depth()) {
451 attribs[cnt++] = NSOpenGLPFADepthSize;
452 attribs[cnt++] = def(format.depthBufferSize(), 32);
453 }
454 if (format.accum()) {
455 attribs[cnt++] = NSOpenGLPFAAccumSize;
456 attribs[cnt++] = def(format.accumBufferSize(), 1);
457 }
458 if (format.sampleBuffers()) {
459 attribs[cnt++] = NSOpenGLPFASampleBuffers;
460 attribs[cnt++] = 1;
461 attribs[cnt++] = NSOpenGLPFASamples;
462 attribs[cnt++] = def(format.samples(), 4);
463 }
464
465 if (format.directRendering())
466 attribs[cnt++] = NSOpenGLPFAAccelerated;
467
468 if (devType == QInternal::Pbuffer)
469 attribs[cnt++] = NSOpenGLPFAPixelBuffer;
470
471 attribs[cnt] = 0;
472 Q_ASSERT(cnt < Max);
473 return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
474#endif
475}
476
477void QGLContextPrivate::clearDrawable()
478{
479 [static_cast<NSOpenGLContext *>(cx) clearDrawable];
480}
481
482/*!
483 \bold{Mac OS X only:} This virtual function tries to find a visual that
484 matches the format, reducing the demands if the original request
485 cannot be met.
486
487 The algorithm for reducing the demands of the format is quite
488 simple-minded, so override this method in your subclass if your
489 application has spcific requirements on visual selection.
490
491 The \a handle argument is always zero and is not used
492
493 \sa chooseContext()
494*/
495
496void *QGLContext::chooseMacVisual(GDHandle /* handle */)
497{
498 Q_D(QGLContext);
499
500 void *fmt = d->tryFormat(d->glFormat);
501 if (!fmt && d->glFormat.stereo()) {
502 d->glFormat.setStereo(false);
503 fmt = d->tryFormat(d->glFormat);
504 }
505 if (!fmt && d->glFormat.sampleBuffers()) {
506 d->glFormat.setSampleBuffers(false);
507 fmt = d->tryFormat(d->glFormat);
508 }
509 if (!fmt)
510 qWarning("QGLContext::chooseMacVisual: Unable to choose a pixel format");
511 return fmt;
512}
513
514void QGLContext::reset()
515{
516 Q_D(QGLContext);
517 if (!d->valid)
518 return;
519 d->cleanup();
520 doneCurrent();
521#ifndef QT_MAC_USE_COCOA
522 if (d->cx)
523 aglDestroyContext((AGLContext)d->cx);
524#else
525 QMacCocoaAutoReleasePool pool;
526 [static_cast<NSOpenGLContext *>(d->cx) release];
527#endif
528 d->cx = 0;
529#ifndef QT_MAC_USE_COCOA
530 if (d->vi)
531 aglDestroyPixelFormat((AGLPixelFormat)d->vi);
532#else
533 [static_cast<NSOpenGLPixelFormat *>(d->vi) release];
534#endif
535 d->vi = 0;
536 d->crWin = false;
537 d->sharing = false;
538 d->valid = false;
539 d->transpColor = QColor();
540 d->initDone = false;
541 QGLContextGroup::removeShare(this);
542}
543
544void QGLContext::makeCurrent()
545{
546 Q_D(QGLContext);
547
548 if (!d->valid) {
549 qWarning("QGLContext::makeCurrent: Cannot make invalid context current");
550 return;
551 }
552#ifndef QT_MAC_USE_COCOA
553 aglSetCurrentContext((AGLContext)d->cx);
554 if (d->update)
555 updatePaintDevice();
556#else
557 [static_cast<NSOpenGLContext *>(d->cx) makeCurrentContext];
558#endif
559 QGLContextPrivate::setCurrentContext(this);
560}
561
562#ifndef QT_MAC_USE_COCOA
563/*
564 Returns the effective scale factor for a widget. For this value to be
565 different than 1, the following must be true:
566 - The system scale factor must be greater than 1.
567 - The widget window must have WA_MacFrameworkScaled set.
568*/
569float qt_mac_get_scale_factor(QWidget *widget)
570{
571 if (!widget | !widget->window())
572 return 1;
573
574 if (widget->window()->testAttribute(Qt::WA_MacFrameworkScaled) == false)
575 return 1;
576
577 float systemScale = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 ? HIGetScaleFactor() : 1;
578 if (systemScale == float(1))
579 return 1;
580
581 return systemScale;
582}
583#endif
584
585/*! \internal
586*/
587void QGLContext::updatePaintDevice()
588{
589 Q_D(QGLContext);
590#ifndef QT_MAC_USE_COCOA
591 d->update = false;
592 if (d->paintDevice->devType() == QInternal::Widget) {
593 //get control information
594 QWidget *w = (QWidget *)d->paintDevice;
595 HIViewRef hiview = (HIViewRef)w->winId();
596 WindowRef window = HIViewGetWindow(hiview);
597#ifdef DEBUG_OPENGL_REGION_UPDATE
598 static int serial_no_gl = 0;
599 qDebug("[%d] %p setting on %s::%s %p/%p [%s]", ++serial_no_gl, w,
600 w->metaObject()->className(), w->objectName().toLatin1().constData(),
601 hiview, window, w->handle() ? "Inside" : "Outside");
602#endif
603
604 //update drawable
605 if (0 && w->isWindow() && w->isFullScreen()) {
606 aglSetDrawable((AGLContext)d->cx, 0);
607 aglSetFullScreen((AGLContext)d->cx, w->width(), w->height(), 0, QApplication::desktop()->screenNumber(w));
608 w->hide();
609 } else {
610 AGLDrawable old_draw = aglGetDrawable((AGLContext)d->cx), new_draw = GetWindowPort(window);
611 if (old_draw != new_draw)
612 aglSetDrawable((AGLContext)d->cx, new_draw);
613 }
614
615 float scale = qt_mac_get_scale_factor(w);
616
617 if (!w->isWindow()) {
618 QRegion clp = qt_mac_get_widget_rgn(w); //get drawable area
619
620#ifdef DEBUG_OPENGL_REGION_UPDATE
621 if (clp.isEmpty()) {
622 qDebug(" Empty area!");
623 } else {
624 QVector<QRect> rs = clp.rects();
625 for(int i = 0; i < rs.count(); i++)
626 qDebug(" %d %d %d %d", rs[i].x(), rs[i].y(), rs[i].width(), rs[i].height());
627 }
628#endif
629 //update the clip
630 if (!aglIsEnabled((AGLContext)d->cx, AGL_BUFFER_RECT))
631 aglEnable((AGLContext)d->cx, AGL_BUFFER_RECT);
632 if (clp.isEmpty()) {
633 GLint offs[4] = { 0, 0, 0, 0 };
634 aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs);
635 if (aglIsEnabled((AGLContext)d->cx, AGL_CLIP_REGION))
636 aglDisable((AGLContext)d->cx, AGL_CLIP_REGION);
637 } else {
638 HIPoint origin = { 0., 0. };
639 HIViewConvertPoint(&origin, HIViewRef(w->winId()), 0);
640 const GLint offs[4] = { qRound(origin.x),
641 w->window()->frameGeometry().height() * scale
642 - (qRound(origin.y) + w->height() * scale),
643 w->width() * scale, w->height() * scale};
644
645 RgnHandle region = clp.handle(true);
646
647 if (scale != float(1)) {
648 // Sacle the clip region by the scale factor
649 Rect regionBounds;
650 GetRegionBounds(region, &regionBounds);
651 Rect regionBoundsDest = regionBounds;
652 regionBoundsDest.bottom *= scale;
653 regionBoundsDest.right *= scale;
654 MapRgn(region, &regionBounds, &regionBoundsDest);
655 }
656
657 aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs);
658 aglSetInteger((AGLContext)d->cx, AGL_CLIP_REGION, (const GLint *)region);
659 if (!aglIsEnabled((AGLContext)d->cx, AGL_CLIP_REGION))
660 aglEnable((AGLContext)d->cx, AGL_CLIP_REGION);
661 }
662 } else {
663 // Set the buffer rect for top-level gl contexts when scaled.
664 if (scale != float(1)) {
665 aglEnable((AGLContext)d->cx, AGL_BUFFER_RECT);
666 const GLint offs[4] = { 0, 0, w->width() * scale , w->height() * scale};
667 aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs);
668 }
669 }
670 } else if (d->paintDevice->devType() == QInternal::Pixmap) {
671 QPixmap *pm = reinterpret_cast<QPixmap *>(d->paintDevice);
672
673 unsigned long qdformat = k32ARGBPixelFormat;
674 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
675 qdformat = k32BGRAPixelFormat;
676 Rect rect;
677 SetRect(&rect, 0, 0, pm->width(), pm->height());
678
679 GWorldPtr gworld;
680 NewGWorldFromPtr(&gworld, qdformat, &rect, 0, 0, 0,
681 reinterpret_cast<char *>(qt_mac_pixmap_get_base(pm)),
682 qt_mac_pixmap_get_bytes_per_line(pm));
683
684 PixMapHandle pixmapHandle = GetGWorldPixMap(gworld);
685 aglSetOffScreen(reinterpret_cast<AGLContext>(d->cx), pm->width(), pm->height(),
686 GetPixRowBytes(pixmapHandle), GetPixBaseAddr(pixmapHandle));
687 } else {
688 qWarning("QGLContext::updatePaintDevice(): Not sure how to render OpenGL on this device!");
689 }
690 aglUpdateContext((AGLContext)d->cx);
691
692#else
693 QMacCocoaAutoReleasePool pool;
694
695 if (d->paintDevice->devType() == QInternal::Widget) {
696 //get control information
697 QWidget *w = (QWidget *)d->paintDevice;
698 NSView *view = qt_mac_nativeview_for(w);
699
700 // ideally we would use QWidget::isVisible(), but we get "invalid drawable" errors
701 if (![(NSWindow *)qt_mac_window_for(w) isVisible])
702 return;
703 if ([static_cast<NSOpenGLContext *>(d->cx) view] != view && ![view isHidden])
704 [static_cast<NSOpenGLContext *>(d->cx) setView:view];
705 } else if (d->paintDevice->devType() == QInternal::Pixmap) {
706 const QPixmap *pm = static_cast<const QPixmap *>(d->paintDevice);
707 [static_cast<NSOpenGLContext *>(d->cx) setOffScreen:qt_mac_pixmap_get_base(pm)
708 width:pm->width()
709 height:pm->height()
710 rowbytes:qt_mac_pixmap_get_bytes_per_line(pm)];
711 } else {
712 qWarning("QGLContext::updatePaintDevice: Not sure how to render OpenGL on this device");
713 }
714 [static_cast<NSOpenGLContext *>(d->cx) update];
715#endif
716}
717
718void QGLContext::doneCurrent()
719{
720
721 if (
722#ifndef QT_MAC_USE_COCOA
723 aglGetCurrentContext() != (AGLContext) d_func()->cx
724#else
725 [NSOpenGLContext currentContext] != d_func()->cx
726#endif
727 )
728 return;
729
730 QGLContextPrivate::setCurrentContext(0);
731#ifndef QT_MAC_USE_COCOA
732 aglSetCurrentContext(0);
733#else
734 [NSOpenGLContext clearCurrentContext];
735#endif
736}
737
738void QGLContext::swapBuffers() const
739{
740 Q_D(const QGLContext);
741 if (!d->valid)
742 return;
743#ifndef QT_MAC_USE_COCOA
744 aglSwapBuffers((AGLContext)d->cx);
745#else
746 [static_cast<NSOpenGLContext *>(d->cx) flushBuffer];
747#endif