Merge lp:~dandrader/qtubuntu/rasterGLSurface into lp:qtubuntu
- rasterGLSurface
- Merge into trunk
Proposed by
Daniel d'Andrada
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~dandrader/qtubuntu/rasterGLSurface | ||||
Merge into: | lp:qtubuntu | ||||
Diff against target: |
931 lines (+243/-346) 12 files modified
README (+6/-7) src/ubuntumirclient/desktopwindow.cpp (+26/-0) src/ubuntumirclient/desktopwindow.h (+29/-0) src/ubuntumirclient/glcontext.cpp (+42/-177) src/ubuntumirclient/glcontext.h (+13/-19) src/ubuntumirclient/integration.cpp (+36/-27) src/ubuntumirclient/integration.h (+0/-4) src/ubuntumirclient/offscreensurface.cpp (+0/-47) src/ubuntumirclient/offscreensurface.h (+0/-41) src/ubuntumirclient/ubuntumirclient.pro (+2/-2) src/ubuntumirclient/window.cpp (+86/-21) src/ubuntumirclient/window.h (+3/-1) |
||||
To merge this branch: | bzr merge lp:~dandrader/qtubuntu/rasterGLSurface | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot | continuous-integration | Approve | |
Ubuntu Phablet Team | Pending | ||
Review via email:
|
Commit message
Add support for QQuickWidgets
- Advertise RasterGLSurface capability
- Implement proper offscreen rendering support using EGL pixel buffers.
- Don't create mir surfaces for Qt::Desktop QWindows. Proper
implementation still pending
Description of the change
To test:
Build & run lp:~dandrader/+junk/qwidget
If you can see the "Hello World" in a red rect, it's working.
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
review:
Approve
(continuous-integration)
Unmerged revisions
- 330. By Daniel d'Andrada
-
Add support for QQuickWidgets
- Advertise RasterGLSurface capability
- Implement proper offscreen rendering support using EGL pixel buffers.
- Don't create mir surfaces for Qt::Desktop QWindows. Proper
implementation still pending - 329. By Daniel d'Andrada
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'README' | |||
2 | --- README 2016-06-20 08:37:56 +0000 | |||
3 | +++ README 2016-07-04 17:59:30 +0000 | |||
4 | @@ -23,13 +23,10 @@ | |||
5 | 23 | $ qmlscene -platform ubuntumirclient Foo.qml | 23 | $ qmlscene -platform ubuntumirclient Foo.qml |
6 | 24 | $ QT_QPA_PLATFORM=ubuntumirclient qmlscene Foo.qml | 24 | $ QT_QPA_PLATFORM=ubuntumirclient qmlscene Foo.qml |
7 | 25 | 25 | ||
15 | 26 | The QPA plugins expose the following environment variables: | 26 | This QPA plugin exposes the following environment variables: |
16 | 27 | 27 | ||
17 | 28 | QTUBUNTU_SWAPINTERVAL: Specifies the required swap interval as an | 28 | QT_QPA_EGLFS_SWAPINTERVAL: Specifies the required swap interval as an |
18 | 29 | integer. 1 by default. | 29 | integer. 1 by default. |
12 | 30 | |||
13 | 31 | QTUBUNTU_MULTISAMPLE: Enables multisampling with using 4 samples | ||
14 | 32 | per fragment. | ||
19 | 33 | 30 | ||
20 | 34 | QTUBUNTU_NO_THREADED_OPENGL: Disables QtQuick threaded OpenGL | 31 | QTUBUNTU_NO_THREADED_OPENGL: Disables QtQuick threaded OpenGL |
21 | 35 | rendering. | 32 | rendering. |
22 | @@ -51,6 +48,8 @@ | |||
23 | 51 | * ubuntumirclient.swapBuffers - Messages related to surface buffer swapping. | 48 | * ubuntumirclient.swapBuffers - Messages related to surface buffer swapping. |
24 | 52 | * ubuntumirclient - For all other messages. | 49 | * ubuntumirclient - For all other messages. |
25 | 53 | 50 | ||
26 | 51 | The QT_QPA_EGLFS_DEBUG environment variable prints a little more information | ||
27 | 52 | from Qt's internals. | ||
28 | 54 | 53 | ||
29 | 55 | 4. Building | 54 | 4. Building |
30 | 56 | ----------- | 55 | ----------- |
31 | 57 | 56 | ||
32 | === added file 'src/ubuntumirclient/desktopwindow.cpp' | |||
33 | --- src/ubuntumirclient/desktopwindow.cpp 1970-01-01 00:00:00 +0000 | |||
34 | +++ src/ubuntumirclient/desktopwindow.cpp 2016-07-04 17:59:30 +0000 | |||
35 | @@ -0,0 +1,26 @@ | |||
36 | 1 | /* | ||
37 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
38 | 3 | * | ||
39 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
40 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
41 | 6 | * the Free Software Foundation. | ||
42 | 7 | * | ||
43 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
44 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
45 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
46 | 11 | * Lesser General Public License for more details. | ||
47 | 12 | * | ||
48 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
49 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
50 | 15 | */ | ||
51 | 16 | |||
52 | 17 | #include "desktopwindow.h" | ||
53 | 18 | |||
54 | 19 | // local | ||
55 | 20 | #include "logging.h" | ||
56 | 21 | |||
57 | 22 | UbuntuDesktopWindow::UbuntuDesktopWindow(QWindow *window) | ||
58 | 23 | : QPlatformWindow(window) | ||
59 | 24 | { | ||
60 | 25 | qCDebug(ubuntumirclient, "UbuntuDesktopWindow(window=%p)", window); | ||
61 | 26 | } | ||
62 | 0 | 27 | ||
63 | === added file 'src/ubuntumirclient/desktopwindow.h' | |||
64 | --- src/ubuntumirclient/desktopwindow.h 1970-01-01 00:00:00 +0000 | |||
65 | +++ src/ubuntumirclient/desktopwindow.h 2016-07-04 17:59:30 +0000 | |||
66 | @@ -0,0 +1,29 @@ | |||
67 | 1 | /* | ||
68 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
69 | 3 | * | ||
70 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
71 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
72 | 6 | * the Free Software Foundation. | ||
73 | 7 | * | ||
74 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
75 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
76 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
77 | 11 | * Lesser General Public License for more details. | ||
78 | 12 | * | ||
79 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
80 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
81 | 15 | */ | ||
82 | 16 | |||
83 | 17 | #ifndef UBUNTU_DESKTOP_WINDOW_H | ||
84 | 18 | #define UBUNTU_DESKTOP_WINDOW_H | ||
85 | 19 | |||
86 | 20 | #include <qpa/qplatformwindow.h> | ||
87 | 21 | |||
88 | 22 | // TODO Implement it. For now it's just an empty, dummy class. | ||
89 | 23 | class UbuntuDesktopWindow : public QPlatformWindow | ||
90 | 24 | { | ||
91 | 25 | public: | ||
92 | 26 | UbuntuDesktopWindow(QWindow*); | ||
93 | 27 | }; | ||
94 | 28 | |||
95 | 29 | #endif // UBUNTU_DESKTOP_WINDOW_H | ||
96 | 0 | 30 | ||
97 | === modified file 'src/ubuntumirclient/glcontext.cpp' | |||
98 | --- src/ubuntumirclient/glcontext.cpp 2016-06-20 08:37:56 +0000 | |||
99 | +++ src/ubuntumirclient/glcontext.cpp 2016-07-04 17:59:30 +0000 | |||
100 | @@ -16,7 +16,6 @@ | |||
101 | 16 | 16 | ||
102 | 17 | #include "glcontext.h" | 17 | #include "glcontext.h" |
103 | 18 | #include "logging.h" | 18 | #include "logging.h" |
104 | 19 | #include "offscreensurface.h" | ||
105 | 20 | #include "window.h" | 19 | #include "window.h" |
106 | 21 | 20 | ||
107 | 22 | #include <QOpenGLFramebufferObject> | 21 | #include <QOpenGLFramebufferObject> |
108 | @@ -25,58 +24,12 @@ | |||
109 | 25 | 24 | ||
110 | 26 | namespace { | 25 | namespace { |
111 | 27 | 26 | ||
130 | 28 | void printOpenGLESConfig() { | 27 | void printEglConfig(EGLDisplay display, EGLConfig config) |
131 | 29 | static bool once = true; | 28 | { |
114 | 30 | if (once) { | ||
115 | 31 | const char* string = (const char*) glGetString(GL_VENDOR); | ||
116 | 32 | qCDebug(ubuntumirclient, "OpenGL ES vendor: %s", string); | ||
117 | 33 | string = (const char*) glGetString(GL_RENDERER); | ||
118 | 34 | qCDebug(ubuntumirclient, "OpenGL ES renderer: %s", string); | ||
119 | 35 | string = (const char*) glGetString(GL_VERSION); | ||
120 | 36 | qCDebug(ubuntumirclient, "OpenGL ES version: %s", string); | ||
121 | 37 | string = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION); | ||
122 | 38 | qCDebug(ubuntumirclient, "OpenGL ES Shading Language version: %s", string); | ||
123 | 39 | string = (const char*) glGetString(GL_EXTENSIONS); | ||
124 | 40 | qCDebug(ubuntumirclient, "OpenGL ES extensions: %s", string); | ||
125 | 41 | once = false; | ||
126 | 42 | } | ||
127 | 43 | } | ||
128 | 44 | |||
129 | 45 | void printEglConfig(EGLDisplay display, EGLConfig config) { | ||
132 | 46 | Q_ASSERT(display != EGL_NO_DISPLAY); | 29 | Q_ASSERT(display != EGL_NO_DISPLAY); |
133 | 47 | Q_ASSERT(config != nullptr); | 30 | Q_ASSERT(config != nullptr); |
134 | 48 | 31 | ||
166 | 49 | static const struct { const EGLint attrib; const char* name; } kAttribs[] = { | 32 | const char *string = eglQueryString(display, EGL_VENDOR); |
136 | 50 | { EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE" }, | ||
137 | 51 | { EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE" }, | ||
138 | 52 | { EGL_BLUE_SIZE, "EGL_BLUE_SIZE" }, | ||
139 | 53 | { EGL_GREEN_SIZE, "EGL_GREEN_SIZE" }, | ||
140 | 54 | { EGL_RED_SIZE, "EGL_RED_SIZE" }, | ||
141 | 55 | { EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE" }, | ||
142 | 56 | { EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE" }, | ||
143 | 57 | { EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT" }, | ||
144 | 58 | { EGL_CONFIG_ID, "EGL_CONFIG_ID" }, | ||
145 | 59 | { EGL_LEVEL, "EGL_LEVEL" }, | ||
146 | 60 | { EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT" }, | ||
147 | 61 | { EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS" }, | ||
148 | 62 | { EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH" }, | ||
149 | 63 | { EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE" }, | ||
150 | 64 | { EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID" }, | ||
151 | 65 | { EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE" }, | ||
152 | 66 | { EGL_SAMPLES, "EGL_SAMPLES" }, | ||
153 | 67 | { EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS" }, | ||
154 | 68 | { EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE" }, | ||
155 | 69 | { EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE" }, | ||
156 | 70 | { EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE" }, | ||
157 | 71 | { EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE" }, | ||
158 | 72 | { EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE" }, | ||
159 | 73 | { EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB" }, | ||
160 | 74 | { EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA" }, | ||
161 | 75 | { EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL" }, | ||
162 | 76 | { EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL" }, | ||
163 | 77 | { -1, NULL } | ||
164 | 78 | }; | ||
165 | 79 | const char* string = eglQueryString(display, EGL_VENDOR); | ||
167 | 80 | qCDebug(ubuntumirclient, "EGL vendor: %s", string); | 33 | qCDebug(ubuntumirclient, "EGL vendor: %s", string); |
168 | 81 | 34 | ||
169 | 82 | string = eglQueryString(display, EGL_VERSION); | 35 | string = eglQueryString(display, EGL_VERSION); |
170 | @@ -85,93 +38,19 @@ | |||
171 | 85 | string = eglQueryString(display, EGL_EXTENSIONS); | 38 | string = eglQueryString(display, EGL_EXTENSIONS); |
172 | 86 | qCDebug(ubuntumirclient, "EGL extensions: %s", string); | 39 | qCDebug(ubuntumirclient, "EGL extensions: %s", string); |
173 | 87 | 40 | ||
223 | 88 | qCDebug(ubuntumirclient, "EGL configuration attibutes:"); | 41 | qCDebug(ubuntumirclient, "EGL configuration attributes:"); |
224 | 89 | for (int index = 0; kAttribs[index].attrib != -1; index++) { | 42 | q_printEglConfig(display, config); |
176 | 90 | EGLint value; | ||
177 | 91 | if (eglGetConfigAttrib(display, config, kAttribs[index].attrib, &value)) | ||
178 | 92 | qCDebug(ubuntumirclient, " %s: %d", kAttribs[index].name, static_cast<int>(value)); | ||
179 | 93 | } | ||
180 | 94 | } | ||
181 | 95 | |||
182 | 96 | QString eglErrorToString(EGLint errorNumber) | ||
183 | 97 | { | ||
184 | 98 | #define EGL_ERROR_CASE(error) case error: return QString(#error); | ||
185 | 99 | |||
186 | 100 | switch (errorNumber) { | ||
187 | 101 | EGL_ERROR_CASE(EGL_SUCCESS) | ||
188 | 102 | EGL_ERROR_CASE(EGL_NOT_INITIALIZED) | ||
189 | 103 | EGL_ERROR_CASE(EGL_BAD_ACCESS) | ||
190 | 104 | EGL_ERROR_CASE(EGL_BAD_ALLOC) | ||
191 | 105 | EGL_ERROR_CASE(EGL_BAD_ATTRIBUTE) | ||
192 | 106 | EGL_ERROR_CASE(EGL_BAD_CONTEXT) | ||
193 | 107 | EGL_ERROR_CASE(EGL_BAD_CONFIG) | ||
194 | 108 | EGL_ERROR_CASE(EGL_BAD_CURRENT_SURFACE) | ||
195 | 109 | EGL_ERROR_CASE(EGL_BAD_DISPLAY) | ||
196 | 110 | EGL_ERROR_CASE(EGL_BAD_SURFACE) | ||
197 | 111 | EGL_ERROR_CASE(EGL_BAD_MATCH) | ||
198 | 112 | EGL_ERROR_CASE(EGL_BAD_PARAMETER) | ||
199 | 113 | EGL_ERROR_CASE(EGL_BAD_NATIVE_PIXMAP) | ||
200 | 114 | EGL_ERROR_CASE(EGL_BAD_NATIVE_WINDOW) | ||
201 | 115 | EGL_ERROR_CASE(EGL_CONTEXT_LOST) | ||
202 | 116 | default: | ||
203 | 117 | return QString("?"); | ||
204 | 118 | } | ||
205 | 119 | |||
206 | 120 | #undef EGL_ERROR_CASE | ||
207 | 121 | } | ||
208 | 122 | |||
209 | 123 | EGLenum api_in_use() | ||
210 | 124 | { | ||
211 | 125 | #ifdef QTUBUNTU_USE_OPENGL | ||
212 | 126 | return EGL_OPENGL_API; | ||
213 | 127 | #else | ||
214 | 128 | return EGL_OPENGL_ES_API; | ||
215 | 129 | #endif | ||
216 | 130 | } | ||
217 | 131 | |||
218 | 132 | const int kSwapInterval = 1; | ||
219 | 133 | |||
220 | 134 | int qGetEnvIntValue(const char *varName, bool *ok) | ||
221 | 135 | { | ||
222 | 136 | return qgetenv(varName).toInt(ok); | ||
225 | 137 | } | 43 | } |
226 | 138 | 44 | ||
227 | 139 | } // anonymous namespace | 45 | } // anonymous namespace |
228 | 140 | 46 | ||
233 | 141 | UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share, | 47 | UbuntuOpenGLContext::UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, |
234 | 142 | EGLDisplay display, EGLConfig config) | 48 | EGLDisplay display) |
235 | 143 | : mSurfaceFormat(surfaceFormat) | 49 | : QEGLPlatformContext(format, share, display, 0) |
232 | 144 | , mEglDisplay(display) | ||
236 | 145 | { | 50 | { |
237 | 146 | // Create an OpenGL ES 2 context. | ||
238 | 147 | QVector<EGLint> attribs; | ||
239 | 148 | attribs.append(EGL_CONTEXT_CLIENT_VERSION); | ||
240 | 149 | attribs.append(2); | ||
241 | 150 | attribs.append(EGL_NONE); | ||
242 | 151 | ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE); | ||
243 | 152 | |||
244 | 153 | if (ubuntumirclient().isDebugEnabled()) { | 51 | if (ubuntumirclient().isDebugEnabled()) { |
246 | 154 | printEglConfig(mEglDisplay, config); | 52 | printEglConfig(display, eglConfig()); |
247 | 155 | } | 53 | } |
248 | 156 | |||
249 | 157 | // Set vblank swap interval. | ||
250 | 158 | bool ok; | ||
251 | 159 | int swapInterval = qGetEnvIntValue("QTUBUNTU_SWAPINTERVAL", &ok); | ||
252 | 160 | if (!ok) | ||
253 | 161 | swapInterval = kSwapInterval; | ||
254 | 162 | |||
255 | 163 | qCDebug(ubuntumirclient, "Setting swap interval to %d", swapInterval); | ||
256 | 164 | eglSwapInterval(mEglDisplay, swapInterval); | ||
257 | 165 | |||
258 | 166 | mEglContext = eglCreateContext(mEglDisplay, config, share ? share->eglContext() : EGL_NO_CONTEXT, | ||
259 | 167 | attribs.constData()); | ||
260 | 168 | |||
261 | 169 | Q_ASSERT(mEglContext != EGL_NO_CONTEXT); | ||
262 | 170 | } | ||
263 | 171 | |||
264 | 172 | UbuntuOpenGLContext::~UbuntuOpenGLContext() | ||
265 | 173 | { | ||
266 | 174 | ASSERT(eglDestroyContext(mEglDisplay, mEglContext) == EGL_TRUE); | ||
267 | 175 | } | 54 | } |
268 | 176 | 55 | ||
269 | 177 | static bool needsFBOReadBackWorkaround() | 56 | static bool needsFBOReadBackWorkaround() |
270 | @@ -179,7 +58,7 @@ | |||
271 | 179 | static bool set = false; | 58 | static bool set = false; |
272 | 180 | static bool needsWorkaround = false; | 59 | static bool needsWorkaround = false; |
273 | 181 | 60 | ||
275 | 182 | if (!set) { | 61 | if (Q_UNLIKELY(!set)) { |
276 | 183 | const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); | 62 | const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); |
277 | 184 | needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0 | 63 | needsWorkaround = qstrncmp(rendererString, "Mali-400", 8) == 0 |
278 | 185 | || qstrncmp(rendererString, "Mali-T7", 7) == 0 | 64 | || qstrncmp(rendererString, "Mali-T7", 7) == 0 |
279 | @@ -194,55 +73,41 @@ | |||
280 | 194 | { | 73 | { |
281 | 195 | Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); | 74 | Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); |
282 | 196 | 75 | ||
301 | 197 | if (surface->surface()->surfaceClass() == QSurface::Offscreen) { | 76 | const bool ret = QEGLPlatformContext::makeCurrent(surface); |
302 | 198 | auto offscreen = static_cast<UbuntuOffscreenSurface *>(surface); | 77 | |
303 | 199 | if (!offscreen->buffer()) { | 78 | if (Q_LIKELY(ret)) { |
286 | 200 | auto buffer = new QOpenGLFramebufferObject(surface->surface()->size()); | ||
287 | 201 | offscreen->setBuffer(buffer); | ||
288 | 202 | } | ||
289 | 203 | return offscreen->buffer()->bind(); | ||
290 | 204 | } else { | ||
291 | 205 | EGLSurface eglSurface = static_cast<UbuntuWindow*>(surface)->eglSurface(); | ||
292 | 206 | ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE); | ||
293 | 207 | |||
294 | 208 | EGLBoolean result = eglMakeCurrent(mEglDisplay, eglSurface, eglSurface, mEglContext); | ||
295 | 209 | if (result == EGL_FALSE) { | ||
296 | 210 | qCCritical(ubuntumirclient, "eglMakeCurrent() failed with %s", | ||
297 | 211 | qPrintable(eglErrorToString(eglGetError()))); | ||
298 | 212 | return false; | ||
299 | 213 | } | ||
300 | 214 | |||
304 | 215 | QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); | 79 | QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); |
305 | 216 | if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) { | 80 | if (!ctx_d->workaround_brokenFBOReadBack && needsFBOReadBackWorkaround()) { |
306 | 217 | ctx_d->workaround_brokenFBOReadBack = true; | 81 | ctx_d->workaround_brokenFBOReadBack = true; |
307 | 218 | } | 82 | } |
330 | 219 | 83 | } | |
331 | 220 | if (ubuntumirclient().isDebugEnabled()) { | 84 | |
332 | 221 | printOpenGLESConfig(); | 85 | return ret; |
333 | 222 | } | 86 | } |
334 | 223 | return true; | 87 | |
335 | 224 | } | 88 | // WORKAROUND for bug 1594198 - avoid having Qt use GLESv3 |
336 | 225 | } | 89 | QSurfaceFormat UbuntuOpenGLContext::format() const |
337 | 226 | 90 | { | |
338 | 227 | void UbuntuOpenGLContext::doneCurrent() | 91 | auto format = QEGLPlatformContext::format(); |
339 | 228 | { | 92 | if (format.renderableType() == QSurfaceFormat::OpenGLES && format.majorVersion() > 2) { |
340 | 229 | ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE); | 93 | format.setMajorVersion(2); |
341 | 230 | ASSERT(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) == EGL_TRUE); | 94 | } |
342 | 231 | } | 95 | return format; |
343 | 232 | 96 | } | |
344 | 233 | void UbuntuOpenGLContext::swapBuffers(QPlatformSurface* surface) | 97 | |
345 | 234 | { | 98 | // Following method used internally in the base class QEGLPlatformContext to access |
346 | 235 | UbuntuWindow *ubuntuWindow = static_cast<UbuntuWindow*>(surface); | 99 | // the egl surface of a QPlatformSurface/UbuntuWindow |
347 | 236 | 100 | EGLSurface UbuntuOpenGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) | |
348 | 237 | EGLSurface eglSurface = ubuntuWindow->eglSurface(); | 101 | { |
349 | 238 | ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE); | 102 | auto ubuntuWindow = static_cast<UbuntuWindow *>(surface); |
350 | 239 | ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE); | 103 | return ubuntuWindow->eglSurface(); |
351 | 240 | 104 | } | |
352 | 105 | |||
353 | 106 | void UbuntuOpenGLContext::swapBuffers(QPlatformSurface *surface) | ||
354 | 107 | { | ||
355 | 108 | QEGLPlatformContext::swapBuffers(surface); | ||
356 | 109 | |||
357 | 110 | // notify window on swap completion | ||
358 | 111 | auto ubuntuWindow = static_cast<UbuntuWindow *>(surface); | ||
359 | 241 | ubuntuWindow->onSwapBuffersDone(); | 112 | ubuntuWindow->onSwapBuffersDone(); |
360 | 242 | } | 113 | } |
361 | 243 | |||
362 | 244 | void (*UbuntuOpenGLContext::getProcAddress(const QByteArray& procName)) () | ||
363 | 245 | { | ||
364 | 246 | ASSERT(eglBindAPI(api_in_use()) == EGL_TRUE); | ||
365 | 247 | return eglGetProcAddress(procName.constData()); | ||
366 | 248 | } | ||
367 | 249 | 114 | ||
368 | === modified file 'src/ubuntumirclient/glcontext.h' | |||
369 | --- src/ubuntumirclient/glcontext.h 2016-06-20 08:37:56 +0000 | |||
370 | +++ src/ubuntumirclient/glcontext.h 2016-07-04 17:59:30 +0000 | |||
371 | @@ -18,30 +18,24 @@ | |||
372 | 18 | #define UBUNTU_OPENGL_CONTEXT_H | 18 | #define UBUNTU_OPENGL_CONTEXT_H |
373 | 19 | 19 | ||
374 | 20 | #include <qpa/qplatformopenglcontext.h> | 20 | #include <qpa/qplatformopenglcontext.h> |
375 | 21 | #include <private/qeglplatformcontext_p.h> | ||
376 | 21 | 22 | ||
377 | 22 | #include <EGL/egl.h> | 23 | #include <EGL/egl.h> |
378 | 23 | 24 | ||
380 | 24 | class UbuntuOpenGLContext : public QPlatformOpenGLContext | 25 | class UbuntuOpenGLContext : public QEGLPlatformContext |
381 | 25 | { | 26 | { |
382 | 26 | public: | 27 | public: |
401 | 27 | UbuntuOpenGLContext(const QSurfaceFormat &surfaceFormat, UbuntuOpenGLContext *share, | 28 | UbuntuOpenGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, |
402 | 28 | EGLDisplay display, EGLConfig config); | 29 | EGLDisplay display); |
403 | 29 | virtual ~UbuntuOpenGLContext(); | 30 | |
404 | 30 | 31 | // QEGLPlatformContext methods. | |
405 | 31 | // QPlatformOpenGLContext methods. | 32 | void swapBuffers(QPlatformSurface *surface) final; |
406 | 32 | QSurfaceFormat format() const override { return mSurfaceFormat; } | 33 | bool makeCurrent(QPlatformSurface *surface) final; |
407 | 33 | void swapBuffers(QPlatformSurface *surface) override; | 34 | |
408 | 34 | bool makeCurrent(QPlatformSurface *surface) override; | 35 | QSurfaceFormat format() const final; |
409 | 35 | void doneCurrent() override; | 36 | |
410 | 36 | bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; } | 37 | protected: |
411 | 37 | void (*getProcAddress(const QByteArray& procName)) () override; | 38 | EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) final; |
394 | 38 | |||
395 | 39 | EGLContext eglContext() const { return mEglContext; } | ||
396 | 40 | |||
397 | 41 | private: | ||
398 | 42 | const QSurfaceFormat mSurfaceFormat; | ||
399 | 43 | EGLContext mEglContext; | ||
400 | 44 | EGLDisplay mEglDisplay; | ||
412 | 45 | }; | 39 | }; |
413 | 46 | 40 | ||
414 | 47 | #endif // UBUNTU_OPENGL_CONTEXT_H | 41 | #endif // UBUNTU_OPENGL_CONTEXT_H |
415 | 48 | 42 | ||
416 | === modified file 'src/ubuntumirclient/integration.cpp' | |||
417 | --- src/ubuntumirclient/integration.cpp 2016-06-20 08:37:56 +0000 | |||
418 | +++ src/ubuntumirclient/integration.cpp 2016-07-04 17:59:30 +0000 | |||
419 | @@ -18,11 +18,11 @@ | |||
420 | 18 | #include "integration.h" | 18 | #include "integration.h" |
421 | 19 | #include "backingstore.h" | 19 | #include "backingstore.h" |
422 | 20 | #include "clipboard.h" | 20 | #include "clipboard.h" |
423 | 21 | #include "desktopwindow.h" | ||
424 | 21 | #include "glcontext.h" | 22 | #include "glcontext.h" |
425 | 22 | #include "input.h" | 23 | #include "input.h" |
426 | 23 | #include "logging.h" | 24 | #include "logging.h" |
427 | 24 | #include "nativeinterface.h" | 25 | #include "nativeinterface.h" |
428 | 25 | #include "offscreensurface.h" | ||
429 | 26 | #include "screen.h" | 26 | #include "screen.h" |
430 | 27 | #include "theme.h" | 27 | #include "theme.h" |
431 | 28 | #include "window.h" | 28 | #include "window.h" |
432 | @@ -30,7 +30,7 @@ | |||
433 | 30 | // Qt | 30 | // Qt |
434 | 31 | #include <QFileInfo> | 31 | #include <QFileInfo> |
435 | 32 | #include <QGuiApplication> | 32 | #include <QGuiApplication> |
437 | 33 | #include <private/qguiapplication_p.h> | 33 | #include <private/qeglpbuffer_p.h> |
438 | 34 | #include <qpa/qplatformnativeinterface.h> | 34 | #include <qpa/qplatformnativeinterface.h> |
439 | 35 | #include <qpa/qplatforminputcontextfactory_p.h> | 35 | #include <qpa/qplatforminputcontextfactory_p.h> |
440 | 36 | #include <qpa/qplatforminputcontext.h> | 36 | #include <qpa/qplatforminputcontext.h> |
441 | @@ -95,31 +95,17 @@ | |||
442 | 95 | 95 | ||
443 | 96 | mMirConnection = u_application_instance_get_mir_connection(mInstance); | 96 | mMirConnection = u_application_instance_get_mir_connection(mInstance); |
444 | 97 | 97 | ||
445 | 98 | // Choose the default surface format suited to the Mir platform | ||
446 | 99 | QSurfaceFormat defaultFormat; | ||
447 | 100 | defaultFormat.setRedBufferSize(8); | ||
448 | 101 | defaultFormat.setGreenBufferSize(8); | ||
449 | 102 | defaultFormat.setBlueBufferSize(8); | ||
450 | 103 | QSurfaceFormat::setDefaultFormat(defaultFormat); | ||
451 | 104 | |||
452 | 98 | // Initialize EGL. | 105 | // Initialize EGL. |
453 | 99 | ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE); | ||
454 | 100 | |||
455 | 101 | mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection); | 106 | mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection); |
456 | 102 | ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY); | 107 | ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY); |
457 | 103 | ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE); | 108 | ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE); |
458 | 104 | |||
459 | 105 | // Configure EGL buffers format for all Windows. | ||
460 | 106 | mSurfaceFormat.setRedBufferSize(8); | ||
461 | 107 | mSurfaceFormat.setGreenBufferSize(8); | ||
462 | 108 | mSurfaceFormat.setBlueBufferSize(8); | ||
463 | 109 | mSurfaceFormat.setAlphaBufferSize(8); | ||
464 | 110 | mSurfaceFormat.setDepthBufferSize(24); | ||
465 | 111 | mSurfaceFormat.setStencilBufferSize(8); | ||
466 | 112 | if (!qEnvironmentVariableIsEmpty("QTUBUNTU_MULTISAMPLE")) { | ||
467 | 113 | mSurfaceFormat.setSamples(4); | ||
468 | 114 | qCDebug(ubuntumirclient, "setting MSAA to 4 samples"); | ||
469 | 115 | } | ||
470 | 116 | #ifdef QTUBUNTU_USE_OPENGL | ||
471 | 117 | mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGL); | ||
472 | 118 | #else | ||
473 | 119 | mSurfaceFormat.setRenderableType(QSurfaceFormat::OpenGLES); | ||
474 | 120 | #endif | ||
475 | 121 | |||
476 | 122 | mEglConfig = q_configFromGLFormat(mEglDisplay, mSurfaceFormat, true); | ||
477 | 123 | } | 109 | } |
478 | 124 | 110 | ||
479 | 125 | void UbuntuClientIntegration::initialize() | 111 | void UbuntuClientIntegration::initialize() |
480 | @@ -226,7 +212,12 @@ | |||
481 | 226 | 212 | ||
482 | 227 | QPlatformWindow* UbuntuClientIntegration::createPlatformWindow(QWindow* window) const | 213 | QPlatformWindow* UbuntuClientIntegration::createPlatformWindow(QWindow* window) const |
483 | 228 | { | 214 | { |
485 | 229 | return new UbuntuWindow(window, mClipboard, mInput, mNativeInterface, mEglDisplay, mEglConfig, mMirConnection); | 215 | if (window->type() == Qt::Desktop) { |
486 | 216 | // Desktop windows should not be backed up by a mir surface as they don't draw anything (nor should). | ||
487 | 217 | return new UbuntuDesktopWindow(window); | ||
488 | 218 | } else { | ||
489 | 219 | return new UbuntuWindow(window, mClipboard, mInput, mNativeInterface, mEglDisplay, mMirConnection); | ||
490 | 220 | } | ||
491 | 230 | } | 221 | } |
492 | 231 | 222 | ||
493 | 232 | bool UbuntuClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const | 223 | bool UbuntuClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const |
494 | @@ -250,6 +241,7 @@ | |||
495 | 250 | } | 241 | } |
496 | 251 | case MultipleWindows: | 242 | case MultipleWindows: |
497 | 252 | case NonFullScreenWindows: | 243 | case NonFullScreenWindows: |
498 | 244 | case RasterGLSurface: | ||
499 | 253 | return true; | 245 | return true; |
500 | 254 | default: | 246 | default: |
501 | 255 | return QPlatformIntegration::hasCapability(cap); | 247 | return QPlatformIntegration::hasCapability(cap); |
502 | @@ -269,8 +261,25 @@ | |||
503 | 269 | QPlatformOpenGLContext* UbuntuClientIntegration::createPlatformOpenGLContext( | 261 | QPlatformOpenGLContext* UbuntuClientIntegration::createPlatformOpenGLContext( |
504 | 270 | QOpenGLContext* context) const | 262 | QOpenGLContext* context) const |
505 | 271 | { | 263 | { |
508 | 272 | return new UbuntuOpenGLContext(mSurfaceFormat, static_cast<UbuntuOpenGLContext*>(context->shareHandle()), | 264 | QSurfaceFormat format(context->format()); |
509 | 273 | mEglDisplay, mEglConfig); | 265 | |
510 | 266 | auto platformContext = new UbuntuOpenGLContext(format, context->shareHandle(), mEglDisplay); | ||
511 | 267 | if (!platformContext->isValid()) { | ||
512 | 268 | // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default | ||
513 | 269 | // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a | ||
514 | 270 | // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to | ||
515 | 271 | // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default | ||
516 | 272 | // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455). | ||
517 | 273 | static const bool isMesa = QString(eglQueryString(mEglDisplay, EGL_VENDOR)).contains(QStringLiteral("Mesa")); | ||
518 | 274 | if (isMesa) { | ||
519 | 275 | qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa"); | ||
520 | 276 | format.setMajorVersion(1); | ||
521 | 277 | format.setMinorVersion(4); | ||
522 | 278 | delete platformContext; | ||
523 | 279 | platformContext = new UbuntuOpenGLContext(format, context->shareHandle(), mEglDisplay); | ||
524 | 280 | } | ||
525 | 281 | } | ||
526 | 282 | return platformContext; | ||
527 | 274 | } | 283 | } |
528 | 275 | 284 | ||
529 | 276 | QStringList UbuntuClientIntegration::themeNames() const | 285 | QStringList UbuntuClientIntegration::themeNames() const |
530 | @@ -314,7 +323,7 @@ | |||
531 | 314 | QPlatformOffscreenSurface *UbuntuClientIntegration::createPlatformOffscreenSurface( | 323 | QPlatformOffscreenSurface *UbuntuClientIntegration::createPlatformOffscreenSurface( |
532 | 315 | QOffscreenSurface *surface) const | 324 | QOffscreenSurface *surface) const |
533 | 316 | { | 325 | { |
535 | 317 | return new UbuntuOffscreenSurface(surface); | 326 | return new QEGLPbuffer(mEglDisplay, QSurfaceFormat::defaultFormat(), surface); |
536 | 318 | } | 327 | } |
537 | 319 | 328 | ||
538 | 320 | void UbuntuClientIntegration::destroyScreen(UbuntuScreen *screen) | 329 | void UbuntuClientIntegration::destroyScreen(UbuntuScreen *screen) |
539 | 321 | 330 | ||
540 | === modified file 'src/ubuntumirclient/integration.h' | |||
541 | --- src/ubuntumirclient/integration.h 2016-06-20 08:37:56 +0000 | |||
542 | +++ src/ubuntumirclient/integration.h 2016-07-04 17:59:30 +0000 | |||
543 | @@ -62,9 +62,7 @@ | |||
544 | 62 | 62 | ||
545 | 63 | // New methods. | 63 | // New methods. |
546 | 64 | MirConnection *mirConnection() const { return mMirConnection; } | 64 | MirConnection *mirConnection() const { return mMirConnection; } |
547 | 65 | QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; } | ||
548 | 66 | EGLDisplay eglDisplay() const { return mEglDisplay; } | 65 | EGLDisplay eglDisplay() const { return mEglDisplay; } |
549 | 67 | EGLConfig eglConfig() const { return mEglConfig; } | ||
550 | 68 | EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; } | 66 | EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; } |
551 | 69 | UbuntuScreenObserver *screenObserver() const { return mScreenObserver.data(); } | 67 | UbuntuScreenObserver *screenObserver() const { return mScreenObserver.data(); } |
552 | 70 | 68 | ||
553 | @@ -97,9 +95,7 @@ | |||
554 | 97 | 95 | ||
555 | 98 | // EGL related | 96 | // EGL related |
556 | 99 | EGLDisplay mEglDisplay{EGL_NO_DISPLAY}; | 97 | EGLDisplay mEglDisplay{EGL_NO_DISPLAY}; |
557 | 100 | EGLConfig mEglConfig{nullptr}; | ||
558 | 101 | EGLNativeDisplayType mEglNativeDisplay; | 98 | EGLNativeDisplayType mEglNativeDisplay; |
559 | 102 | QSurfaceFormat mSurfaceFormat; | ||
560 | 103 | }; | 99 | }; |
561 | 104 | 100 | ||
562 | 105 | #endif // UBUNTU_CLIENT_INTEGRATION_H | 101 | #endif // UBUNTU_CLIENT_INTEGRATION_H |
563 | 106 | 102 | ||
564 | === removed file 'src/ubuntumirclient/offscreensurface.cpp' | |||
565 | --- src/ubuntumirclient/offscreensurface.cpp 2016-01-04 17:18:51 +0000 | |||
566 | +++ src/ubuntumirclient/offscreensurface.cpp 1970-01-01 00:00:00 +0000 | |||
567 | @@ -1,47 +0,0 @@ | |||
568 | 1 | /* | ||
569 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
570 | 3 | * | ||
571 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
572 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
573 | 6 | * the Free Software Foundation. | ||
574 | 7 | * | ||
575 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
576 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
577 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
578 | 11 | * Lesser General Public License for more details. | ||
579 | 12 | * | ||
580 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
581 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
582 | 15 | */ | ||
583 | 16 | |||
584 | 17 | #include "offscreensurface.h" | ||
585 | 18 | |||
586 | 19 | #include <QOffscreenSurface> | ||
587 | 20 | #include <QOpenGLFramebufferObject> | ||
588 | 21 | |||
589 | 22 | UbuntuOffscreenSurface::UbuntuOffscreenSurface(QOffscreenSurface *offscreenSurface) | ||
590 | 23 | : QPlatformOffscreenSurface(offscreenSurface) | ||
591 | 24 | , m_buffer(nullptr) | ||
592 | 25 | , m_format(offscreenSurface->requestedFormat()) | ||
593 | 26 | { | ||
594 | 27 | } | ||
595 | 28 | |||
596 | 29 | QSurfaceFormat UbuntuOffscreenSurface::format() const | ||
597 | 30 | { | ||
598 | 31 | return m_format; | ||
599 | 32 | } | ||
600 | 33 | |||
601 | 34 | bool UbuntuOffscreenSurface::isValid() const | ||
602 | 35 | { | ||
603 | 36 | return m_buffer != nullptr && m_buffer->isValid(); | ||
604 | 37 | } | ||
605 | 38 | |||
606 | 39 | QOpenGLFramebufferObject* UbuntuOffscreenSurface::buffer() const | ||
607 | 40 | { | ||
608 | 41 | return m_buffer; | ||
609 | 42 | } | ||
610 | 43 | |||
611 | 44 | void UbuntuOffscreenSurface::setBuffer(QOpenGLFramebufferObject *buffer) | ||
612 | 45 | { | ||
613 | 46 | m_buffer = buffer; | ||
614 | 47 | } | ||
615 | 48 | 0 | ||
616 | === removed file 'src/ubuntumirclient/offscreensurface.h' | |||
617 | --- src/ubuntumirclient/offscreensurface.h 2016-01-04 17:18:51 +0000 | |||
618 | +++ src/ubuntumirclient/offscreensurface.h 1970-01-01 00:00:00 +0000 | |||
619 | @@ -1,41 +0,0 @@ | |||
620 | 1 | /* | ||
621 | 2 | * Copyright (C) 2016 Canonical, Ltd. | ||
622 | 3 | * | ||
623 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
624 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
625 | 6 | * the Free Software Foundation. | ||
626 | 7 | * | ||
627 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
628 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
629 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
630 | 11 | * Lesser General Public License for more details. | ||
631 | 12 | * | ||
632 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
633 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
634 | 15 | */ | ||
635 | 16 | |||
636 | 17 | #ifndef UBUNTU_OFFSCREEN_SURFACE_H | ||
637 | 18 | #define UBUNTU_OFFSCREEN_SURFACE_H | ||
638 | 19 | |||
639 | 20 | #include <qpa/qplatformoffscreensurface.h> | ||
640 | 21 | #include <QSurfaceFormat> | ||
641 | 22 | |||
642 | 23 | class QOpenGLFramebufferObject; | ||
643 | 24 | |||
644 | 25 | class UbuntuOffscreenSurface : public QPlatformOffscreenSurface | ||
645 | 26 | { | ||
646 | 27 | public: | ||
647 | 28 | UbuntuOffscreenSurface(QOffscreenSurface *offscreenSurface); | ||
648 | 29 | |||
649 | 30 | QSurfaceFormat format() const override; | ||
650 | 31 | bool isValid() const override; | ||
651 | 32 | |||
652 | 33 | QOpenGLFramebufferObject* buffer() const; | ||
653 | 34 | void setBuffer(QOpenGLFramebufferObject *buffer); | ||
654 | 35 | |||
655 | 36 | private: | ||
656 | 37 | QOpenGLFramebufferObject *m_buffer; | ||
657 | 38 | QSurfaceFormat m_format; | ||
658 | 39 | }; | ||
659 | 40 | |||
660 | 41 | #endif // UBUNTU_OFFSCREEN_SURFACE_H | ||
661 | 42 | 0 | ||
662 | === modified file 'src/ubuntumirclient/ubuntumirclient.pro' | |||
663 | --- src/ubuntumirclient/ubuntumirclient.pro 2016-05-30 17:14:14 +0000 | |||
664 | +++ src/ubuntumirclient/ubuntumirclient.pro 2016-07-04 17:59:30 +0000 | |||
665 | @@ -18,11 +18,11 @@ | |||
666 | 18 | backingstore.cpp \ | 18 | backingstore.cpp \ |
667 | 19 | clipboard.cpp \ | 19 | clipboard.cpp \ |
668 | 20 | cursor.cpp \ | 20 | cursor.cpp \ |
669 | 21 | desktopwindow.cpp \ | ||
670 | 21 | glcontext.cpp \ | 22 | glcontext.cpp \ |
671 | 22 | input.cpp \ | 23 | input.cpp \ |
672 | 23 | integration.cpp \ | 24 | integration.cpp \ |
673 | 24 | nativeinterface.cpp \ | 25 | nativeinterface.cpp \ |
674 | 25 | offscreensurface.cpp \ | ||
675 | 26 | platformservices.cpp \ | 26 | platformservices.cpp \ |
676 | 27 | plugin.cpp \ | 27 | plugin.cpp \ |
677 | 28 | screen.cpp \ | 28 | screen.cpp \ |
678 | @@ -34,12 +34,12 @@ | |||
679 | 34 | backingstore.h \ | 34 | backingstore.h \ |
680 | 35 | clipboard.h \ | 35 | clipboard.h \ |
681 | 36 | cursor.h \ | 36 | cursor.h \ |
682 | 37 | desktopwindow.h \ | ||
683 | 37 | glcontext.h \ | 38 | glcontext.h \ |
684 | 38 | input.h \ | 39 | input.h \ |
685 | 39 | integration.h \ | 40 | integration.h \ |
686 | 40 | logging.h \ | 41 | logging.h \ |
687 | 41 | nativeinterface.h \ | 42 | nativeinterface.h \ |
688 | 42 | offscreensurface.h \ | ||
689 | 43 | orientationchangeevent_p.h \ | 43 | orientationchangeevent_p.h \ |
690 | 44 | platformservices.h \ | 44 | platformservices.h \ |
691 | 45 | plugin.h \ | 45 | plugin.h \ |
692 | 46 | 46 | ||
693 | === modified file 'src/ubuntumirclient/window.cpp' | |||
694 | --- src/ubuntumirclient/window.cpp 2016-06-20 08:37:56 +0000 | |||
695 | +++ src/ubuntumirclient/window.cpp 2016-07-04 17:59:30 +0000 | |||
696 | @@ -29,6 +29,7 @@ | |||
697 | 29 | #include <QMutexLocker> | 29 | #include <QMutexLocker> |
698 | 30 | #include <QSize> | 30 | #include <QSize> |
699 | 31 | #include <QtMath> | 31 | #include <QtMath> |
700 | 32 | #include <private/qeglconvenience_p.h> | ||
701 | 32 | 33 | ||
702 | 33 | // Platform API | 34 | // Platform API |
703 | 34 | #include <ubuntu/application/instance.h> | 35 | #include <ubuntu/application/instance.h> |
704 | @@ -101,6 +102,24 @@ | |||
705 | 101 | } | 102 | } |
706 | 102 | } | 103 | } |
707 | 103 | 104 | ||
708 | 105 | const char *mirPixelFormatToStr(MirPixelFormat pixelFormat) | ||
709 | 106 | { | ||
710 | 107 | switch (pixelFormat) { | ||
711 | 108 | case mir_pixel_format_invalid: return "invalid"; | ||
712 | 109 | case mir_pixel_format_abgr_8888: return "ABGR8888"; | ||
713 | 110 | case mir_pixel_format_xbgr_8888: return "XBGR8888"; | ||
714 | 111 | case mir_pixel_format_argb_8888: return "ARGB8888"; | ||
715 | 112 | case mir_pixel_format_xrgb_8888: return "XRGB8888"; | ||
716 | 113 | case mir_pixel_format_bgr_888: return "BGR888"; | ||
717 | 114 | case mir_pixel_format_rgb_888: return "RGB888"; | ||
718 | 115 | case mir_pixel_format_rgb_565: return "RGB565"; | ||
719 | 116 | case mir_pixel_format_rgba_5551: return "RGBA5551"; | ||
720 | 117 | case mir_pixel_format_rgba_4444: return "RGBA4444"; | ||
721 | 118 | case mir_pixel_formats: | ||
722 | 119 | default: return "???"; | ||
723 | 120 | } | ||
724 | 121 | } | ||
725 | 122 | |||
726 | 104 | MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state) | 123 | MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state) |
727 | 105 | { | 124 | { |
728 | 106 | switch (state) { | 125 | switch (state) { |
729 | @@ -124,14 +143,6 @@ | |||
730 | 124 | return id++; | 143 | return id++; |
731 | 125 | } | 144 | } |
732 | 126 | 145 | ||
733 | 127 | MirPixelFormat defaultPixelFormatFor(MirConnection *connection) | ||
734 | 128 | { | ||
735 | 129 | MirPixelFormat format; | ||
736 | 130 | unsigned int nformats; | ||
737 | 131 | mir_connection_get_available_surface_formats(connection, &format, 1, &nformats); | ||
738 | 132 | return format; | ||
739 | 133 | } | ||
740 | 134 | |||
741 | 135 | UAUiWindowRole roleFor(QWindow *window) | 146 | UAUiWindowRole roleFor(QWindow *window) |
742 | 136 | { | 147 | { |
743 | 137 | QVariant roleVariant = window->property("role"); | 148 | QVariant roleVariant = window->property("role"); |
744 | @@ -151,12 +162,11 @@ | |||
745 | 151 | return parent ? static_cast<UbuntuWindow *>(parent->handle()) : nullptr; | 162 | return parent ? static_cast<UbuntuWindow *>(parent->handle()) : nullptr; |
746 | 152 | } | 163 | } |
747 | 153 | 164 | ||
749 | 154 | Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirConnection *connection) | 165 | Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirPixelFormat pixelFormat, MirConnection *connection) |
750 | 155 | { | 166 | { |
751 | 156 | const auto geom = window->geometry(); | 167 | const auto geom = window->geometry(); |
752 | 157 | const int width = geom.width() > 0 ? geom.width() : 1; | 168 | const int width = geom.width() > 0 ? geom.width() : 1; |
753 | 158 | const int height = geom.height() > 0 ? geom.height() : 1; | 169 | const int height = geom.height() > 0 ? geom.height() : 1; |
754 | 159 | const auto pixelFormat = defaultPixelFormatFor(connection); | ||
755 | 160 | 170 | ||
756 | 161 | if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) { | 171 | if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) { |
757 | 162 | qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height); | 172 | qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height); |
758 | @@ -217,11 +227,11 @@ | |||
759 | 217 | } | 227 | } |
760 | 218 | } | 228 | } |
761 | 219 | 229 | ||
763 | 220 | MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input, | 230 | MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input, MirPixelFormat pixelFormat, |
764 | 221 | MirConnection *connection, mir_surface_event_callback inputCallback, | 231 | MirConnection *connection, mir_surface_event_callback inputCallback, |
765 | 222 | void* inputContext) | 232 | void* inputContext) |
766 | 223 | { | 233 | { |
768 | 224 | auto spec = makeSurfaceSpec(window, input, connection); | 234 | auto spec = makeSurfaceSpec(window, input, pixelFormat, connection); |
769 | 225 | 235 | ||
770 | 226 | // Install event handler as early as possible | 236 | // Install event handler as early as possible |
771 | 227 | mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext); | 237 | mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext); |
772 | @@ -244,6 +254,18 @@ | |||
773 | 244 | return surface; | 254 | return surface; |
774 | 245 | } | 255 | } |
775 | 246 | 256 | ||
776 | 257 | MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat) | ||
777 | 258 | { | ||
778 | 259 | switch(pixelFormat) { | ||
779 | 260 | case mir_pixel_format_abgr_8888: | ||
780 | 261 | return mir_pixel_format_xbgr_8888; | ||
781 | 262 | case mir_pixel_format_argb_8888: | ||
782 | 263 | return mir_pixel_format_xrgb_8888; | ||
783 | 264 | default: // can do nothing, leave it alone | ||
784 | 265 | return pixelFormat; | ||
785 | 266 | } | ||
786 | 267 | } | ||
787 | 268 | |||
788 | 247 | // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633 | 269 | // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633 |
789 | 248 | // we need to guess the panel height (3GU) | 270 | // we need to guess the panel height (3GU) |
790 | 249 | int panelHeight() | 271 | int panelHeight() |
791 | @@ -266,8 +288,7 @@ | |||
792 | 266 | class UbuntuSurface | 288 | class UbuntuSurface |
793 | 267 | { | 289 | { |
794 | 268 | public: | 290 | public: |
797 | 269 | UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, EGLConfig config, int mirOutputId, | 291 | UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection) |
796 | 270 | UbuntuInput *input, MirConnection *connection) | ||
798 | 271 | : mWindow(platformWindow->window()) | 292 | : mWindow(platformWindow->window()) |
799 | 272 | , mPlatformWindow(platformWindow) | 293 | , mPlatformWindow(platformWindow) |
800 | 273 | , mInput(input) | 294 | , mInput(input) |
801 | @@ -275,9 +296,44 @@ | |||
802 | 275 | , mEglDisplay(display) | 296 | , mEglDisplay(display) |
803 | 276 | , mNeedsRepaint(false) | 297 | , mNeedsRepaint(false) |
804 | 277 | , mParented(mWindow->transientParent() || mWindow->parent()) | 298 | , mParented(mWindow->transientParent() || mWindow->parent()) |
805 | 299 | , mFormat(mWindow->requestedFormat()) | ||
806 | 278 | , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal) | 300 | , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal) |
807 | 279 | { | 301 | { |
809 | 280 | mMirSurface = createMirSurface(mWindow, mirOutputId, input, connection, surfaceEventCallback, this); | 302 | // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it |
810 | 303 | EGLConfig config = q_configFromGLFormat(display, mFormat, true); | ||
811 | 304 | if (config == 0) { | ||
812 | 305 | // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default | ||
813 | 306 | // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a | ||
814 | 307 | // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to | ||
815 | 308 | // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default | ||
816 | 309 | // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455). | ||
817 | 310 | static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa")); | ||
818 | 311 | if (isMesa) { | ||
819 | 312 | qCDebug(ubuntumirclient, "Attempting to choose OpenGL 1.4 context which may suit Mesa"); | ||
820 | 313 | mFormat.setMajorVersion(1); | ||
821 | 314 | mFormat.setMinorVersion(4); | ||
822 | 315 | config = q_configFromGLFormat(display, mFormat, true); | ||
823 | 316 | } | ||
824 | 317 | } | ||
825 | 318 | if (config == 0) { | ||
826 | 319 | qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat; | ||
827 | 320 | } | ||
828 | 321 | |||
829 | 322 | mFormat = q_glFormatFromConfig(display, config, mFormat); | ||
830 | 323 | |||
831 | 324 | // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way | ||
832 | 325 | // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers. | ||
833 | 326 | auto pixelFormat = mir_connection_get_egl_pixel_format(connection, display, config); | ||
834 | 327 | // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client. | ||
835 | 328 | // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer. | ||
836 | 329 | // This is an optimisation for the compositor, as it can avoid blending this surface. | ||
837 | 330 | if (mWindow->requestedFormat().alphaBufferSize() < 0) { | ||
838 | 331 | pixelFormat = disableAlphaBufferIfPossible(pixelFormat); | ||
839 | 332 | } | ||
840 | 333 | |||
841 | 334 | const auto outputId = static_cast<UbuntuScreen *>(mWindow->screen()->handle())->mirOutputId(); | ||
842 | 335 | |||
843 | 336 | mMirSurface = createMirSurface(mWindow, outputId, input, pixelFormat, connection, surfaceEventCallback, this); | ||
844 | 281 | mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr); | 337 | mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr); |
845 | 282 | 338 | ||
846 | 283 | // Window manager can give us a final size different from what we asked for | 339 | // Window manager can give us a final size different from what we asked for |
847 | @@ -299,8 +355,11 @@ | |||
848 | 299 | platformWindow->QPlatformWindow::setGeometry(geom); | 355 | platformWindow->QPlatformWindow::setGeometry(geom); |
849 | 300 | QWindowSystemInterface::handleGeometryChange(mWindow, geom); | 356 | QWindowSystemInterface::handleGeometryChange(mWindow, geom); |
850 | 301 | 357 | ||
853 | 302 | qCDebug(ubuntumirclient, "created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n", | 358 | qCDebug(ubuntumirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title() |
854 | 303 | geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow)); | 359 | << "role:" << roleFor(mWindow) |
855 | 360 | << "\nRequested format:" << mWindow->requestedFormat() | ||
856 | 361 | << "\nActual format:" << mFormat | ||
857 | 362 | << "with associated Mir pixel format:" << mirPixelFormatToStr(pixelFormat); | ||
858 | 304 | } | 363 | } |
859 | 305 | 364 | ||
860 | 306 | ~UbuntuSurface() | 365 | ~UbuntuSurface() |
861 | @@ -335,6 +394,8 @@ | |||
862 | 335 | void setSurfaceParent(MirSurface*); | 394 | void setSurfaceParent(MirSurface*); |
863 | 336 | bool hasParent() const { return mParented; } | 395 | bool hasParent() const { return mParented; } |
864 | 337 | 396 | ||
865 | 397 | QSurfaceFormat format() const { return mFormat; } | ||
866 | 398 | |||
867 | 338 | private: | 399 | private: |
868 | 339 | static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context); | 400 | static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context); |
869 | 340 | void postEvent(const MirEvent *event); | 401 | void postEvent(const MirEvent *event); |
870 | @@ -351,6 +412,7 @@ | |||
871 | 351 | bool mNeedsRepaint; | 412 | bool mNeedsRepaint; |
872 | 352 | bool mParented; | 413 | bool mParented; |
873 | 353 | QSize mBufferSize; | 414 | QSize mBufferSize; |
874 | 415 | QSurfaceFormat mFormat; | ||
875 | 354 | 416 | ||
876 | 355 | QMutex mTargetSizeMutex; | 417 | QMutex mTargetSizeMutex; |
877 | 356 | QSize mTargetSize; | 418 | QSize mTargetSize; |
878 | @@ -509,8 +571,7 @@ | |||
879 | 509 | } | 571 | } |
880 | 510 | 572 | ||
881 | 511 | UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard, | 573 | UbuntuWindow::UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard, |
884 | 512 | UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay, | 574 | UbuntuInput *input, UbuntuNativeInterface *native, EGLDisplay eglDisplay, MirConnection *mirConnection) |
883 | 513 | EGLConfig eglConfig, MirConnection *mirConnection) | ||
885 | 514 | : QObject(nullptr) | 575 | : QObject(nullptr) |
886 | 515 | , QPlatformWindow(w) | 576 | , QPlatformWindow(w) |
887 | 516 | , mId(makeId()) | 577 | , mId(makeId()) |
888 | @@ -520,8 +581,7 @@ | |||
889 | 520 | , mWindowVisible(false) | 581 | , mWindowVisible(false) |
890 | 521 | , mWindowExposed(true) | 582 | , mWindowExposed(true) |
891 | 522 | , mNativeInterface(native) | 583 | , mNativeInterface(native) |
894 | 523 | , mSurface(new UbuntuSurface{this, eglDisplay, eglConfig, | 584 | , mSurface(new UbuntuSurface{this, eglDisplay, input, mirConnection}) |
893 | 524 | static_cast<UbuntuScreen*>(w->screen()->handle())->mirOutputId(), input, mirConnection}) | ||
895 | 525 | , mScale(1.0) | 585 | , mScale(1.0) |
896 | 526 | , mFormFactor(mir_form_factor_unknown) | 586 | , mFormFactor(mir_form_factor_unknown) |
897 | 527 | { | 587 | { |
898 | @@ -709,6 +769,11 @@ | |||
899 | 709 | return mWindowVisible && mWindowExposed; | 769 | return mWindowVisible && mWindowExposed; |
900 | 710 | } | 770 | } |
901 | 711 | 771 | ||
902 | 772 | QSurfaceFormat UbuntuWindow::format() const | ||
903 | 773 | { | ||
904 | 774 | return mSurface->format(); | ||
905 | 775 | } | ||
906 | 776 | |||
907 | 712 | void* UbuntuWindow::eglSurface() const | 777 | void* UbuntuWindow::eglSurface() const |
908 | 713 | { | 778 | { |
909 | 714 | return mSurface->eglSurface(); | 779 | return mSurface->eglSurface(); |
910 | 715 | 780 | ||
911 | === modified file 'src/ubuntumirclient/window.h' | |||
912 | --- src/ubuntumirclient/window.h 2016-06-20 08:37:56 +0000 | |||
913 | +++ src/ubuntumirclient/window.h 2016-07-04 17:59:30 +0000 | |||
914 | @@ -40,7 +40,7 @@ | |||
915 | 40 | Q_OBJECT | 40 | Q_OBJECT |
916 | 41 | public: | 41 | public: |
917 | 42 | UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard, | 42 | UbuntuWindow(QWindow *w, const QSharedPointer<UbuntuClipboard> &clipboard, |
919 | 43 | UbuntuInput *input, UbuntuNativeInterface* native, EGLDisplay eglDisplay, EGLConfig eglConfig, | 43 | UbuntuInput *input, UbuntuNativeInterface* native, EGLDisplay eglDisplay, |
920 | 44 | MirConnection *mirConnection); | 44 | MirConnection *mirConnection); |
921 | 45 | virtual ~UbuntuWindow(); | 45 | virtual ~UbuntuWindow(); |
922 | 46 | 46 | ||
923 | @@ -54,6 +54,8 @@ | |||
924 | 54 | void propagateSizeHints() override; | 54 | void propagateSizeHints() override; |
925 | 55 | bool isExposed() const override; | 55 | bool isExposed() const override; |
926 | 56 | 56 | ||
927 | 57 | QSurfaceFormat format() const override; | ||
928 | 58 | |||
929 | 57 | // Additional Window properties exposed by NativeInterface | 59 | // Additional Window properties exposed by NativeInterface |
930 | 58 | MirFormFactor formFactor() const { return mFormFactor; } | 60 | MirFormFactor formFactor() const { return mFormFactor; } |
931 | 59 | float scale() const { return mScale; } | 61 | float scale() const { return mScale; } |
PASSED: Continuous integration, rev:330 /unity8- jenkins. ubuntu. com/job/ lp-qtubuntu- ci/93/ /unity8- jenkins. ubuntu. com/job/ build/2209 /unity8- jenkins. ubuntu. com/job/ build-0- fetch/2237 /unity8- jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= vivid+overlay/ 2143 /unity8- jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= xenial+ overlay/ 2143 /unity8- jenkins. ubuntu. com/job/ build-1- sourcepkg/ release= yakkety/ 2143 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 2134/artifact/ output/ *zip*/output. zip /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2134 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= yakkety/ 2134/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-qtubuntu- ci/93/rebuild
https:/