Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qcocoaglcontext.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <AppKit/AppKit.h>
5
6#include "qcocoaglcontext.h"
7#include "qcocoawindow.h"
8#include "qcocoahelpers.h"
9#include "qcocoascreen.h"
10
11#include <QtCore/private/qcore_mac_p.h>
12
13#include <qdebug.h>
14#include <dlfcn.h>
15
17{
18 if (const GLubyte *s = glGetString(param))
19 return QByteArray(reinterpret_cast<const char*>(s));
20 return QByteArray();
21}
22
24
25Q_LOGGING_CATEGORY(lcQpaOpenGLContext, "qt.qpa.openglcontext", QtWarningMsg);
26
32
33QCocoaGLContext::QCocoaGLContext(NSOpenGLContext *nativeContext)
35{
36 m_context = [nativeContext retain];
37}
38
40{
41 if (m_context) {
42 // Note: We have no way of knowing whether the NSOpenGLContext was created with the
43 // share context as reported by the QOpenGLContext, but we just have to trust that
44 // it was. It's okey, as the only thing we're using it for is to report isShared().
45 if (QPlatformOpenGLContext *shareContext = context()->shareHandle())
46 m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext();
47
48 updateSurfaceFormat();
49 return;
50 }
51
52 // ----------- Default case, we own the NSOpenGLContext -----------
53
54 // We only support OpenGL contexts under Cocoa
57 if (m_format.renderableType() != QSurfaceFormat::OpenGL)
58 return;
59
60 if (QPlatformOpenGLContext *shareContext = context()->shareHandle()) {
61 m_shareContext = static_cast<QCocoaGLContext *>(shareContext)->nativeContext();
62
63 // Allow sharing between 3.2 Core and 4.1 Core profile versions in
64 // cases where NSOpenGLContext creates a 4.1 context where a 3.2
65 // context was requested. Due to the semantics of QSurfaceFormat
66 // this 4.1 version can find its way onto the format for the new
67 // context, even though it was at no point requested by the user.
68 GLint shareContextRequestedProfile;
69 [m_shareContext.pixelFormat getValues:&shareContextRequestedProfile
70 forAttribute:NSOpenGLPFAOpenGLProfile forVirtualScreen:0];
71 auto shareContextActualProfile = shareContext->format().version();
72
73 if (shareContextRequestedProfile == NSOpenGLProfileVersion3_2Core
74 && shareContextActualProfile >= qMakePair(4, 1)) {
75 // There is a mismatch. Downgrade requested format to make the
76 // NSOpenGLPFAOpenGLProfile attributes match. (NSOpenGLContext
77 // will fail to create a new context if there is a mismatch).
78 if (m_format.version() >= qMakePair(4, 1))
79 m_format.setVersion(3, 2);
80 }
81 }
82
83 // ------------------------- Create NSOpenGLContext -------------------------
84
85 NSOpenGLPixelFormat *pixelFormat = [pixelFormatForSurfaceFormat(m_format) autorelease];
86 m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext];
87
88 if (!m_context && m_shareContext) {
89 qCWarning(lcQpaOpenGLContext, "Could not create NSOpenGLContext with shared context, "
90 "falling back to unshared context.");
91 m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
92 m_shareContext = nil;
93 }
94
95 if (!m_context) {
96 qCWarning(lcQpaOpenGLContext, "Failed to create NSOpenGLContext");
97 return;
98 }
99
100 // --------------------- Set NSOpenGLContext properties ---------------------
101
102 const GLint interval = m_format.swapInterval() >= 0 ? m_format.swapInterval() : 1;
103 [m_context setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
104
105 if (m_format.alphaBufferSize() > 0) {
106 int zeroOpacity = 0;
107 [m_context setValues:&zeroOpacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
108 }
109
110 // OpenGL surfaces can be ordered either above(default) or below the NSWindow
111 // FIXME: Promote to QSurfaceFormat option or property
112 const GLint order = qt_mac_resolveOption(1, "QT_MAC_OPENGL_SURFACE_ORDER");
113 [m_context setValues:&order forParameter:NSOpenGLContextParameterSurfaceOrder];
114
115 updateSurfaceFormat();
116
117 qCDebug(lcQpaOpenGLContext).verbosity(3) << "Created" << this << "based on requested" << context()->format();
118}
119
120NSOpenGLPixelFormat *QCocoaGLContext::pixelFormatForSurfaceFormat(const QSurfaceFormat &format)
121{
122 QVector<NSOpenGLPixelFormatAttribute> attrs;
123
124 attrs << NSOpenGLPFAOpenGLProfile;
125 if (format.profile() == QSurfaceFormat::CoreProfile) {
126 if (format.version() >= qMakePair(4, 1))
127 attrs << NSOpenGLProfileVersion4_1Core;
128 else if (format.version() >= qMakePair(3, 2))
129 attrs << NSOpenGLProfileVersion3_2Core;
130 else
131 attrs << NSOpenGLProfileVersionLegacy;
132 } else {
133 attrs << NSOpenGLProfileVersionLegacy;
134 }
135
136 switch (format.swapBehavior()) {
138 break; // The NSOpenGLPixelFormat default, no attribute to set
140 // Technically this should be single-buffered, but we force double-buffered
141 // FIXME: Why do we force double-buffered?
144 attrs.append(NSOpenGLPFADoubleBuffer);
145 break;
147 attrs.append(NSOpenGLPFATripleBuffer);
148 break;
149 }
150
151 if (format.depthBufferSize() > 0)
152 attrs << NSOpenGLPFADepthSize << format.depthBufferSize();
153 if (format.stencilBufferSize() > 0)
154 attrs << NSOpenGLPFAStencilSize << format.stencilBufferSize();
155 if (format.alphaBufferSize() > 0)
156 attrs << NSOpenGLPFAAlphaSize << format.alphaBufferSize();
157
158 auto rbz = format.redBufferSize();
159 auto gbz = format.greenBufferSize();
160 auto bbz = format.blueBufferSize();
161 if (rbz > 0 || gbz > 0 || bbz > 0) {
162 auto fallbackSize = qMax(rbz, qMax(gbz, bbz));
163 auto colorSize = (rbz > 0 ? rbz : fallbackSize)
164 + (gbz > 0 ? gbz : fallbackSize)
165 + (bbz > 0 ? bbz : fallbackSize);
166 attrs << NSOpenGLPFAColorSize << colorSize << NSOpenGLPFAMinimumPolicy;
167 }
168
169 if (format.samples() > 0) {
170 attrs << NSOpenGLPFAMultisample
171 << NSOpenGLPFASampleBuffers << NSOpenGLPixelFormatAttribute(1)
172 << NSOpenGLPFASamples << NSOpenGLPixelFormatAttribute(format.samples());
173 }
174
175 //Workaround for problems with Chromium and offline renderers on the lat 2013 MacPros.
176 //FIXME: Think if this could be solved via QSurfaceFormat in the future.
177 static bool offlineRenderersAllowed = qEnvironmentVariableIsEmpty("QT_MAC_PRO_WEBENGINE_WORKAROUND");
178 if (offlineRenderersAllowed) {
179 // Allow rendering on GPUs without a connected display
180 attrs << NSOpenGLPFAAllowOfflineRenderers;
181 }
182
183 if (qGuiApp->testAttribute(Qt::AA_UseSoftwareOpenGL)) {
184 // kCGLRendererGenericFloatID is the modern software renderer on macOS,
185 // as opposed to kCGLRendererGenericID, which is deprecated.
186 attrs << NSOpenGLPFARendererID << kCGLRendererGenericFloatID;
187 }
188
189 attrs << 0; // 0-terminate array
190 return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs.constData()];
191}
192
198void QCocoaGLContext::updateSurfaceFormat()
199{
200 NSOpenGLContext *oldContext = [NSOpenGLContext currentContext];
201 [m_context makeCurrentContext];
202
203 // --------------------- Query GL state ---------------------
204
205 int major = 0, minor = 0;
206 QByteArray versionString(getGlString(GL_VERSION));
207 if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
208 m_format.setMajorVersion(major);
209 m_format.setMinorVersion(minor);
210 }
211
213 if (m_format.version() >= qMakePair(3, 2)) {
214 GLint value = 0;
215 glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
220 }
221
223 if (m_format.version() < qMakePair(3, 0)) {
224 return true;
225 } else {
226 GLint value = 0;
227 glGetIntegerv(GL_CONTEXT_FLAGS, &value);
229 }
230 }());
231
232 // Debug contexts not supported on macOS
234
235 // Nor are stereo buffers (deprecated in macOS 10.12)
237
238 // ------------------ Query the pixel format ------------------
239
240 NSOpenGLPixelFormat *pixelFormat = m_context.pixelFormat;
241
242 GLint virtualScreen = [&, this]() {
243 auto *platformScreen = static_cast<QCocoaScreen*>(context()->screen()->handle());
244 auto displayId = platformScreen->nativeScreen().qt_displayId;
245 auto requestedDisplay = CGDisplayIDToOpenGLDisplayMask(displayId);
246 for (int i = 0; i < pixelFormat.numberOfVirtualScreens; ++i) {
247 GLint supportedDisplays;
248 [pixelFormat getValues:&supportedDisplays forAttribute:NSOpenGLPFAScreenMask forVirtualScreen:i];
249 // Note: The mask returned for NSOpenGLPFAScreenMask is a bit mask of
250 // physical displays that the renderer can drive, while the one returned
251 // from CGDisplayIDToOpenGLDisplayMask has a single bit set, representing
252 // that particular display.
253 if (requestedDisplay & supportedDisplays)
254 return i;
255 }
256 qCWarning(lcQpaOpenGLContext) << "Could not find virtual screen for"
257 << platformScreen << "with displayId" << displayId;
258 return 0;
259 }();
260
261 auto pixelFormatAttribute = [&](NSOpenGLPixelFormatAttribute attribute) {
262 int value = 0;
263 [pixelFormat getValues:&value forAttribute:attribute forVirtualScreen:virtualScreen];
264 return value;
265 };
266
267 int colorSize = pixelFormatAttribute(NSOpenGLPFAColorSize);
268 colorSize /= 4; // The attribute includes the alpha component
269 m_format.setRedBufferSize(colorSize);
270 m_format.setGreenBufferSize(colorSize);
271 m_format.setBlueBufferSize(colorSize);
272
273 // Surfaces on macOS always have an alpha channel, but unless the user requested
274 // one via setAlphaBufferSize(), which triggered setting NSOpenGLCPSurfaceOpacity
275 // to make the surface non-opaque, we don't want to report back the actual alpha
276 // size, as that will make the user believe the alpha channel can be used for
277 // something useful, when in reality it can't, due to the surface being opaque.
278 if (m_format.alphaBufferSize() > 0)
279 m_format.setAlphaBufferSize(pixelFormatAttribute(NSOpenGLPFAAlphaSize));
280
281 m_format.setDepthBufferSize(pixelFormatAttribute(NSOpenGLPFADepthSize));
282 m_format.setStencilBufferSize(pixelFormatAttribute(NSOpenGLPFAStencilSize));
283 m_format.setSamples(pixelFormatAttribute(NSOpenGLPFASamples));
284
285 if (pixelFormatAttribute(NSOpenGLPFATripleBuffer))
287 else if (pixelFormatAttribute(NSOpenGLPFADoubleBuffer))
289 else
291
292 // ------------------- Query the context -------------------
293
294 auto glContextParameter = [&](NSOpenGLContextParameter parameter) {
295 int value = 0;
296 [m_context getValues:&value forParameter:parameter];
297 return value;
298 };
299
300 m_format.setSwapInterval(glContextParameter(NSOpenGLContextParameterSwapInterval));
301
302 if (oldContext)
303 [oldContext makeCurrentContext];
304 else
305 [NSOpenGLContext clearCurrentContext];
306}
307
309{
310 [m_context release];
311}
312
314{
316
317 qCDebug(lcQpaOpenGLContext) << "Making" << this << "current"
318 << "in" << QThread::currentThread() << "for" << surface;
319
320 Q_ASSERT(surface->surface()->supportsOpenGL());
321
322 if (!setDrawable(surface))
323 return false;
324
325 [m_context makeCurrentContext];
326
327 if (surface->surface()->surfaceClass() == QSurface::Window) {
328 if (m_needsUpdate.fetchAndStoreRelaxed(false))
329 update();
330 }
331
332 return true;
333}
334
339bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
340{
341 // Make sure any surfaces released during this process are deallocated
342 // straight away, otherwise we may run out of surfaces when spinning a
343 // render-loop that doesn't return to one of the outer pools.
345
346 if (!surface || surface->surface()->surfaceClass() == QSurface::Offscreen) {
347 // Clear the current drawable and reset the active window, so that GL
348 // commands that don't target a specific FBO will not end up stomping
349 // on the previously set drawable.
350 qCDebug(lcQpaOpenGLContext) << "Clearing current drawable" << QT_IGNORE_DEPRECATIONS(m_context.view) << "for" << m_context;
351 [m_context clearDrawable];
352 return true;
353 }
354
356 auto *cocoaWindow = static_cast<QCocoaWindow *>(surface);
357 QNSView *view = qnsview_cast(cocoaWindow->view());
358
359 if (view == QT_IGNORE_DEPRECATIONS(m_context.view))
360 return true;
361
362 // We generally want high-DPI GL surfaces, unless the user has explicitly disabled them.
363 // According to the documentation, layer-backed views ignore wantsBestResolutionOpenGLSurface
364 // and configure their own backing surface at an appropriate resolution, but in some cases
365 // we've seen this fail (plugin views embedded in surface-backed hosts), so we do it anyways.
366 QT_IGNORE_DEPRECATIONS(view.wantsBestResolutionOpenGLSurface) = qt_mac_resolveOption(YES,
367 cocoaWindow->window(), "_q_mac_wantsBestResolutionOpenGLSurface",
368 "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
369
370 // Setting the drawable may happen on a separate thread as a result of
371 // a call to makeCurrent, so we need to set up the observers before we
372 // associate the view with the context. That way we will guarantee that
373 // as long as the view is the drawable of the context we will know about
374 // any updates to the view that require surface invalidation.
375
376 auto updateCallback = [this, view]() {
377 Q_ASSERT(QThread::currentThread() == qApp->thread());
378 if (QT_IGNORE_DEPRECATIONS(m_context.view) != view)
379 return;
380 m_needsUpdate = true;
381 };
382
383 m_updateObservers.clear();
384
385 m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback));
386 m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
387
388 m_updateObservers.append(QMacNotificationObserver([NSApplication sharedApplication],
389 NSApplicationDidChangeScreenParametersNotification, updateCallback));
390
391 m_updateObservers.append(QMacNotificationObserver(view,
393 if (QT_IGNORE_DEPRECATIONS(m_context.view) != view)
394 return;
395 qCDebug(lcQpaOpenGLContext) << view << "about to be released."
396 << "Clearing current drawable for" << m_context;
397 [m_context clearDrawable];
398 }));
399
400 // If any of the observers fire at this point it's fine. We check the
401 // view association (atomically) in the update callback, and skip the
402 // update if we haven't associated yet. Setting the drawable below will
403 // have the same effect as an update.
404
405 // Now we are ready to associate the view with the context
406 QT_IGNORE_DEPRECATIONS(m_context.view) = view;
407 if (QT_IGNORE_DEPRECATIONS(m_context.view) != view) {
408 qCInfo(lcQpaOpenGLContext) << "Failed to set" << view << "as drawable for" << m_context;
409 m_updateObservers.clear();
410 return false;
411 }
412
413 qCInfo(lcQpaOpenGLContext) << "Set drawable for" << m_context << "to" << QT_IGNORE_DEPRECATIONS(m_context.view);
414 return true;
415}
416
417// NSOpenGLContext is not re-entrant. Even when using separate contexts per thread,
418// view, and window, calls into the API will still deadlock. For more information
419// see https://openradar.appspot.com/37064579
420Q_CONSTINIT static QMutex s_reentrancyMutex;
421
423{
424 // Make sure any surfaces released during this process are deallocated
425 // straight away, otherwise we may run out of surfaces when spinning a
426 // render-loop that doesn't return to one of the outer pools.
428
430 qCInfo(lcQpaOpenGLContext) << "Updating" << m_context << "for" << QT_IGNORE_DEPRECATIONS(m_context.view);
431 [m_context update];
432}
433
435{
437
438 qCDebug(lcQpaOpenGLContext) << "Swapping" << m_context
439 << "in" << QThread::currentThread() << "to" << surface;
440
441 if (surface->surface()->surfaceClass() == QSurface::Offscreen)
442 return; // Nothing to do
443
444 if (!setDrawable(surface)) {
445 qCWarning(lcQpaOpenGLContext) << "Can't flush" << m_context
446 << "without" << surface << "as drawable";
447 return;
448 }
449
450 // Flushing an NSOpenGLContext will hit the screen immediately, ignoring
451 // any Core Animation transactions in place. This may result in major
452 // visual artifacts if the flush happens out of sync with the size
453 // of the layer, view, and window reflected by other parts of the UI,
454 // e.g. if the application flushes in the resize event or a timer during
455 // window resizing, instead of in the expose event.
456 auto *cocoaWindow = static_cast<QCocoaWindow *>(surface);
457 if (cocoaWindow->geometry().size() != cocoaWindow->m_exposedRect.size()) {
458 qCInfo(lcQpaOpenGLContext) << "Window exposed size does not match geometry (yet)."
459 << "Skipping flush to avoid visual artifacts.";
460 return;
461 }
462
464 [m_context flushBuffer];
465}
466
468{
470
471 qCDebug(lcQpaOpenGLContext) << "Clearing current context"
472 << [NSOpenGLContext currentContext] << "in" << QThread::currentThread();
473
474 // Note: We do not need to clear the current drawable here.
475 // As long as there is no current context, GL calls will
476 // do nothing.
477
478 [NSOpenGLContext clearCurrentContext];
479}
480
482{
483 return m_format;
484}
485
487{
488 return m_context != nil;
489}
490
492{
493 return m_shareContext != nil;
494}
495
496NSOpenGLContext *QCocoaGLContext::nativeContext() const
497{
498 return m_context;
499}
500
501QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName)
502{
503 return (QFunctionPointer)dlsym(RTLD_NEXT, procName);
504}
505
506#ifndef QT_NO_DEBUG_STREAM
508{
509 QDebugStateSaver saver(debug);
510 debug.nospace();
511 debug << "QCocoaGLContext(" << (const void *)context;
512 if (context) {
513 if (debug.verbosity() > QDebug::DefaultVerbosity)
514 debug << ", " << context->format();
515 debug << ", " << context->nativeContext();
516 }
517 debug << ')';
518 return debug;
519}
520#endif // !QT_NO_DEBUG_STREAM
521
T fetchAndStoreRelaxed(T newValue) noexcept
\inmodule QtCore
Definition qbytearray.h:57
NSOpenGLContext * nativeContext() const override
void swapBuffers(QPlatformSurface *surface) override
Reimplement in subclass to native swap buffers calls.
void doneCurrent() override
QSurfaceFormat format() const override
bool isSharing() const override
void initialize() override
Called after a new instance is constructed.
QFunctionPointer getProcAddress(const char *procName) override
Reimplement in subclass to allow dynamic querying of OpenGL symbols.
QCocoaGLContext(QOpenGLContext *context)
bool makeCurrent(QPlatformSurface *surface) override
bool isValid() const override
NSScreen * nativeScreen() const
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qmutex.h:313
\inmodule QtCore
Definition qmutex.h:281
\inmodule QtGui
QSurfaceFormat format() const
Returns the format of the underlying platform context, if create() has been called.
QScreen * screen() const
Returns the screen the context was created for.
The QPlatformOpenGLContext class provides an abstraction for native GL contexts.
QOpenGLContext * context() const
static bool parseOpenGLVersion(const QByteArray &versionString, int &major, int &minor)
The QPlatformSurface class provides an abstraction for a surface.
QSurface * surface() const
QPlatformScreen * handle() const
Get the platform screen handle.
Definition qscreen.cpp:83
The QSurfaceFormat class represents the format of a QSurface. \inmodule QtGui.
void setMinorVersion(int minorVersion)
Sets the desired minor OpenGL version.
void setSwapBehavior(SwapBehavior behavior)
Set the swap behavior of the surface.
void setRenderableType(RenderableType type)
Sets the desired renderable type.
void setDepthBufferSize(int size)
Set the minimum depth buffer size to size.
void setGreenBufferSize(int size)
Set the desired size in bits of the green channel of the color buffer.
void setRedBufferSize(int size)
Set the desired size in bits of the red channel of the color buffer.
int alphaBufferSize() const
Get the size in bits of the alpha channel of the color buffer.
void setProfile(OpenGLContextProfile profile)
Sets the desired OpenGL context profile.
void setBlueBufferSize(int size)
Set the desired size in bits of the blue channel of the color buffer.
void setAlphaBufferSize(int size)
Set the desired size in bits of the alpha channel of the color buffer.
int swapInterval() const
Returns the swap interval.
void setVersion(int major, int minor)
Sets the desired major and minor OpenGL versions.
void setStencilBufferSize(int size)
Set the preferred stencil buffer size to size bits.
void setSamples(int numSamples)
Set the preferred number of samples per pixel when multisampling is enabled to numSamples.
RenderableType renderableType() const
Gets the renderable type.
void setSwapInterval(int interval)
Sets the preferred swap interval.
void setMajorVersion(int majorVersion)
Sets the desired major OpenGL version.
void setOption(FormatOption option, bool on=true)
QPair< int, int > version() const
Returns a QPair<int, int> representing the OpenGL version.
SurfaceClass surfaceClass() const
Returns the surface class of this surface.
Definition qsurface.cpp:121
bool supportsOpenGL() const
Returns true if the surface is OpenGL compatible and can be used in conjunction with QOpenGLContext; ...
Definition qsurface.cpp:70
@ Offscreen
Definition qsurface.h:26
static QThread * currentThread()
Definition qthread.cpp:1039
void append(const T &t)
Combined button and popup list for selecting options.
@ AA_UseSoftwareOpenGL
Definition qnamespace.h:446
static void * context
QDebug operator<<(QDebug debug, const QCocoaGLContext *context)
static QByteArray getGlString(GLenum param)
static Q_CONSTINIT QMutex s_reentrancyMutex
QNSView * qnsview_cast(NSView *view)
Returns the view cast to a QNSview if possible.
const NSNotificationName QCocoaWindowWillReleaseQNSViewNotification
#define Q_FALLTHROUGH()
#define QT_IGNORE_DEPRECATIONS(statement)
#define qApp
static struct AttrInfo attrs[]
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
#define GL_CONTEXT_PROFILE_MASK
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
#define GL_CONTEXT_CORE_PROFILE_BIT
#define GL_CONTEXT_FLAGS
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputLayerEXT EGLint attribute
#define qGuiApp
@ QtWarningMsg
Definition qlogging.h:31
#define Q_LOGGING_CATEGORY(name,...)
#define qCInfo(category,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLenum const GLint * param
GLint GLsizei GLsizei GLenum format
GLdouble s
[6]
Definition qopenglext.h:235
GLfixed GLfixed GLint GLint order
QT_BEGIN_NAMESPACE constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition qpair.h:19
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
sem release()
QQuickView * view
[0]