Merge lp:~gerboland/qtubuntu/minor-cleanup into lp:qtubuntu

Proposed by Gerry Boland
Status: Superseded
Proposed branch: lp:~gerboland/qtubuntu/minor-cleanup
Merge into: lp:qtubuntu
Diff against target: 687 lines (+162/-256)
7 files modified
README (+6/-7)
src/ubuntumirclient/glcontext.cpp (+30/-165)
src/ubuntumirclient/glcontext.h (+11/-19)
src/ubuntumirclient/integration.cpp (+26/-35)
src/ubuntumirclient/integration.h (+0/-8)
src/ubuntumirclient/window.cpp (+86/-21)
src/ubuntumirclient/window.h (+3/-1)
To merge this branch: bzr merge lp:~gerboland/qtubuntu/minor-cleanup
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Approve
Daniel d'Andrada (community) Approve
Review via email: mp+295241@code.launchpad.net

This proposal has been superseded by a proposal from 2016-06-03.

Commit message

Integration: no need for the non-const versions of createWindow and createGLContext

To post a comment you must log in.
Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:317
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/55/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1696
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1646
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1646
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1639
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1639/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1639
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1639/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1639
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1639/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1639
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1639/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1639
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1639/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1639
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1639/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/55/rebuild

review: Approve (continuous-integration)
lp:~gerboland/qtubuntu/minor-cleanup updated
328. By Gerry Boland

Remove old incorrect info from readme

329. By Gerry Boland

Fix typo

330. By Gerry Boland

Set minimum GL version to 1.0 so that EGL chooses a suitable context on Atom-based hardware

Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default requested OpenGL version to 1.0 to ensure EGL will give us a working context.

331. By Gerry Boland

Rename SurfaceFormatChooser to SurfaceFormatFilter and add env var to disable filteringi

332. By Gerry Boland

QML does not need alpha channel to render correctly, so do not impose it

333. By Gerry Boland

Typo spot dy duflu

334. By Gerry Boland

Update comments to reflect reality

335. By Gerry Boland

Enable GL version hack only on Mesa

336. By Gerry Boland

Micro optimisation

337. By Gerry Boland

Minor syntax standardization

338. By Gerry Boland

GCC disagreeed with CLang about removing the default from the switch

339. By Gerry Boland

Set a sensible QSurfaceFormat::setDefaultFormat instead of guess-filtering after user request

340. By Gerry Boland

Refactor again to remove the SurfaceFormatFilter, and just retry config choice with lower GL version

Revision history for this message
Daniel d'Andrada (dandrader) :
review: Approve
lp:~gerboland/qtubuntu/minor-cleanup updated
341. By Gerry Boland

Merge trunk, fix conflicts, give hints to branch predictor

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:317
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/66/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/1813
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/1846
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/1788
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/1788
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/1788
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=yakkety/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=yakkety/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=vivid+overlay/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/1778/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1778
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=yakkety/1778/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/66/rebuild

review: Approve (continuous-integration)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README'
2--- README 2015-12-09 13:30:15 +0000
3+++ README 2016-06-03 10:25:36 +0000
4@@ -23,13 +23,10 @@
5 $ qmlscene -platform ubuntumirclient Foo.qml
6 $ QT_QPA_PLATFORM=ubuntumirclient qmlscene Foo.qml
7
8- The QPA plugins expose the following environment variables:
9-
10- QTUBUNTU_SWAPINTERVAL: Specifies the required swap interval as an
11- integer. 1 by default.
12-
13- QTUBUNTU_MULTISAMPLE: Enables multisampling with using 4 samples
14- per fragment.
15+ This QPA plugin exposes the following environment variables:
16+
17+ QT_QPA_EGLFS_SWAPINTERVAL: Specifies the required swap interval as an
18+ integer. 1 by default.
19
20 QTUBUNTU_NO_THREADED_OPENGL: Disables QtQuick threaded OpenGL
21 rendering.
22@@ -51,6 +48,8 @@
23 * ubuntumirclient.swapBuffers - Messages related to surface buffer swapping.
24 * ubuntumirclient - For all other messages.
25
26+ The QT_QPA_EGLFS_DEBUG environment variable prints a little more information
27+ from Qt's internals.
28
29 4. Building
30 -----------
31
32=== modified file 'src/ubuntumirclient/glcontext.cpp'
33--- src/ubuntumirclient/glcontext.cpp 2016-05-27 13:05:20 +0000
34+++ src/ubuntumirclient/glcontext.cpp 2016-06-03 10:25:36 +0000
35@@ -25,58 +25,12 @@
36
37 namespace {
38
39-void printOpenGLESConfig() {
40- static bool once = true;
41- if (once) {
42- const char* string = (const char*) glGetString(GL_VENDOR);
43- qCDebug(ubuntumirclient, "OpenGL ES vendor: %s", string);
44- string = (const char*) glGetString(GL_RENDERER);
45- qCDebug(ubuntumirclient, "OpenGL ES renderer: %s", string);
46- string = (const char*) glGetString(GL_VERSION);
47- qCDebug(ubuntumirclient, "OpenGL ES version: %s", string);
48- string = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
49- qCDebug(ubuntumirclient, "OpenGL ES Shading Language version: %s", string);
50- string = (const char*) glGetString(GL_EXTENSIONS);
51- qCDebug(ubuntumirclient, "OpenGL ES extensions: %s", string);
52- once = false;
53- }
54-}
55-
56-void printEglConfig(EGLDisplay display, EGLConfig config) {
57+void printEglConfig(EGLDisplay display, EGLConfig config)
58+{
59 Q_ASSERT(display != EGL_NO_DISPLAY);
60 Q_ASSERT(config != nullptr);
61
62- static const struct { const EGLint attrib; const char* name; } kAttribs[] = {
63- { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" },
64- { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" },
65- { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" },
66- { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" },
67- { EGL_RED_SIZE, "EGL_RED_SIZE" },
68- { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" },
69- { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" },
70- { EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT" },
71- { EGL_CONFIG_ID, "EGL_CONFIG_ID" },
72- { EGL_LEVEL, "EGL_LEVEL" },
73- { EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT" },
74- { EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS" },
75- { EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH" },
76- { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" },
77- { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" },
78- { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" },
79- { EGL_SAMPLES, "EGL_SAMPLES" },
80- { EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS" },
81- { EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE" },
82- { EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE" },
83- { EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE" },
84- { EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE" },
85- { EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE" },
86- { EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB" },
87- { EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA" },
88- { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" },
89- { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" },
90- { -1, NULL }
91- };
92- const char* string = eglQueryString(display, EGL_VENDOR);
93+ const char *string = eglQueryString(display, EGL_VENDOR);
94 qCDebug(ubuntumirclient, "EGL vendor: %s", string);
95
96 string = eglQueryString(display, EGL_VERSION);
97@@ -85,93 +39,19 @@
98 string = eglQueryString(display, EGL_EXTENSIONS);
99 qCDebug(ubuntumirclient, "EGL extensions: %s", string);
100
101- qCDebug(ubuntumirclient, "EGL configuration attibutes:");
102- for (int index = 0; kAttribs[index].attrib != -1; index++) {
103- EGLint value;
104- if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value))
105- qCDebug(ubuntumirclient, " %s: %d", kAttribs[index].name, static_cast<int>(value));
106- }
107-}
108-
109-QString eglErrorToString(EGLint errorNumber)
110-{
111- #define EGL_ERROR_CASE(error) case error: return QString(#error);
112-
113- switch (errorNumber) {
114- EGL_ERROR_CASE(EGL_SUCCESS)
115- EGL_ERROR_CASE(EGL_NOT_INITIALIZED)
116- EGL_ERROR_CASE(EGL_BAD_ACCESS)
117- EGL_ERROR_CASE(EGL_BAD_ALLOC)
118- EGL_ERROR_CASE(EGL_BAD_ATTRIBUTE)
119- EGL_ERROR_CASE(EGL_BAD_CONTEXT)
120- EGL_ERROR_CASE(EGL_BAD_CONFIG)
121- EGL_ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
122- EGL_ERROR_CASE(EGL_BAD_DISPLAY)
123- EGL_ERROR_CASE(EGL_BAD_SURFACE)
124- EGL_ERROR_CASE(EGL_BAD_MATCH)
125- EGL_ERROR_CASE(EGL_BAD_PARAMETER)
126- EGL_ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
127- EGL_ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
128- EGL_ERROR_CASE(EGL_CONTEXT_LOST)
129- default:
130- return QString("?");
131- }
132-
133- #undef EGL_ERROR_CASE
134-}
135-
136-EGLenum api_in_use()
137-{
138- #ifdef QTUBUNTU_USE_OPENGL
139- return EGL_OPENGL_API;
140- #else
141- return EGL_OPENGL_ES_API;
142- #endif
143-}
144-
145-const int kSwapInterval = 1;
146-
147-int qGetEnvIntValue(const char *varName, bool *ok)
148-{
149- return qgetenv(varName).toInt(ok);
150+ qCDebug(ubuntumirclient, "EGL configuration attributes:");
151+ q_printEglConfig(display, config);
152 }
153
154 } // anonymous namespace
155
156-UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share,
157- EGLDisplay display, EGLConfig config)
158- : mSurfaceFormat(surfaceFormat)
159- , mEglDisplay(display)
160+UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
161+ EGLDisplay display)
162+ : QEGLPlatformContext(format, share, display, 0)
163 {
164- // Create an OpenGL ES 2 context.
165- QVector<EGLint> attribs;
166- attribs.append(EGL_CONTEXT_CLIENT_VERSION);
167- attribs.append(2);
168- attribs.append(EGL_NONE);
169- ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
170-
171 if (ubuntumirclient().isDebugEnabled()) {
172- printEglConfig(mEglDisplay, config);
173+ printEglConfig(display, eglConfig());
174 }
175-
176- // Set vblank swap interval.
177- bool ok;
178- int swapInterval = qGetEnvIntValue("QTUBUNTU_SWAPINTERVAL", &ok);
179- if (!ok)
180- swapInterval = kSwapInterval;
181-
182- qCDebug(ubuntumirclient, "Setting swap interval to %d", swapInterval);
183- eglSwapInterval(mEglDisplay, swapInterval);
184-
185- mEglContext = eglCreateContext(mEglDisplay, config, share ? share->eglContext() : EGL_NO_CONTEXT,
186- attribs.constData());
187-
188- Q_ASSERT(mEglContext != EGL_NO_CONTEXT);
189-}
190-
191-UbuntuOpenGLContext::~UbuntuOpenGLContext()
192-{
193- ASSERT(eglDestroyContext(mEglDisplay, mEglContext) == EGL_TRUE);
194 }
195
196 static bool needsFBOReadBackWorkaround()
197@@ -179,7 +59,7 @@
198 static bool set = false;
199 static bool needsWorkaround = false;
200
201- if (!set) {
202+ if (Q_UNLIKELY(!set)) {
203 const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
204 needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0
205 || qstrncmp(rendererString, "Mali-T7", 7) == 0
206@@ -202,47 +82,32 @@
207 }
208 return offscreen->buffer()->bind();
209 } else {
210- EGLSurface eglSurface = static_cast<UbuntuWindow*>(surface)->eglSurface();
211- ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
212-
213- EGLBoolean result = eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext);
214- if (result == EGL_FALSE) {
215- qCCritical(ubuntumirclient, "eglMakeCurrent() failed with %s",
216- qPrintable(eglErrorToString(eglGetError())));
217- return false;
218- }
219-
220- QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
221- if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
222- ctx_d->workaround_brokenFBOReadBack = true;
223- }
224-
225- if (ubuntumirclient().isDebugEnabled()) {
226- printOpenGLESConfig();
227- }
228- return true;
229+ const bool ret = QEGLPlatformContext::makeCurrent(surface);
230+
231+ if (Q_LIKELY(ret)) {
232+ QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context());
233+ if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) {
234+ ctx_d->workaround_brokenFBOReadBack = true;
235+ }
236+ }
237+
238+ return ret;
239 }
240 }
241
242-void UbuntuOpenGLContext::doneCurrent()
243+// Following method used internally in the base class QEGLPlatformContext to access
244+// the egl surface of a QPlatformSurface/UbuntuWindow
245+EGLSurface UbuntuOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface)
246 {
247- ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
248- ASSERT(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE);
249+ auto ubuntuWindow = static_cast<UbuntuWindow *>(surface);
250+ return ubuntuWindow->eglSurface();
251 }
252
253-void UbuntuOpenGLContext::swapBuffers(QPlatformSurface* surface)
254+void UbuntuOpenGLContext::swapBuffers(QPlatformSurface *surface)
255 {
256- UbuntuWindow *ubuntuWindow = static_cast<UbuntuWindow*>(surface);
257-
258- EGLSurface eglSurface = ubuntuWindow->eglSurface();
259- ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
260- ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE);
261-
262+ QEGLPlatformContext::swapBuffers(surface);
263+
264+ // notify window on swap completion
265+ auto ubuntuWindow = static_cast<UbuntuWindow *>(surface);
266 ubuntuWindow->onSwapBuffersDone();
267 }
268-
269-void (*UbuntuOpenGLContext::getProcAddress(const QByteArray& procName)) ()
270-{
271- ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE);
272- return eglGetProcAddress(procName.constData());
273-}
274
275=== modified file 'src/ubuntumirclient/glcontext.h'
276--- src/ubuntumirclient/glcontext.h 2016-04-28 14:09:54 +0000
277+++ src/ubuntumirclient/glcontext.h 2016-06-03 10:25:36 +0000
278@@ -18,30 +18,22 @@
279 #define UBUNTU_OPENGL_CONTEXT_H
280
281 #include <qpa/qplatformopenglcontext.h>
282+#include <private/qeglplatformcontext_p.h>
283
284 #include <EGL/egl.h>
285
286-class UbuntuOpenGLContext : public QPlatformOpenGLContext
287+class UbuntuOpenGLContext : public QEGLPlatformContext
288 {
289 public:
290- UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share,
291- EGLDisplay display, EGLConfig config);
292- virtual ~UbuntuOpenGLContext();
293-
294- // QPlatformOpenGLContext methods.
295- QSurfaceFormat format() const override { return mSurfaceFormat; }
296- void swapBuffers(QPlatformSurface *surface) override;
297- bool makeCurrent(QPlatformSurface *surface) override;
298- void doneCurrent() override;
299- bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; }
300- void (*getProcAddress(const QByteArray& procName)) () override;
301-
302- EGLContext eglContext() const { return mEglContext; }
303-
304-private:
305- const QSurfaceFormat mSurfaceFormat;
306- EGLContext mEglContext;
307- EGLDisplay mEglDisplay;
308+ UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
309+ EGLDisplay display);
310+
311+ // QEGLPlatformContext methods.
312+ void swapBuffers(QPlatformSurface *surface) final;
313+ bool makeCurrent(QPlatformSurface *surface) final;
314+
315+protected:
316+ EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) final;
317 };
318
319 #endif // UBUNTU_OPENGL_CONTEXT_H
320
321=== modified file 'src/ubuntumirclient/integration.cpp'
322--- src/ubuntumirclient/integration.cpp 2016-04-28 14:44:18 +0000
323+++ src/ubuntumirclient/integration.cpp 2016-06-03 10:25:36 +0000
324@@ -29,7 +29,6 @@
325
326 // Qt
327 #include <QGuiApplication>
328-#include <private/qguiapplication_p.h>
329 #include <qpa/qplatformnativeinterface.h>
330 #include <qpa/qplatforminputcontextfactory_p.h>
331 #include <qpa/qplatforminputcontext.h>
332@@ -90,31 +89,17 @@
333
334 mMirConnection = u_application_instance_get_mir_connection(mInstance);
335
336+ // Choose the default surface format suited to the Mir platform
337+ QSurfaceFormat defaultFormat;
338+ defaultFormat.setRedBufferSize(8);
339+ defaultFormat.setGreenBufferSize(8);
340+ defaultFormat.setBlueBufferSize(8);
341+ QSurfaceFormat::setDefaultFormat(defaultFormat);
342+
343 // Initialize EGL.
344- ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE);
345-
346 mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection);
347 ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
348 ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
349-
350- // Configure EGL buffers format for all Windows.
351- mSurfaceFormat.setRedBufferSize(8);
352- mSurfaceFormat.setGreenBufferSize(8);
353- mSurfaceFormat.setBlueBufferSize(8);
354- mSurfaceFormat.setAlphaBufferSize(8);
355- mSurfaceFormat.setDepthBufferSize(24);
356- mSurfaceFormat.setStencilBufferSize(8);
357- if (!qEnvironmentVariableIsEmpty("QTUBUNTU_MULTISAMPLE")) {
358- mSurfaceFormat.setSamples(4);
359- qCDebug(ubuntumirclient, "setting MSAA to 4 samples");
360- }
361-#ifdef QTUBUNTU_USE_OPENGL
362- mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGL);
363-#else
364- mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES);
365-#endif
366-
367- mEglConfig = q_configFromGLFormat(mEglDisplay, mSurfaceFormat, true);
368 }
369
370 void UbuntuClientIntegration::initialize()
371@@ -192,12 +177,7 @@
372
373 QPlatformWindow* UbuntuClientIntegration::createPlatformWindow(QWindow* window) const
374 {
375- return const_cast<UbuntuClientIntegration*>(this)->createPlatformWindow(window);
376-}
377-
378-QPlatformWindow* UbuntuClientIntegration::createPlatformWindow(QWindow* window)
379-{
380- return new UbuntuWindow(window, mClipboard, mInput, mNativeInterface, mEglDisplay, mEglConfig, mMirConnection);
381+ return new UbuntuWindow(window, mClipboard, mInput, mNativeInterface, mEglDisplay, mMirConnection);
382 }
383
384 bool UbuntuClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const
385@@ -240,14 +220,25 @@
386 QPlatformOpenGLContext* UbuntuClientIntegration::createPlatformOpenGLContext(
387 QOpenGLContext* context) const
388 {
389- return const_cast<UbuntuClientIntegration*>(this)->createPlatformOpenGLContext(context);
390-}
391+ QSurfaceFormat format(context->format());
392
393-QPlatformOpenGLContext* UbuntuClientIntegration::createPlatformOpenGLContext(
394- QOpenGLContext* context)
395-{
396- return new UbuntuOpenGLContext(mSurfaceFormat, static_cast<UbuntuOpenGLContext*>(context->shareHandle()),
397- mEglDisplay, mEglConfig);
398+ auto platformContext = new UbuntuOpenGLContext(format, context->shareHandle(), mEglDisplay);
399+ if (!platformContext->isValid()) {
400+ // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
401+ // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
402+ // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to
403+ // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
404+ // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
405+ static const bool isMesa = QString(eglQueryString(mEglDisplay, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
406+ if (isMesa) {
407+ qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
408+ format.setMajorVersion(1);
409+ format.setMinorVersion(4);
410+ delete platformContext;
411+ platformContext = new UbuntuOpenGLContext(format, context->shareHandle(), mEglDisplay);
412+ }
413+ }
414+ return platformContext;
415 }
416
417 QStringList UbuntuClientIntegration::themeNames() const
418
419=== modified file 'src/ubuntumirclient/integration.h'
420--- src/ubuntumirclient/integration.h 2016-04-28 14:09:54 +0000
421+++ src/ubuntumirclient/integration.h 2016-06-03 10:25:36 +0000
422@@ -60,15 +60,9 @@
423 void initialize() override;
424 QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
425
426- // non-const versions of some QPlatformIntegration methods
427- QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context);
428- QPlatformWindow* createPlatformWindow(QWindow* window);
429-
430 // New methods.
431 MirConnection *mirConnection() const { return mMirConnection; }
432- QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; }
433 EGLDisplay eglDisplay() const { return mEglDisplay; }
434- EGLConfig eglConfig() const { return mEglConfig; }
435 EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
436 UbuntuScreenObserver *screenObserver() const { return mScreenObserver.data(); }
437
438@@ -99,9 +93,7 @@
439
440 // EGL related
441 EGLDisplay mEglDisplay{EGL_NO_DISPLAY};
442- EGLConfig mEglConfig{nullptr};
443 EGLNativeDisplayType mEglNativeDisplay;
444- QSurfaceFormat mSurfaceFormat;
445 };
446
447 #endif // UBUNTU_CLIENT_INTEGRATION_H
448
449=== modified file 'src/ubuntumirclient/window.cpp'
450--- src/ubuntumirclient/window.cpp 2016-04-28 14:44:18 +0000
451+++ src/ubuntumirclient/window.cpp 2016-06-03 10:25:36 +0000
452@@ -29,6 +29,7 @@
453 #include <QMutexLocker>
454 #include <QSize>
455 #include <QtMath>
456+#include <private/qeglconvenience_p.h>
457
458 // Platform API
459 #include <ubuntu/application/instance.h>
460@@ -101,6 +102,24 @@
461 }
462 }
463
464+const char *mirPixelFormatToStr(MirPixelFormat pixelFormat)
465+{
466+ switch (pixelFormat) {
467+ case mir_pixel_format_invalid: return "invalid";
468+ case mir_pixel_format_abgr_8888: return "ABGR8888";
469+ case mir_pixel_format_xbgr_8888: return "XBGR8888";
470+ case mir_pixel_format_argb_8888: return "ARGB8888";
471+ case mir_pixel_format_xrgb_8888: return "XRGB8888";
472+ case mir_pixel_format_bgr_888: return "BGR888";
473+ case mir_pixel_format_rgb_888: return "RGB888";
474+ case mir_pixel_format_rgb_565: return "RGB565";
475+ case mir_pixel_format_rgba_5551: return "RGBA5551";
476+ case mir_pixel_format_rgba_4444: return "RGBA4444";
477+ case mir_pixel_formats:
478+ default: return "???";
479+ }
480+}
481+
482 MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state)
483 {
484 switch (state) {
485@@ -124,14 +143,6 @@
486 return id++;
487 }
488
489-MirPixelFormat defaultPixelFormatFor(MirConnection *connection)
490-{
491- MirPixelFormat format;
492- unsigned int nformats;
493- mir_connection_get_available_surface_formats(connection, &format, 1, &nformats);
494- return format;
495-}
496-
497 UAUiWindowRole roleFor(QWindow *window)
498 {
499 QVariant roleVariant = window->property("role");
500@@ -151,12 +162,11 @@
501 return parent ? static_cast<UbuntuWindow *>(parent->handle()) : nullptr;
502 }
503
504-Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection)
505+Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirPixelFormat pixelFormat, MirConnection *connection)
506 {
507 const auto geom = window->geometry();
508 const int width = geom.width() > 0 ? geom.width() : 1;
509 const int height = geom.height() > 0 ? geom.height() : 1;
510- const auto pixelFormat = defaultPixelFormatFor(connection);
511
512 if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) {
513 qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height);
514@@ -217,11 +227,11 @@
515 }
516 }
517
518-MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input,
519+MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input, MirPixelFormat pixelFormat,
520 MirConnection *connection, mir_surface_event_callback inputCallback,
521 void* inputContext)
522 {
523- auto spec = makeSurfaceSpec(window, input, connection);
524+ auto spec = makeSurfaceSpec(window, input, pixelFormat, connection);
525
526 // Install event handler as early as possible
527 mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext);
528@@ -244,6 +254,18 @@
529 return surface;
530 }
531
532+MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat)
533+{
534+ switch(pixelFormat) {
535+ case mir_pixel_format_abgr_8888:
536+ return mir_pixel_format_xbgr_8888;
537+ case mir_pixel_format_argb_8888:
538+ return mir_pixel_format_xrgb_8888;
539+ default: // can do nothing, leave it alone
540+ return pixelFormat;
541+ }
542+}
543+
544 // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
545 // we need to guess the panel height (3GU)
546 int panelHeight()
547@@ -266,8 +288,7 @@
548 class UbuntuSurface
549 {
550 public:
551- UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, EGLConfig config, int mirOutputId,
552- UbuntuInput *input, MirConnection *connection)
553+ UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection)
554 : mWindow(platformWindow->window())
555 , mPlatformWindow(platformWindow)
556 , mInput(input)
557@@ -275,9 +296,44 @@
558 , mEglDisplay(display)
559 , mNeedsRepaint(false)
560 , mParented(mWindow->transientParent() || mWindow->parent())
561+ , mFormat(mWindow->requestedFormat())
562 , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
563 {
564- mMirSurface = createMirSurface(mWindow, mirOutputId, input, connection, surfaceEventCallback, this);
565+ // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it
566+ EGLConfig config = q_configFromGLFormat(display, mFormat, true);
567+ if (config == 0) {
568+ // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default
569+ // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a
570+ // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to
571+ // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default
572+ // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455).
573+ static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa"));
574+ if (isMesa) {
575+ qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa");
576+ mFormat.setMajorVersion(1);
577+ mFormat.setMinorVersion(4);
578+ config = q_configFromGLFormat(display, mFormat, true);
579+ }
580+ }
581+ if (config == 0) {
582+ qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat;
583+ }
584+
585+ mFormat = q_glFormatFromConfig(display, config, mFormat);
586+
587+ // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way
588+ // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers.
589+ auto pixelFormat = mir_connection_get_egl_pixel_format(connection, display, config);
590+ // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client.
591+ // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer.
592+ // This is an optimisation for the compositor, as it can avoid blending this surface.
593+ if (mWindow->requestedFormat().alphaBufferSize() < 0) {
594+ pixelFormat = disableAlphaBufferIfPossible(pixelFormat);
595+ }
596+
597+ const auto outputId = static_cast<UbuntuScreen *>(mWindow->screen()->handle())->mirOutputId();
598+
599+ mMirSurface = createMirSurface(mWindow, outputId, input, pixelFormat, connection, surfaceEventCallback, this);
600 mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr);
601
602 // Window manager can give us a final size different from what we asked for
603@@ -299,8 +355,11 @@
604 platformWindow->QPlatformWindow::setGeometry(geom);
605 QWindowSystemInterface::handleGeometryChange(mWindow, geom);
606
607- qCDebug(ubuntumirclient, "created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n",
608- geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow));
609+ qCDebug(ubuntumirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title()
610+ << "role:" << roleFor(mWindow)
611+ << "\nRequested format:" << mWindow->requestedFormat()
612+ << "\nActual format:" << mFormat
613+ << "with associated Mir pixel format:" << mirPixelFormatToStr(pixelFormat);
614 }
615
616 ~UbuntuSurface()
617@@ -335,6 +394,8 @@
618 void setSurfaceParent(MirSurface*);
619 bool hasParent() const { return mParented; }
620
621+ QSurfaceFormat format() const { return mFormat; }
622+
623 private:
624 static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context);
625 void postEvent(const MirEvent *event);
626@@ -351,6 +412,7 @@
627 bool mNeedsRepaint;
628 bool mParented;
629 QSize mBufferSize;
630+ QSurfaceFormat mFormat;
631
632 QMutex mTargetSizeMutex;
633 QSize mTargetSize;
634@@ -509,8 +571,7 @@
635 }
636
637 UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard,
638- UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay,
639- EGLConfig eglConfig, MirConnection *mirConnection)
640+ UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay, MirConnection *mirConnection)
641 : QObject(nullptr)
642 , QPlatformWindow(w)
643 , mId(makeId())
644@@ -520,8 +581,7 @@
645 , mWindowVisible(false)
646 , mWindowExposed(true)
647 , mNativeInterface(native)
648- , mSurface(new UbuntuSurface{this, eglDisplay, eglConfig,
649- static_cast<UbuntuScreen*>(w->screen()->handle())->mirOutputId(), input, mirConnection})
650+ , mSurface(new UbuntuSurface{this, eglDisplay, input, mirConnection})
651 , mScale(1.0)
652 , mFormFactor(mir_form_factor_unknown)
653 {
654@@ -709,6 +769,11 @@
655 return mWindowVisible && mWindowExposed;
656 }
657
658+QSurfaceFormat UbuntuWindow::format() const
659+{
660+ return mSurface->format();
661+}
662+
663 void* UbuntuWindow::eglSurface() const
664 {
665 return mSurface->eglSurface();
666
667=== modified file 'src/ubuntumirclient/window.h'
668--- src/ubuntumirclient/window.h 2016-04-28 14:44:18 +0000
669+++ src/ubuntumirclient/window.h 2016-06-03 10:25:36 +0000
670@@ -40,7 +40,7 @@
671 Q_OBJECT
672 public:
673 UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard,
674- UbuntuInput *input, UbuntuNativeInterface* native, EGLDisplay eglDisplay, EGLConfig eglConfig,
675+ UbuntuInput *input, UbuntuNativeInterface* native, EGLDisplay eglDisplay,
676 MirConnection *mirConnection);
677 virtual ~UbuntuWindow();
678
679@@ -54,6 +54,8 @@
680 void propagateSizeHints() override;
681 bool isExposed() const override;
682
683+ QSurfaceFormat format() const override;
684+
685 // Additional Window properties exposed by NativeInterface
686 MirFormFactor formFactor() const { return mFormFactor; }
687 float scale() const { return mScale; }

Subscribers

People subscribed via source and target branches