11#include <QtCore/private/qcore_mac_p.h>
18 if (
const GLubyte *
s = glGetString(
param))
19 return QByteArray(
reinterpret_cast<const char*
>(
s));
48 updateSurfaceFormat();
68 GLint shareContextRequestedProfile;
69 [m_shareContext.pixelFormat getValues:&shareContextRequestedProfile
70 forAttribute:NSOpenGLPFAOpenGLProfile forVirtualScreen:0];
71 auto shareContextActualProfile = shareContext->format().version();
73 if (shareContextRequestedProfile == NSOpenGLProfileVersion3_2Core
74 && shareContextActualProfile >=
qMakePair(4, 1)) {
85 NSOpenGLPixelFormat *pixelFormat = [pixelFormatForSurfaceFormat(m_format) autorelease];
86 m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext];
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];
96 qCWarning(lcQpaOpenGLContext,
"Failed to create NSOpenGLContext");
103 [m_context setValues:&interval forParameter:NSOpenGLContextParameterSwapInterval];
107 [m_context setValues:&zeroOpacity forParameter:NSOpenGLContextParameterSurfaceOpacity];
112 const GLint order = qt_mac_resolveOption(1,
"QT_MAC_OPENGL_SURFACE_ORDER");
113 [m_context setValues:&
order forParameter:NSOpenGLContextParameterSurfaceOrder];
115 updateSurfaceFormat();
117 qCDebug(lcQpaOpenGLContext).verbosity(3) <<
"Created" <<
this <<
"based on requested" <<
context()->
format();
124 attrs << NSOpenGLPFAOpenGLProfile;
127 attrs << NSOpenGLProfileVersion4_1Core;
129 attrs << NSOpenGLProfileVersion3_2Core;
131 attrs << NSOpenGLProfileVersionLegacy;
133 attrs << NSOpenGLProfileVersionLegacy;
136 switch (
format.swapBehavior()) {
144 attrs.append(NSOpenGLPFADoubleBuffer);
147 attrs.append(NSOpenGLPFATripleBuffer);
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();
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;
169 if (
format.samples() > 0) {
170 attrs << NSOpenGLPFAMultisample
171 << NSOpenGLPFASampleBuffers << NSOpenGLPixelFormatAttribute(1)
172 << NSOpenGLPFASamples << NSOpenGLPixelFormatAttribute(
format.samples());
178 if (offlineRenderersAllowed) {
180 attrs << NSOpenGLPFAAllowOfflineRenderers;
186 attrs << NSOpenGLPFARendererID << kCGLRendererGenericFloatID;
190 return [[NSOpenGLPixelFormat alloc] initWithAttributes:
attrs.constData()];
198void QCocoaGLContext::updateSurfaceFormat()
200 NSOpenGLContext *oldContext = [NSOpenGLContext currentContext];
201 [m_context makeCurrentContext];
205 int major = 0, minor = 0;
240 NSOpenGLPixelFormat *pixelFormat = m_context.pixelFormat;
242 GLint virtualScreen = [&,
this]() {
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];
253 if (requestedDisplay & supportedDisplays)
256 qCWarning(lcQpaOpenGLContext) <<
"Could not find virtual screen for"
257 << platformScreen <<
"with displayId" << displayId;
261 auto pixelFormatAttribute = [&](NSOpenGLPixelFormatAttribute
attribute) {
263 [pixelFormat getValues:&
value forAttribute:
attribute forVirtualScreen:virtualScreen];
267 int colorSize = pixelFormatAttribute(NSOpenGLPFAColorSize);
283 m_format.
setSamples(pixelFormatAttribute(NSOpenGLPFASamples));
285 if (pixelFormatAttribute(NSOpenGLPFATripleBuffer))
287 else if (pixelFormatAttribute(NSOpenGLPFADoubleBuffer))
294 auto glContextParameter = [&](NSOpenGLContextParameter parameter) {
296 [m_context getValues:&
value forParameter:parameter];
300 m_format.
setSwapInterval(glContextParameter(NSOpenGLContextParameterSwapInterval));
303 [oldContext makeCurrentContext];
305 [NSOpenGLContext clearCurrentContext];
317 qCDebug(lcQpaOpenGLContext) <<
"Making" <<
this <<
"current"
322 if (!setDrawable(surface))
325 [m_context makeCurrentContext];
351 [m_context clearDrawable];
356 auto *cocoaWindow =
static_cast<QCocoaWindow *
>(surface);
367 cocoaWindow->window(),
"_q_mac_wantsBestResolutionOpenGLSurface",
368 "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
376 auto updateCallback = [
this,
view]() {
380 m_needsUpdate =
true;
383 m_updateObservers.
clear();
389 NSApplicationDidChangeScreenParametersNotification, updateCallback));
395 qCDebug(lcQpaOpenGLContext) <<
view <<
"about to be released."
396 <<
"Clearing current drawable for" << m_context;
397 [m_context clearDrawable];
408 qCInfo(lcQpaOpenGLContext) <<
"Failed to set" <<
view <<
"as drawable for" << m_context;
409 m_updateObservers.
clear();
438 qCDebug(lcQpaOpenGLContext) <<
"Swapping" << m_context
444 if (!setDrawable(surface)) {
445 qCWarning(lcQpaOpenGLContext) <<
"Can't flush" << m_context
446 <<
"without" << surface <<
"as drawable";
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.";
464 [m_context flushBuffer];
471 qCDebug(lcQpaOpenGLContext) <<
"Clearing current context"
478 [NSOpenGLContext clearCurrentContext];
488 return m_context != nil;
493 return m_shareContext != nil;
503 return (QFunctionPointer)dlsym(RTLD_NEXT, procName);
506#ifndef QT_NO_DEBUG_STREAM
513 if (
debug.verbosity() > QDebug::DefaultVerbosity)
T fetchAndStoreRelaxed(T newValue) noexcept
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
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)
QPlatformScreen * handle() const
Get the platform screen handle.
SurfaceClass surfaceClass() const
Returns the surface class of this surface.
bool supportsOpenGL() const
Returns true if the surface is OpenGL compatible and can be used in conjunction with QOpenGLContext; ...
static QThread * currentThread()
Combined button and popup list for selecting options.
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 QT_IGNORE_DEPRECATIONS(statement)
static struct AttrInfo attrs[]
#define GL_CONTEXT_PROFILE_MASK
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
#define GL_CONTEXT_CORE_PROFILE_BIT
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
EGLOutputLayerEXT EGLint attribute
#define Q_LOGGING_CATEGORY(name,...)
#define qCInfo(category,...)
#define qCWarning(category,...)
#define qCDebug(category,...)
constexpr const T & qMax(const T &a, const T &b)
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLenum const GLint * param
GLint GLsizei GLsizei GLenum format
GLfixed GLfixed GLint GLint order
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept