Warning: That file was not part of the compilation database. It may have many parsing errors.

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 "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
117
118/*
119 QGLTemporaryContext implementation
120*/
121
122class QGLTemporaryContextPrivate
123{
124public:
125#ifndef QT_MAC_USE_COCOA
126 AGLContext ctx;
127#else
128 NSOpenGLContext *ctx;
129#endif
130};
131
132QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
133 : d(new QGLTemporaryContextPrivate)
134{
135 d->ctx = 0;
136#ifndef QT_MAC_USE_COCOA
137 GLint attribs[] = {AGL_RGBA, AGL_NONE};
138 AGLPixelFormat fmt = aglChoosePixelFormat(0, 0, attribs);
139 if (!fmt) {
140 qDebug("QGLTemporaryContext: Couldn't find any RGB visuals");
141 return;
142 }
143 d->ctx = aglCreateContext(fmt, 0);
144 if (!d->ctx)
145 qDebug("QGLTemporaryContext: Unable to create context");
146 else
147 aglSetCurrentContext(d->ctx);
148 aglDestroyPixelFormat(fmt);
149#else
150 QMacCocoaAutoReleasePool pool;
151 NSOpenGLPixelFormatAttribute attribs[] = { 0 };
152 NSOpenGLPixelFormat *fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
153 if (!fmt) {
154 qWarning("QGLTemporaryContext: Cannot find any visuals");
155 return;
156 }
157
158 d->ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
159 if (!d->ctx)
160 qWarning("QGLTemporaryContext: Cannot create context");
161 else
162 [d->ctx makeCurrentContext];
163 [fmt release];
164#endif
165}
166
167QGLTemporaryContext::~QGLTemporaryContext()
168{
169 if (d->ctx) {
170#ifndef QT_MAC_USE_COCOA
171 aglSetCurrentContext(0);
172 aglDestroyContext(d->ctx);
173#else
174 [NSOpenGLContext clearCurrentContext];
175 [d->ctx release];
176#endif
177 }
178}
179
180bool QGLFormat::hasOpenGL()
181{
182 return true;
183}
184
185bool QGLFormat::hasOpenGLOverlays()
186{
187 return false;
188}
189
190bool QGLContext::chooseContext(const QGLContext *shareContext)
191{
192 QMacCocoaAutoReleasePool pool;
193 Q_D(QGLContext);
194 d->cx = 0;
195 d->vi = chooseMacVisual(0);
196 if (!d->vi)
197 return false;
198
199#ifndef QT_MAC_USE_COCOA
200 AGLPixelFormat fmt = (AGLPixelFormat)d->vi;
201 GLint res;
202 aglDescribePixelFormat(fmt, AGL_LEVEL, &res);
203 d->glFormat.setPlane(res);
204 if (deviceIsPixmap())
205 res = 0;
206 else
207 aglDescribePixelFormat(fmt, AGL_DOUBLEBUFFER, &res);
208 d->glFormat.setDoubleBuffer(res);
209 aglDescribePixelFormat(fmt, AGL_DEPTH_SIZE, &res);
210 d->glFormat.setDepth(res);
211 if (d->glFormat.depth())
212 d->glFormat.setDepthBufferSize(res);
213 aglDescribePixelFormat(fmt, AGL_RGBA, &res);
214 d->glFormat.setRgba(res);
215 aglDescribePixelFormat(fmt, AGL_RED_SIZE, &res);
216 d->glFormat.setRedBufferSize(res);
217 aglDescribePixelFormat(fmt, AGL_GREEN_SIZE, &res);
218 d->glFormat.setGreenBufferSize(res);
219 aglDescribePixelFormat(fmt, AGL_BLUE_SIZE, &res);
220 d->glFormat.setBlueBufferSize(res);
221 aglDescribePixelFormat(fmt, AGL_ALPHA_SIZE, &res);
222 d->glFormat.setAlpha(res);
223 if (d->glFormat.alpha())
224 d->glFormat.setAlphaBufferSize(res);
225 aglDescribePixelFormat(fmt, AGL_ACCUM_RED_SIZE, &res);
226 // Bug in Apple OpenGL (rdr://5015603), when we don't have an accumulation
227 // buffer, it still claims that we have a 16-bit one (which is pretty rare).
228 // So, we just assume we can never have a buffer that small.
229 d->glFormat.setAccum(res > 5);
230 if (d->glFormat.accum())
231 d->glFormat.setAccumBufferSize(res);
232 aglDescribePixelFormat(fmt, AGL_STENCIL_SIZE, &res);
233 d->glFormat.setStencil(res);
234 if (d->glFormat.stencil())
235 d->glFormat.setStencilBufferSize(res);
236 aglDescribePixelFormat(fmt, AGL_STEREO, &res);
237 d->glFormat.setStereo(res);
238 aglDescribePixelFormat(fmt, AGL_SAMPLE_BUFFERS_ARB, &res);
239 d->glFormat.setSampleBuffers(res);
240 if (d->glFormat.sampleBuffers()) {
241 aglDescribePixelFormat(fmt, AGL_SAMPLES_ARB, &res);
242 d->glFormat.setSamples(res);
243 }
244#else
245 NSOpenGLPixelFormat *fmt = static_cast<NSOpenGLPixelFormat *>(d->vi);
246
247 d->glFormat = QGLFormat();
248
249 // ### make sure to reset other options
250 d->glFormat.setDoubleBuffer(attribValue(fmt, NSOpenGLPFADoubleBuffer));
251
252 int depthSize = attribValue(fmt, NSOpenGLPFADepthSize);
253 d->glFormat.setDepth(depthSize > 0);
254 if (depthSize > 0)
255 d->glFormat.setDepthBufferSize(depthSize);
256
257 int alphaSize = attribValue(fmt, NSOpenGLPFAAlphaSize);
258 d->glFormat.setAlpha(alphaSize > 0);
259 if (alphaSize > 0)
260 d->glFormat.setAlphaBufferSize(alphaSize);
261
262 int accumSize = attribValue(fmt, NSOpenGLPFAAccumSize);
263 d->glFormat.setAccum(accumSize > 0);
264 if (accumSize > 0)
265 d->glFormat.setAccumBufferSize(accumSize);
266
267 int stencilSize = attribValue(fmt, NSOpenGLPFAStencilSize);
268 d->glFormat.setStencil(stencilSize > 0);
269 if (stencilSize > 0)
270 d->glFormat.setStencilBufferSize(stencilSize);
271
272 d->glFormat.setStereo(attribValue(fmt, NSOpenGLPFAStereo));
273
274 int sampleBuffers = attribValue(fmt, NSOpenGLPFASampleBuffers);
275 d->glFormat.setSampleBuffers(sampleBuffers);
276 if (sampleBuffers > 0)
277 d->glFormat.setSamples(attribValue(fmt, NSOpenGLPFASamples));
278#endif
279 if (shareContext && (!shareContext->isValid() || !shareContext->d_func()->cx)) {
280 qWarning("QGLContext::chooseContext: Cannot share with invalid context");
281 shareContext = 0;
282 }
283
284 // sharing between rgba and color-index will give wrong colors
285 if (shareContext && (format().rgba() != shareContext->format().rgba()))
286 shareContext = 0;
287
288#ifndef QT_MAC_USE_COCOA
289 AGLContext ctx = aglCreateContext(fmt, (AGLContext) (shareContext ? shareContext->d_func()->cx : 0));
290#else
291 NSOpenGLContext *ctx = [[NSOpenGLContext alloc] initWithFormat:fmt
292 shareContext:(shareContext ? static_cast<NSOpenGLContext *>(shareContext->d_func()->cx)
293 : 0)];
294#endif
295 if (!ctx) {
296#ifndef QT_MAC_USE_COCOA
297 GLenum err = aglGetError();
298 if (err == AGL_BAD_MATCH || err == AGL_BAD_CONTEXT) {
299 if (shareContext && shareContext->d_func()->cx) {
300 qWarning("QGLContext::chooseContext(): Context sharing mismatch!");
301 if (!(ctx = aglCreateContext(fmt, 0)))
302 return false;
303 shareContext = 0;
304 }
305 }
306#else
307 if (shareContext) {
308 ctx = [[NSOpenGLContext alloc] initWithFormat:fmt shareContext:0];
309 if (ctx) {
310 qWarning("QGLContext::chooseContext: Context sharing mismatch");
311 shareContext = 0;
312 }
313 }
314#endif
315 if (!ctx) {
316 qWarning("QGLContext::chooseContext: Unable to create QGLContext");
317 return false;
318 }
319 }
320 d->cx = ctx;
321 if (shareContext && shareContext->d_func()->cx) {
322 QGLContext *share = const_cast<QGLContext *>(shareContext);
323 d->sharing = true;
324 share->d_func()->sharing = true;
325 }
326 if (deviceIsPixmap())
327 updatePaintDevice();
328
329 // vblank syncing
330 GLint interval = d->reqFormat.swapInterval();
331 if (interval != -1) {
332#ifndef QT_MAC_USE_COCOA
333 aglSetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval);
334 if (interval != 0)
335 aglEnable((AGLContext)d->cx, AGL_SWAP_INTERVAL);
336 else
337 aglDisable((AGLContext)d->cx, AGL_SWAP_INTERVAL);
338#else
339 [ctx setValues:&interval forParameter:NSOpenGLCPSwapInterval];
340#endif
341 }
342#ifndef QT_MAC_USE_COCOA
343 aglGetInteger((AGLContext)d->cx, AGL_SWAP_INTERVAL, &interval);
344#else
345 [ctx getValues:&interval forParameter:NSOpenGLCPSwapInterval];
346#endif
347 d->glFormat.setSwapInterval(interval);
348 return true;
349}
350
351void *QGLContextPrivate::tryFormat(const QGLFormat &format)
352{
353 static const int Max = 40;
354#ifndef QT_MAC_USE_COCOA
355 GLint attribs[Max], cnt = 0;
356 bool device_is_pixmap = (paintDevice->devType() == QInternal::Pixmap);
357
358 attribs[cnt++] = AGL_RGBA;
359 attribs[cnt++] = AGL_BUFFER_SIZE;
360 attribs[cnt++] = device_is_pixmap ? static_cast<QPixmap *>(paintDevice)->depth() : 32;
361 attribs[cnt++] = AGL_LEVEL;
362 attribs[cnt++] = format.plane();
363
364 if (format.redBufferSize() != -1) {
365 attribs[cnt++] = AGL_RED_SIZE;
366 attribs[cnt++] = format.redBufferSize();
367 }
368 if (format.greenBufferSize() != -1) {
369 attribs[cnt++] = AGL_GREEN_SIZE;
370 attribs[cnt++] = format.greenBufferSize();
371 }
372 if (format.blueBufferSize() != -1) {
373 attribs[cnt++] = AGL_BLUE_SIZE;
374 attribs[cnt++] = format.blueBufferSize();
375 }
376 if (device_is_pixmap) {
377 attribs[cnt++] = AGL_PIXEL_SIZE;
378 attribs[cnt++] = static_cast<QPixmap *>(paintDevice)->depth();
379 attribs[cnt++] = AGL_OFFSCREEN;
380 if (!format.alpha()) {
381 attribs[cnt++] = AGL_ALPHA_SIZE;
382 attribs[cnt++] = 8;
383 }
384 } else {
385 if (format.doubleBuffer())
386 attribs[cnt++] = AGL_DOUBLEBUFFER;
387 }
388
389 if (format.stereo())
390 attribs[cnt++] = AGL_STEREO;
391 if (format.alpha()) {
392 attribs[cnt++] = AGL_ALPHA_SIZE;
393 attribs[cnt++] = format.alphaBufferSize() == -1 ? 8 : format.alphaBufferSize();
394 }
395 if (format.stencil()) {
396 attribs[cnt++] = AGL_STENCIL_SIZE;
397 attribs[cnt++] = format.stencilBufferSize() == -1 ? 8 : format.stencilBufferSize();
398 }
399 if (format.depth()) {
400 attribs[cnt++] = AGL_DEPTH_SIZE;
401 attribs[cnt++] = format.depthBufferSize() == -1 ? 32 : format.depthBufferSize();
402 }
403 if (format.accum()) {
404 attribs[cnt++] = AGL_ACCUM_RED_SIZE;
405 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
406 attribs[cnt++] = AGL_ACCUM_BLUE_SIZE;
407 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
408 attribs[cnt++] = AGL_ACCUM_GREEN_SIZE;
409 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
410 attribs[cnt++] = AGL_ACCUM_ALPHA_SIZE;
411 attribs[cnt++] = format.accumBufferSize() == -1 ? 1 : format.accumBufferSize();
412 }
413 if (format.sampleBuffers()) {
414 attribs[cnt++] = AGL_SAMPLE_BUFFERS_ARB;
415 attribs[cnt++] = 1;
416 attribs[cnt++] = AGL_SAMPLES_ARB;
417 attribs[cnt++] = format.samples() == -1 ? 4 : format.samples();
418 }
419
420 attribs[cnt] = AGL_NONE;
421 Q_ASSERT(cnt < Max);
422 return aglChoosePixelFormat(0, 0, attribs);
423#else
424 NSOpenGLPixelFormatAttribute attribs[Max];
425 int cnt = 0;
426 int devType = paintDevice->devType();
427 bool device_is_pixmap = (devType == QInternal::Pixmap);
428 int depth = device_is_pixmap ? static_cast<QPixmap *>(paintDevice)->depth() : 32;
429
430 attribs[cnt++] = NSOpenGLPFAColorSize;
431 attribs[cnt++] = depth;
432
433 if (device_is_pixmap) {
434 attribs[cnt++] = NSOpenGLPFAOffScreen;
435 } else {
436 if (format.doubleBuffer())
437 attribs[cnt++] = NSOpenGLPFADoubleBuffer;
438 }
439 if (glFormat.stereo())
440 attribs[cnt++] = NSOpenGLPFAStereo;
441 if (device_is_pixmap || format.alpha()) {
442 attribs[cnt++] = NSOpenGLPFAAlphaSize;
443 attribs[cnt++] = def(format.alphaBufferSize(), 8);
444 }
445 if (format.stencil()) {
446 attribs[cnt++] = NSOpenGLPFAStencilSize;
447 attribs[cnt++] = def(format.stencilBufferSize(), 8);
448 }
449 if (format.depth()) {
450 attribs[cnt++] = NSOpenGLPFADepthSize;
451 attribs[cnt++] = def(format.depthBufferSize(), 32);
452 }
453 if (format.accum()) {
454 attribs[cnt++] = NSOpenGLPFAAccumSize;
455 attribs[cnt++] = def(format.accumBufferSize(), 1);
456 }
457 if (format.sampleBuffers()) {
458 attribs[cnt++] = NSOpenGLPFASampleBuffers;
459 attribs[cnt++] = 1;
460 attribs[cnt++] = NSOpenGLPFASamples;
461 attribs[cnt++] = def(format.samples(), 4);
462 }
463
464 if (devType == QInternal::Pbuffer)
465 attribs[cnt++] = NSOpenGLPFAPixelBuffer;
466
467 attribs[cnt] = 0;
468 Q_ASSERT(cnt < Max);
469 return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
470#endif
471}
472
473void QGLContextPrivate::clearDrawable()
474{
475 [static_cast<NSOpenGLContext *>(cx) clearDrawable];
476}
477
478/*!
479 \bold{Mac OS X only:} This virtual function tries to find a visual that
480 matches the format, reducing the demands if the original request
481 cannot be met.
482
483 The algorithm for reducing the demands of the format is quite
484 simple-minded, so override this method in your subclass if your
485 application has spcific requirements on visual selection.
486
487 The \a handle argument is always zero and is not used
488
489 \sa chooseContext()
490*/
491
492void *QGLContext::chooseMacVisual(GDHandle /* handle */)
493{
494 Q_D(QGLContext);
495
496 void *fmt = d->tryFormat(d->glFormat);
497 if (!fmt && d->glFormat.stereo()) {
498 d->glFormat.setStereo(false);
499 fmt = d->tryFormat(d->glFormat);
500 }
501 if (!fmt && d->glFormat.sampleBuffers()) {
502 d->glFormat.setSampleBuffers(false);
503 fmt = d->tryFormat(d->glFormat);
504 }
505 if (!fmt)
506 qWarning("QGLContext::chooseMacVisual: Unable to choose a pixel format");
507 return fmt;
508}
509
510void QGLContext::reset()
511{
512 Q_D(QGLContext);
513 if (!d->valid)
514 return;
515 d->cleanup();
516 doneCurrent();
517#ifndef QT_MAC_USE_COCOA
518 if (d->cx)
519 aglDestroyContext((AGLContext)d->cx);
520#else
521 QMacCocoaAutoReleasePool pool;
522 [static_cast<NSOpenGLContext *>(d->cx) release];
523#endif
524 d->cx = 0;
525#ifndef QT_MAC_USE_COCOA
526 if (d->vi)
527 aglDestroyPixelFormat((AGLPixelFormat)d->vi);
528#else
529 [static_cast<NSOpenGLPixelFormat *>(d->vi) release];
530#endif
531 d->vi = 0;
532 d->crWin = false;
533 d->sharing = false;
534 d->valid = false;
535 d->transpColor = QColor();
536 d->initDone = false;
537 QGLContextGroup::removeShare(this);
538}
539
540void QGLContext::makeCurrent()
541{
542 Q_D(QGLContext);
543
544 if (!d->valid) {
545 qWarning("QGLContext::makeCurrent: Cannot make invalid context current");
546 return;
547 }
548#ifndef QT_MAC_USE_COCOA
549 aglSetCurrentContext((AGLContext)d->cx);
550 if (d->update)
551 updatePaintDevice();
552#else
553 [static_cast<NSOpenGLContext *>(d->cx) makeCurrentContext];
554#endif
555 QGLContextPrivate::setCurrentContext(this);
556}
557
558#ifndef QT_MAC_USE_COCOA
559/*
560 Returns the effective scale factor for a widget. For this value to be
561 different than 1, the following must be true:
562 - The system scale factor must be greater than 1.
563 - The widget window must have WA_MacFrameworkScaled set.
564*/
565float qt_mac_get_scale_factor(QWidget *widget)
566{
567 if (!widget | !widget->window())
568 return 1;
569
570 if (widget->window()->testAttribute(Qt::WA_MacFrameworkScaled) == false)
571 return 1;
572
573 float systemScale = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4 ? HIGetScaleFactor() : 1;
574 if (systemScale == float(1))
575 return 1;
576
577 return systemScale;
578}
579#endif
580
581/*! \internal
582*/
583void QGLContext::updatePaintDevice()
584{
585 Q_D(QGLContext);
586#ifndef QT_MAC_USE_COCOA
587 d->update = false;
588 if (d->paintDevice->devType() == QInternal::Widget) {
589 //get control information
590 QWidget *w = (QWidget *)d->paintDevice;
591 HIViewRef hiview = (HIViewRef)w->winId();
592 WindowRef window = HIViewGetWindow(hiview);
593#ifdef DEBUG_OPENGL_REGION_UPDATE
594 static int serial_no_gl = 0;
595 qDebug("[%d] %p setting on %s::%s %p/%p [%s]", ++serial_no_gl, w,
596 w->metaObject()->className(), w->objectName().toLatin1().constData(),
597 hiview, window, w->handle() ? "Inside" : "Outside");
598#endif
599
600 //update drawable
601 if (0 && w->isWindow() && w->isFullScreen()) {
602 aglSetDrawable((AGLContext)d->cx, 0);
603 aglSetFullScreen((AGLContext)d->cx, w->width(), w->height(), 0, QApplication::desktop()->screenNumber(w));
604 w->hide();
605 } else {
606 AGLDrawable old_draw = aglGetDrawable((AGLContext)d->cx), new_draw = GetWindowPort(window);
607 if (old_draw != new_draw)
608 aglSetDrawable((AGLContext)d->cx, new_draw);
609 }
610
611 float scale = qt_mac_get_scale_factor(w);
612
613 if (!w->isWindow()) {
614 QRegion clp = qt_mac_get_widget_rgn(w); //get drawable area
615
616#ifdef DEBUG_OPENGL_REGION_UPDATE
617 if (clp.isEmpty()) {
618 qDebug(" Empty area!");
619 } else {
620 QVector<QRect> rs = clp.rects();
621 for(int i = 0; i < rs.count(); i++)
622 qDebug(" %d %d %d %d", rs[i].x(), rs[i].y(), rs[i].width(), rs[i].height());
623 }
624#endif
625 //update the clip
626 if (!aglIsEnabled((AGLContext)d->cx, AGL_BUFFER_RECT))
627 aglEnable((AGLContext)d->cx, AGL_BUFFER_RECT);
628 if (clp.isEmpty()) {
629 GLint offs[4] = { 0, 0, 0, 0 };
630 aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs);
631 if (aglIsEnabled((AGLContext)d->cx, AGL_CLIP_REGION))
632 aglDisable((AGLContext)d->cx, AGL_CLIP_REGION);
633 } else {
634 HIPoint origin = { 0., 0. };
635 HIViewConvertPoint(&origin, HIViewRef(w->winId()), 0);
636 const GLint offs[4] = { qRound(origin.x),
637 w->window()->frameGeometry().height() * scale
638 - (qRound(origin.y) + w->height() * scale),
639 w->width() * scale, w->height() * scale};
640
641 RgnHandle region = clp.handle(true);
642
643 if (scale != float(1)) {
644 // Sacle the clip region by the scale factor
645 Rect regionBounds;
646 GetRegionBounds(region, &regionBounds);
647 Rect regionBoundsDest = regionBounds;
648 regionBoundsDest.bottom *= scale;
649 regionBoundsDest.right *= scale;
650 MapRgn(region, &regionBounds, &regionBoundsDest);
651 }
652
653 aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs);
654 aglSetInteger((AGLContext)d->cx, AGL_CLIP_REGION, (const GLint *)region);
655 if (!aglIsEnabled((AGLContext)d->cx, AGL_CLIP_REGION))
656 aglEnable((AGLContext)d->cx, AGL_CLIP_REGION);
657 }
658 } else {
659 // Set the buffer rect for top-level gl contexts when scaled.
660 if (scale != float(1)) {
661 aglEnable((AGLContext)d->cx, AGL_BUFFER_RECT);
662 const GLint offs[4] = { 0, 0, w->width() * scale , w->height() * scale};
663 aglSetInteger((AGLContext)d->cx, AGL_BUFFER_RECT, offs);
664 }
665 }
666 } else if (d->paintDevice->devType() == QInternal::Pixmap) {
667 QPixmap *pm = reinterpret_cast<QPixmap *>(d->paintDevice);
668
669 unsigned long qdformat = k32ARGBPixelFormat;
670 if (QSysInfo::ByteOrder == QSysInfo::LittleEndian)
671 qdformat = k32BGRAPixelFormat;
672 Rect rect;
673 SetRect(&rect, 0, 0, pm->width(), pm->height());
674
675 GWorldPtr gworld;
676 NewGWorldFromPtr(&gworld, qdformat, &rect, 0, 0, 0,
677 reinterpret_cast<char *>(qt_mac_pixmap_get_base(pm)),
678 qt_mac_pixmap_get_bytes_per_line(pm));
679
680 PixMapHandle pixmapHandle = GetGWorldPixMap(gworld);
681 aglSetOffScreen(reinterpret_cast<AGLContext>(d->cx), pm->width(), pm->height(),
682 GetPixRowBytes(pixmapHandle), GetPixBaseAddr(pixmapHandle));
683 } else {
684 qWarning("QGLContext::updatePaintDevice(): Not sure how to render OpenGL on this device!");
685 }
686 aglUpdateContext((AGLContext)d->cx);
687
688#else
689 QMacCocoaAutoReleasePool pool;
690
691 if (d->paintDevice->devType() == QInternal::Widget) {
692 //get control information
693 QWidget *w = (QWidget *)d->paintDevice;
694 NSView *view = qt_mac_nativeview_for(w);
695
696 // Trying to attach the GL context to the NSView will fail with
697 // "invalid drawable" if done too soon, but we have to make sure
698 // the connection is made before the first paint event. Using
699 // the NSView do to this check fails as the NSView is visible
700 // before it's safe to connect, and using the NSWindow fails as
701 // the NSWindow will become visible after the first paint event.
702 // This leaves us with the QWidget, who's visible state seems
703 // to match the point in time when it's safe to connect.
704 if (!w || !w->isVisible())
705 return; // Not safe to attach GL context to view yet
706
707 if ([static_cast<NSOpenGLContext *>(d->cx) view] != view && ![view isHidden])
708 [static_cast<NSOpenGLContext *>(d->cx) setView:view];
709 } else if (d->paintDevice->devType() == QInternal::Pixmap) {
710 const QPixmap *pm = static_cast<const QPixmap *>(d->paintDevice);
711 [static_cast<NSOpenGLContext *>(d->cx) setOffScreen:qt_mac_pixmap_get_base(pm)
712 width:pm->width()
713 height:pm->height()
714 rowbytes:qt_mac_pixmap_get_bytes_per_line(pm)];
715 } else {
716 qWarning("QGLContext::updatePaintDevice: Not sure how to render OpenGL on this device");
717 }
718 [static_cast<NSOpenGLContext *>(d->cx) update];
719#endif
720}
721
722void QGLContext::doneCurrent()
723{
724
725 if (
726#ifndef QT_MAC_USE_COCOA
727 aglGetCurrentContext() != (AGLContext) d_func()->cx
728#else
729 [NSOpenGLContext currentContext] != d_func()->cx
730#endif
731 )
732 return;
733
734 QGLContextPrivate::setCurrentContext(0);
735#ifndef QT_MAC_USE_COCOA
736 aglSetCurrentContext(0);
737#else
738 [NSOpenGLContext clearCurrentContext];
739#endif
740}
741
742void QGLContext::swapBuffers() const
743{
744 Q_D(const QGLContext);
745 if (!d->valid)
746 return;
747#ifndef QT_MAC_USE_COCOA
748 aglSwapBuffers((AGLContext)d->cx);
749#else
750 [static_cast<NSOpenGLContext *>(d->cx) flushBuffer];
751#endif
752}
753
754QColor QGLContext::overlayTransparentColor() const
755{
756 return QColor(0, 0, 0); // Invalid color
757}
758
759#ifndef QT_MAC_USE_COCOA
760static QColor cmap[256];
761static bool cmap_init = false;
762#endif
763uint QGLContext::colorIndex(const QColor &c) const
764{
765#ifndef QT_MAC_USE_COCOA
766 int ret = -1;
767 if(!cmap_init) {
768 cmap_init = true;
769 for(int i = 0; i < 256; i++)
770 cmap[i] = QColor();
771 } else {
772 for(int i = 0; i < 256; i++) {
773 if(cmap[i].isValid() && cmap[i] == c) {
774 ret = i;
775 break;
776 }
777 }
778 }
779 if(ret == -1) {
780 for(ret = 0; ret < 256; ret++)
781 if(!cmap[ret].isValid())
782 break;
783 if(ret == 256) {
784 ret = -1;
785 qWarning("QGLContext::colorIndex(): Internal error!");
786 } else {
787 cmap[ret] = c;
788
789 GLint vals[4];
790 vals[0] = ret;
791 vals[1] = c.red();
792 vals[2] = c.green();
793 vals[3] = c.blue();
794 aglSetInteger((AGLContext)d_func()->cx, AGL_COLORMAP_ENTRY, vals);
795 }
796 }
797 return (uint)(ret == -1 ? 0 : ret);
798#else
799 Q_UNUSED(c);
800 return 0;
801#endif
802}
803
804void QGLContext::generateFontDisplayLists(const QFont & /* fnt */, int /* listBase */)
805{
806}
807
808static CFBundleRef qt_getOpenGLBundle()
809{
810 CFBundleRef bundle = 0;
811 CFStringRef urlString = QCFString::toCFStringRef(QLatin1String("/System/Library/Frameworks/OpenGL.framework"));
812 QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
813 urlString, kCFURLPOSIXPathStyle, false);
814 if (url)
815 bundle = CFBundleCreate(kCFAllocatorDefault, url);
816 CFRelease(urlString);
817 return bundle;
818}
819
820void *QGLContext::getProcAddress(const QString &proc) const
821{
822 CFStringRef procName = QCFString(proc).toCFStringRef(proc);
823 void *result = CFBundleGetFunctionPointerForName(QCFType<CFBundleRef>(qt_getOpenGLBundle()),
824 procName);
825 CFRelease(procName);
826 return result;
827}
828#ifndef QT_MAC_USE_COCOA
829/*****************************************************************************
830 QGLWidget AGL-specific code
831 *****************************************************************************/
832
833/****************************************************************************
834 Hacks to glue AGL to an HIView
835 ***************************************************************************/
836QRegion qt_mac_get_widget_rgn(const QWidget *widget)
837{
838 if(!widget->isVisible() || widget->isMinimized())
839 return QRegion();
840 const QRect wrect = QRect(qt_mac_posInWindow(widget), widget->size());
841 if(!wrect.isValid())
842 return QRegion();
843
844 RgnHandle macr = qt_mac_get_rgn();
845 GetControlRegion((HIViewRef)widget->winId(), kControlStructureMetaPart, macr);
846 OffsetRgn(macr, wrect.x(), wrect.y());
847 QRegion ret = qt_mac_convert_mac_region(macr);
848
849 QPoint clip_pos = wrect.topLeft();
850 for(const QWidget *last_clip = 0, *clip = widget; clip; last_clip = clip, clip = clip->parentWidget()) {
851 if(clip != widget) {
852 GetControlRegion((HIViewRef)clip->winId(), kControlStructureMetaPart, macr);
853 OffsetRgn(macr, clip_pos.x(), clip_pos.y());
854 ret &= qt_mac_convert_mac_region(macr);
855 }
856 const QObjectList &children = clip->children();
857 for(int i = children.size()-1; i >= 0; --i) {
858 if(QWidget *child = qobject_cast<QWidget*>(children.at(i))) {
859 if(child == last_clip)
860 break;
861
862 // This check may seem weird, but when we are using a unified toolbar
863 // The widget is actually being owned by that toolbar and not by Qt.
864 // This means that the geometry it reports will be wrong
865 // and will accidentally cause problems when calculating the region
866 // So, it is better to skip these widgets since they aren't the hierarchy
867 // anyway.
868 if (HIViewGetSuperview(HIViewRef(child->winId())) != HIViewRef(clip->winId()))
869 continue;
870
871 if(child->isVisible() && !child->isMinimized() && !child->isTopLevel()) {
872 const QRect childRect = QRect(clip_pos+child->pos(), child->size());
873 if(childRect.isValid() && wrect.intersects(childRect)) {
874 GetControlRegion((HIViewRef)child->winId(), kControlStructureMetaPart, macr);
875 OffsetRgn(macr, childRect.x(), childRect.y());
876 ret -= qt_mac_convert_mac_region(macr);
877 }
878 }
879 }
880 }
881 if(clip->isWindow())
882 break;
883 clip_pos -= clip->pos();
884 }
885 qt_mac_dispose_rgn(macr);
886 return ret;
887}
888
889#endif
890
891void QGLWidget::setMouseTracking(bool enable)
892{
893 QWidget::setMouseTracking(enable);
894}
895
896void QGLWidget::resizeEvent(QResizeEvent *)
897{
898 Q_D(QGLWidget);
899 if (!isValid())
900 return;
901#ifndef QT_MAC_USE_COCOA
902 if (!isWindow())
903 d->glcx->d_func()->update = true;
904#endif
905 makeCurrent();
906 if (!d->glcx->initialized())
907 glInit();
908#ifdef QT_MAC_USE_COCOA
909 d->glcx->updatePaintDevice();
910#endif
911#ifndef QT_MAC_USE_COCOA
912 float scale = qt_mac_get_scale_factor(this);
913 resizeGL(width() * scale, height() * scale);
914#else
915 resizeGL(width(), height());
916#endif
917}
918
919const QGLContext* QGLWidget::overlayContext() const
920{
921 return 0;
922}
923
924void QGLWidget::makeOverlayCurrent()
925{
926}
927
928void QGLWidget::updateOverlayGL()
929{
930}
931
932void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
933{
934 Q_D(QGLWidget);
935 if (context == 0) {
936 qWarning("QGLWidget::setContext: Cannot set null context");
937 return;
938 }
939
940 if (d->glcx)
941 d->glcx->doneCurrent();
942 QGLContext* oldcx = d->glcx;
943 d->glcx = context;
944 if (!d->glcx->isValid())
945 d->glcx->create(shareContext ? shareContext : oldcx);
946 if (deleteOldContext && oldcx)
947 delete oldcx;
948}
949
950void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
951{
952 Q_Q(QGLWidget);
953
954 initContext(context, shareWidget);
955
956 QWidget *current = q;
957 while (current) {
958 qt_widget_private(current)->glWidgets.append(QWidgetPrivate::GlWidgetInfo(q));
959 if (current->isWindow())
960 break;
961 current = current->parentWidget();
962 }
963}
964
965bool QGLWidgetPrivate::renderCxPm(QPixmap*)
966{
967 return false;
968}
969
970void QGLWidgetPrivate::cleanupColormaps()
971{
972}
973
974const QGLColormap & QGLWidget::colormap() const
975{
976 return d_func()->cmap;
977}
978
979void QGLWidget::setColormap(const QGLColormap &)
980{
981}
982
983void QGLWidgetPrivate::updatePaintDevice()
984{
985 Q_Q(QGLWidget);
986 glcx->updatePaintDevice();
987 q->update();
988}
989
990#endif
991
992QT_END_NAMESPACE
993

Warning: That file was not part of the compilation database. It may have many parsing errors.