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 "qplatformopenglcontext.h" |
5 | |
6 | #include <QOpenGLFunctions> |
7 | |
8 | QT_BEGIN_NAMESPACE |
9 | |
10 | /*! |
11 | \class QPlatformOpenGLContext |
12 | \since 4.8 |
13 | \internal |
14 | \preliminary |
15 | \ingroup qpa |
16 | |
17 | \brief The QPlatformOpenGLContext class provides an abstraction for native GL contexts. |
18 | |
19 | In QPA the way to support OpenGL or OpenVG or other technologies that requires a native GL |
20 | context is through the QPlatformOpenGLContext wrapper. |
21 | |
22 | There is no factory function for QPlatformOpenGLContexts, but rather only one accessor function. |
23 | The only place to retrieve a QPlatformOpenGLContext from is through a QPlatformWindow. |
24 | |
25 | The context which is current for a specific thread can be collected by the currentContext() |
26 | function. This is how QPlatformOpenGLContext also makes it possible to use the Qt GUI module |
27 | withhout using QOpenGLWidget. When using QOpenGLContext::currentContext(), it will ask |
28 | QPlatformOpenGLContext for the currentContext. Then a corresponding QOpenGLContext will be returned, |
29 | which maps to the QPlatformOpenGLContext. |
30 | */ |
31 | |
32 | /*! \fn void QPlatformOpenGLContext::swapBuffers(QPlatformSurface *surface) |
33 | Reimplement in subclass to native swap buffers calls |
34 | |
35 | The implementation must support being called in a thread different than the gui-thread. |
36 | */ |
37 | |
38 | /*! \fn QFunctionPointer QPlatformOpenGLContext::getProcAddress(const char *procName) |
39 | |
40 | Reimplement in subclass to allow dynamic querying of OpenGL symbols. As opposed to e.g. the wglGetProcAddress |
41 | function on Windows, Qt expects this methods to be able to return valid function pointers even for standard |
42 | OpenGL symbols. |
43 | */ |
44 | |
45 | class QPlatformOpenGLContextPrivate |
46 | { |
47 | public: |
48 | QPlatformOpenGLContextPrivate() : context(nullptr) {} |
49 | |
50 | QOpenGLContext *context; |
51 | }; |
52 | |
53 | QPlatformOpenGLContext::QPlatformOpenGLContext() |
54 | : d_ptr(new QPlatformOpenGLContextPrivate) |
55 | { |
56 | } |
57 | |
58 | QPlatformOpenGLContext::~QPlatformOpenGLContext() |
59 | { |
60 | } |
61 | |
62 | /*! |
63 | Called after a new instance is constructed. The default implementation does nothing. |
64 | |
65 | Subclasses can use this function to perform additional initialization that relies on |
66 | virtual functions. |
67 | */ |
68 | void QPlatformOpenGLContext::initialize() |
69 | { |
70 | } |
71 | |
72 | /*! |
73 | Reimplement in subclass if your platform uses framebuffer objects for surfaces. |
74 | |
75 | The default implementation returns 0. |
76 | */ |
77 | GLuint QPlatformOpenGLContext::defaultFramebufferObject(QPlatformSurface *) const |
78 | { |
79 | return 0; |
80 | } |
81 | |
82 | QOpenGLContext *QPlatformOpenGLContext::context() const |
83 | { |
84 | Q_D(const QPlatformOpenGLContext); |
85 | return d->context; |
86 | } |
87 | |
88 | void QPlatformOpenGLContext::setContext(QOpenGLContext *context) |
89 | { |
90 | Q_D(QPlatformOpenGLContext); |
91 | d->context = context; |
92 | } |
93 | |
94 | bool QPlatformOpenGLContext::parseOpenGLVersion(const QByteArray &versionString, int &major, int &minor) |
95 | { |
96 | bool majorOk = false; |
97 | bool minorOk = false; |
98 | QList<QByteArray> parts = versionString.split(sep: ' '); |
99 | if (versionString.startsWith(QByteArrayLiteral("OpenGL ES" ))) { |
100 | if (parts.size() >= 3) { |
101 | QList<QByteArray> versionParts = parts.at(i: 2).split(sep: '.'); |
102 | if (versionParts.size() >= 2) { |
103 | major = versionParts.at(i: 0).toInt(ok: &majorOk); |
104 | minor = versionParts.at(i: 1).toInt(ok: &minorOk); |
105 | // Nexus 6 has "OpenGL ES 3.0V@95.0 (GIT@I86da836d38)" |
106 | if (!minorOk) |
107 | if (int idx = versionParts.at(i: 1).indexOf(c: 'V')) |
108 | minor = versionParts.at(i: 1).left(len: idx).toInt(ok: &minorOk); |
109 | } else { |
110 | qWarning(msg: "Unrecognized OpenGL ES version" ); |
111 | } |
112 | } else { |
113 | // If < 3 parts to the name, it is an unrecognised OpenGL ES |
114 | qWarning(msg: "Unrecognised OpenGL ES version" ); |
115 | } |
116 | } else { |
117 | // Not OpenGL ES, but regular OpenGL, the version numbers are first in the string |
118 | QList<QByteArray> versionParts = parts.at(i: 0).split(sep: '.'); |
119 | if (versionParts.size() >= 2) { |
120 | major = versionParts.at(i: 0).toInt(ok: &majorOk); |
121 | minor = versionParts.at(i: 1).toInt(ok: &minorOk); |
122 | } else { |
123 | qWarning(msg: "Unrecognized OpenGL version" ); |
124 | } |
125 | } |
126 | |
127 | if (!majorOk || !minorOk) |
128 | qWarning(msg: "Unrecognized OpenGL version" ); |
129 | return (majorOk && minorOk); |
130 | } |
131 | |
132 | /*! |
133 | Called when the RHI begins rendering a new frame in the context. Will always be paired with a |
134 | call to \l endFrame(). |
135 | */ |
136 | void QPlatformOpenGLContext::beginFrame() |
137 | { |
138 | } |
139 | |
140 | /*! |
141 | Called when the RHI ends rendering a in the context. Is always preceded by a call to |
142 | \l beginFrame(). |
143 | */ |
144 | void QPlatformOpenGLContext::endFrame() |
145 | { |
146 | } |
147 | |
148 | QT_END_NAMESPACE |
149 | |