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

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

trunk: Merged in qt 4.6.1 sources.

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