Changeset View
Changeset View
Standalone View
Standalone View
plugins/qpa/abstractplatformcontext.cpp
Show All 13 Lines | |||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | 15 | GNU General Public License for more details. | ||
16 | 16 | | |||
17 | You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | *********************************************************************/ | 19 | *********************************************************************/ | ||
20 | #include "abstractplatformcontext.h" | 20 | #include "abstractplatformcontext.h" | ||
21 | #include "integration.h" | 21 | #include "integration.h" | ||
22 | #include "egl_context_attribute_builder.h" | ||||
22 | #include <logging.h> | 23 | #include <logging.h> | ||
23 | 24 | | |||
25 | #include <memory> | ||||
26 | | ||||
24 | namespace KWin | 27 | namespace KWin | ||
25 | { | 28 | { | ||
26 | 29 | | |||
27 | namespace QPA | 30 | namespace QPA | ||
28 | { | 31 | { | ||
29 | 32 | | |||
30 | static bool isOpenGLES() | 33 | static bool isOpenGLES() | ||
31 | { | 34 | { | ||
▲ Show 20 Lines • Show All 108 Lines • ▼ Show 20 Line(s) | |||||
140 | 143 | | |||
141 | void AbstractPlatformContext::createContext(EGLContext shareContext) | 144 | void AbstractPlatformContext::createContext(EGLContext shareContext) | ||
142 | { | 145 | { | ||
143 | const QByteArray eglExtensions = eglQueryString(eglDisplay(), EGL_EXTENSIONS); | 146 | const QByteArray eglExtensions = eglQueryString(eglDisplay(), EGL_EXTENSIONS); | ||
144 | const QList<QByteArray> extensions = eglExtensions.split(' '); | 147 | const QList<QByteArray> extensions = eglExtensions.split(' '); | ||
145 | const bool haveRobustness = extensions.contains(QByteArrayLiteral("EGL_EXT_create_context_robustness")); | 148 | const bool haveRobustness = extensions.contains(QByteArrayLiteral("EGL_EXT_create_context_robustness")); | ||
146 | const bool haveCreateContext = extensions.contains(QByteArrayLiteral("EGL_KHR_create_context")); | 149 | const bool haveCreateContext = extensions.contains(QByteArrayLiteral("EGL_KHR_create_context")); | ||
147 | 150 | | |||
148 | EGLContext context = EGL_NO_CONTEXT; | 151 | std::vector<std::unique_ptr<AbstractOpenGLContextAttributeBuilder>> candidates; | ||
149 | if (isOpenGLES()) { | 152 | if (isOpenGLES()) { | ||
150 | if (haveCreateContext && haveRobustness) { | 153 | if (haveCreateContext && haveRobustness) { | ||
151 | const EGLint context_attribs[] = { | 154 | auto glesRobust = std::unique_ptr<AbstractOpenGLContextAttributeBuilder>(new EglOpenGLESContextAttributeBuilder); | ||
152 | EGL_CONTEXT_CLIENT_VERSION, 2, | 155 | glesRobust->setVersion(2); | ||
153 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_TRUE, | 156 | glesRobust->setRobust(true); | ||
154 | EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_LOSE_CONTEXT_ON_RESET_EXT, | 157 | candidates.push_back(std::move(glesRobust)); | ||
155 | EGL_NONE | 158 | } | ||
156 | }; | 159 | auto gles = std::unique_ptr<AbstractOpenGLContextAttributeBuilder>(new EglOpenGLESContextAttributeBuilder); | ||
157 | context = eglCreateContext(eglDisplay(), config(), shareContext, context_attribs); | 160 | gles->setVersion(2); | ||
158 | } | 161 | candidates.push_back(std::move(gles)); | ||
159 | if (context == EGL_NO_CONTEXT) { | | |||
160 | const EGLint context_attribs[] = { | | |||
161 | EGL_CONTEXT_CLIENT_VERSION, 2, | | |||
162 | EGL_NONE | | |||
163 | }; | | |||
164 | | ||||
165 | context = eglCreateContext(eglDisplay(), config(), shareContext, context_attribs); | | |||
166 | } | | |||
167 | } else { | 162 | } else { | ||
168 | // Try to create a 3.1 core context | 163 | // Try to create a 3.1 core context | ||
169 | if (m_format.majorVersion() >= 3 && haveCreateContext) { | 164 | if (m_format.majorVersion() >= 3 && haveCreateContext) { | ||
170 | if (haveRobustness) { | 165 | if (haveRobustness) { | ||
171 | const int attribs[] = { | 166 | auto robustCore = std::unique_ptr<AbstractOpenGLContextAttributeBuilder>(new EglContextAttributeBuilder); | ||
172 | EGL_CONTEXT_MAJOR_VERSION_KHR, m_format.majorVersion(), | 167 | robustCore->setVersion(m_format.majorVersion(), m_format.minorVersion()); | ||
173 | EGL_CONTEXT_MINOR_VERSION_KHR, m_format.minorVersion(), | 168 | robustCore->setRobust(true); | ||
174 | EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, EGL_LOSE_CONTEXT_ON_RESET_KHR, | 169 | robustCore->setForwardCompatible(true); | ||
175 | EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, | 170 | if (m_format.profile() == QSurfaceFormat::CoreProfile) { | ||
176 | EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, m_format.profile() == QSurfaceFormat::CoreProfile ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR, | 171 | robustCore->setCoreProfile(true); | ||
177 | EGL_NONE | 172 | } else if (m_format.profile() == QSurfaceFormat::CompatibilityProfile) { | ||
178 | }; | 173 | robustCore->setCompatibilityProfile(true); | ||
179 | context = eglCreateContext(eglDisplay(), config(), shareContext, attribs); | 174 | } | ||
180 | } | 175 | candidates.push_back(std::move(robustCore)); | ||
181 | if (context == EGL_NO_CONTEXT) { | 176 | } | ||
182 | // try without robustness | 177 | auto core = std::unique_ptr<AbstractOpenGLContextAttributeBuilder>(new EglContextAttributeBuilder); | ||
183 | const EGLint attribs[] = { | 178 | core->setVersion(m_format.majorVersion(), m_format.minorVersion()); | ||
184 | EGL_CONTEXT_MAJOR_VERSION_KHR, m_format.majorVersion(), | 179 | core->setForwardCompatible(true); | ||
185 | EGL_CONTEXT_MINOR_VERSION_KHR, m_format.minorVersion(), | 180 | if (m_format.profile() == QSurfaceFormat::CoreProfile) { | ||
186 | EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, | 181 | core->setCoreProfile(true); | ||
187 | EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, m_format.profile() == QSurfaceFormat::CoreProfile ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR, | 182 | } else if (m_format.profile() == QSurfaceFormat::CompatibilityProfile) { | ||
188 | EGL_NONE | 183 | core->setCompatibilityProfile(true); | ||
189 | }; | 184 | } | ||
190 | context = eglCreateContext(eglDisplay(), config(), shareContext, attribs); | 185 | candidates.push_back(std::move(core)); | ||
186 | } | ||||
187 | | ||||
188 | if (haveRobustness && haveCreateContext) { | ||||
189 | auto robust = std::unique_ptr<AbstractOpenGLContextAttributeBuilder>(new EglContextAttributeBuilder); | ||||
190 | robust->setRobust(true); | ||||
191 | candidates.push_back(std::move(robust)); | ||||
191 | } | 192 | } | ||
193 | candidates.emplace_back(new EglContextAttributeBuilder); | ||||
192 | } | 194 | } | ||
193 | 195 | | |||
194 | if (context == EGL_NO_CONTEXT && haveRobustness && haveCreateContext) { | 196 | EGLContext context = EGL_NO_CONTEXT; | ||
195 | const int attribs[] = { | 197 | for (auto it = candidates.begin(); it != candidates.end(); it++) { | ||
196 | EGL_CONTEXT_FLAGS_KHR, EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR, | 198 | const auto attribs = (*it)->build(); | ||
197 | EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, EGL_LOSE_CONTEXT_ON_RESET_KHR, | 199 | context = eglCreateContext(eglDisplay(), config(), shareContext, attribs.data()); | ||
198 | EGL_NONE | 200 | if (context != EGL_NO_CONTEXT) { | ||
199 | }; | 201 | qCDebug(KWIN_QPA) << "Created EGL context with attributes:" << (*it).get(); | ||
200 | context = eglCreateContext(eglDisplay(), config(), shareContext, attribs); | 202 | break; | ||
201 | } | | |||
202 | if (context == EGL_NO_CONTEXT) { | | |||
203 | // and last but not least: try without robustness | | |||
204 | const EGLint attribs[] = { | | |||
205 | EGL_NONE | | |||
206 | }; | | |||
207 | context = eglCreateContext(eglDisplay(), config(), shareContext, attribs); | | |||
208 | } | 203 | } | ||
209 | } | 204 | } | ||
210 | 205 | | |||
211 | if (context == EGL_NO_CONTEXT) { | 206 | if (context == EGL_NO_CONTEXT) { | ||
212 | qCWarning(KWIN_QPA) << "Failed to create EGL context"; | 207 | qCWarning(KWIN_QPA) << "Failed to create EGL context"; | ||
213 | return; | 208 | return; | ||
214 | } | 209 | } | ||
215 | m_context = context; | 210 | m_context = context; | ||
216 | } | 211 | } | ||
217 | 212 | | |||
218 | } | 213 | } | ||
219 | } | 214 | } |