Merge lp:~albaguirre/qtubuntu/use-mir-rs-api into lp:qtubuntu

Proposed by Alberto Aguirre on 2017-03-31
Status: Needs review
Proposed branch: lp:~albaguirre/qtubuntu/use-mir-rs-api
Merge into: lp:qtubuntu
Diff against target: 592 lines (+154/-188)
7 files modified
debian/control (+3/-4)
src/ubuntumirclient/qmirclientcursor.cpp (+68/-25)
src/ubuntumirclient/qmirclientinput.cpp (+0/-4)
src/ubuntumirclient/qmirclientintegration.cpp (+1/-2)
src/ubuntumirclient/qmirclientintegration.h (+1/-2)
src/ubuntumirclient/qmirclientwindow.cpp (+80/-150)
src/ubuntumirclient/ubuntumirclient.pro (+1/-1)
To merge this branch: bzr merge lp:~albaguirre/qtubuntu/use-mir-rs-api
Reviewer Review Type Date Requested Status
Unity8 CI Bot continuous-integration Needs Fixing on 2017-05-27
Gerry Boland (community) Needs Information on 2017-05-22
Alan Griffiths 2017-03-31 Needs Information on 2017-05-19
Review via email: mp+321627@code.launchpad.net

Commit message

Avoid use of deprecated mir EGL related apis.

With the new mesa update, the EGLNativeDisplayType is MirConnection * and the EGLNativeWindowType is a MirRenderSurface *.

Ignore deprecation warnings on use of MirRenderSurface - its "deprecated" because it'll be renamed in mir 1.0.

To post a comment you must log in.
Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

This would be nicely simplified by lp:~alan-griffiths/mir/deprecation-macros plus -DMIR_DEPRECATE_RENDERSURFACES=0

Alan Griffiths (alan-griffiths) wrote :

Looks mostly sensible, but I need to get more familiar with qtubuntu to be sure.

Can we aim to land lp:~alan-griffiths/mir/deprecation-macros and use -DMIR_DEPRECATE_RENDERSURFACES=0 - or building against trunk Mir an issue?

review: Needs Information
Gerry Boland (gerboland) wrote :

I have a question about how pixel formats work with the newer Mir API. I see you've removed code where Qt could set a desired pixel format on the mir surface - is this feature impossible to replicate?

This was done because sometimes the EGL config chosen may have an alpha buffer enabled, even if Qt doesn't need it. We used the mir pixel format to inform the Mir compositor that blending is not required in that case - a nice optimisation.

review: Needs Information
Gerry Boland (gerboland) wrote :

I agree with Alan that using his deprecation bits would be nice, but I'd be ok with landing this in the current state if we need this to land first.

Alan Griffiths (alan-griffiths) wrote :

> I have a question about how pixel formats work with the newer Mir API. I see
> you've removed code where Qt could set a desired pixel format on the mir
> surface - is this feature impossible to replicate?

Mir currently has "Window" and "RenderSurface" but not "surface". I assume you mean "RenderSurface"?

> This was done because sometimes the EGL config chosen may have an alpha buffer
> enabled, even if Qt doesn't need it. We used the mir pixel format to inform
> the Mir compositor that blending is not required in that case - a nice
> optimisation.

I don't see that in the RS code, but I'm still learning my way around it.

Gerry Boland (gerboland) wrote :

And the obvious question: can we jump to using non-deprecated APIs in one go?

Alan Griffiths (alan-griffiths) wrote :

> And the obvious question: can we jump to using non-deprecated APIs in one go?

It depends.

The reason for the current situation being that we can't introduce the intended "surface" APIs until we delete the current ones.

The RS APIs are a temporary workaround to enable the "surface" functionality without a name clash.

If we decide not to rename MirRenderSurface => MirSurface in 1.0 we can just remove the deprecation of render surface.

Gerry Boland (gerboland) wrote :

+ // Assume that the buffer size matches the surface size at creation time
I'd rather not make that assumption. Does the new API loose this functionality?

Gerry Boland (gerboland) wrote :

+bool UbuntuSurface::needsRepaint() const
+{
+ return mNeedsRepaint;

This can totally go away AFAICS, since this changes the buffer "ownership" drastically. Before when we got a surface resize event, we had to keep swapping buffers until we got one sized at the new size - so we had to keep force repainting until that happened. Now since Qt owns the buffer, it can resize immediately.

Removing all the needsRepaint stuff also makes resizing smoother IMO in my tests here.

Gerry Boland (gerboland) wrote :

overall looks ok, I just
- miss the pixel format optimisation
- would ultimately like to remove any deprecated api use (but not necessarily in this MP)

Alberto Aguirre (albaguirre) wrote :

> I have a question about how pixel formats work with the newer Mir API. I see
> you've removed code where Qt could set a desired pixel format on the mir
> surface - is this feature impossible to replicate?
>
> This was done because sometimes the EGL config chosen may have an alpha buffer
> enabled, even if Qt doesn't need it. We used the mir pixel format to inform
> the Mir compositor that blending is not required in that case - a nice
> optimisation.

The pixel format for EGL rendering is now set through the chosen EGLConfig. The new mir mesa path will actually obey the pixel format selected.

If you want to use mir_pixel_format enums, you can specify a EGL_NATIVE_VISUAL_ID in the attribs list during eglChooseConfig and it'll be respected.

Alberto Aguirre (albaguirre) wrote :

> + // Assume that the buffer size matches the surface size at creation time
> I'd rather not make that assumption. Does the new API loose this
> functionality?

If the size chosen by the server is changed, it now gets delivered as a resize event as long as the event handler was registered through the window spec. This means that the same resizing logic is applied.

I tested this slightly by using the fullscreen window manager option in mir's demo server.

Unity8 CI Bot (unity8-ci-bot) wrote :
review: Needs Fixing (continuous-integration)
Alberto Aguirre (albaguirre) wrote :

> overall looks ok, I just
> - miss the pixel format optimisation
I'll look into that, I should just be able to use EGL_NATIVE_VISUAL_ID.

Alberto Aguirre (albaguirre) wrote :

> Looks mostly sensible, but I need to get more familiar with qtubuntu to be
> sure.
>
> Can we aim to land lp:~alan-griffiths/mir/deprecation-macros and use
> -DMIR_DEPRECATE_RENDERSURFACES=0 - or building against trunk Mir an issue?

Shouldn't be an issue on a local machine, but qtubuntu's CI would be.

397. By Alberto Aguirre on 2017-05-27

Cleanup #pragmas and unneeded repaints when resizing.

Unmerged revisions

397. By Alberto Aguirre on 2017-05-27

Cleanup #pragmas and unneeded repaints when resizing.

396. By Alberto Aguirre on 2017-04-06

Avoid using mir_window_get_parameters, it will be deprecated

395. By Alberto Aguirre on 2017-04-05

Remove mir_event_type_key and mir_event_type_motion as they are deprecated.

394. By Alberto Aguirre on 2017-04-05

Use MirRenderSurface for pixmap cursors.

Creating buffer streams directly will be deprecated in mir in the near future, instead use render surfaces.

393. By Alberto Aguirre on 2017-04-05

Update resizing now that client can drive the buffer size through mir_render_surface_set_size.

392. By Alberto Aguirre on 2017-03-31

Avoid use of deprecated mir EGL related apis.

With the new mesa update, the EGLNativeDisplayType is MirConnection and the EGLNativeWindowType is a MirRenderSurface.
Ignore deprecation warnings on use of MirRenderSurface - its "deprecated" because it'll be renamed in mir 1.0.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2017-01-10 06:41:48 +0000
3+++ debian/control 2017-05-27 01:33:26 +0000
4@@ -4,14 +4,13 @@
5 Build-Depends: debhelper (>= 9),
6 libatspi2.0-dev,
7 libcontent-hub-dev (>= 0.2),
8- libegl1-mesa-dev,
9+ libegl1-mesa-dev (>= 17.0.2),
10 libfontconfig1-dev,
11 libfreetype6-dev,
12- libgles2-mesa-dev,
13+ libgles2-mesa-dev (>= 17.0.2),
14 libglib2.0-dev,
15 libinput-dev,
16- libmirclient-dev (>= 0.25.0),
17- libmirclient-debug-extension-dev,
18+ libmirclient-dev (>= 0.26.1),
19 libmtdev-dev,
20 libubuntu-application-api-dev (>= 2.9.0),
21 libudev-dev,
22
23=== modified file 'src/ubuntumirclient/qmirclientcursor.cpp'
24--- src/ubuntumirclient/qmirclientcursor.cpp 2017-03-28 17:12:13 +0000
25+++ src/ubuntumirclient/qmirclientcursor.cpp 2017-05-27 01:33:26 +0000
26@@ -138,11 +138,17 @@
27 {
28 public:
29 CursorWindowSpec(MirConnection *connection, const char *name)
30- : spec(mir_create_window_spec(connection))
31+ : CursorWindowSpec(connection)
32 {
33 mir_window_spec_set_cursor_name(spec, name);
34 }
35
36+ CursorWindowSpec(MirConnection *connection, MirRenderSurface *surface, int hotspotX, int hotspotY)
37+ : CursorWindowSpec(connection)
38+ {
39+ mir_window_spec_set_cursor_render_surface(spec, surface, hotspotX, hotspotY);
40+ }
41+
42 ~CursorWindowSpec()
43 {
44 mir_window_spec_release(spec);
45@@ -153,8 +159,60 @@
46 mir_window_apply_spec(window, spec);
47 }
48 private:
49+ CursorWindowSpec(MirConnection *connection) : spec(mir_create_window_spec(connection)) {}
50 MirWindowSpec * const spec;
51 };
52+
53+class BufferStream
54+{
55+public:
56+ BufferStream(MirRenderSurface *surface, int width, int height)
57+ : stream(mir_render_surface_get_buffer_stream(surface, width, height, mir_pixel_format_argb_8888))
58+ {
59+ }
60+
61+ void draw(QImage const& image)
62+ {
63+ MirGraphicsRegion region;
64+ const bool validRegion = mir_buffer_stream_get_graphics_region(stream, &region);
65+ if (!validRegion)
66+ throw std::runtime_error("Could not get graphics region to draw into");
67+
68+ auto regionLine = region.vaddr;
69+ Q_ASSERT(image.bytesPerLine() <= region.stride);
70+
71+ for (int i = 0; i < image.height(); ++i) {
72+ memcpy(regionLine, image.scanLine(i), image.bytesPerLine());
73+ regionLine += region.stride;
74+ }
75+ mir_buffer_stream_swap_buffers_sync(stream);
76+ }
77+
78+private:
79+ MirBufferStream * const stream;
80+};
81+
82+class RenderSurface
83+{
84+public:
85+ RenderSurface(MirConnection *connection, int width, int height)
86+ : surface(mir_connection_create_render_surface_sync(connection, width, height)),
87+ stream(surface, width, height)
88+ {
89+ if (!mir_render_surface_is_valid(surface)) {
90+ throw std::runtime_error(mir_render_surface_get_error_message(surface));
91+ }
92+ }
93+
94+ ~RenderSurface() { mir_render_surface_release(surface); }
95+ operator MirRenderSurface *() const { return surface; }
96+ void draw(QImage const& image) { stream.draw(image); }
97+
98+private:
99+ MirRenderSurface * const surface;
100+ BufferStream stream;
101+};
102+
103 } // anonymous namespace
104
105 void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window)
106@@ -196,30 +254,15 @@
107 image = image.convertToFormat(QImage::Format_ARGB32);
108 }
109
110- MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection,
111- image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software);
112-
113- {
114- MirGraphicsRegion region;
115- mir_buffer_stream_get_graphics_region(bufferStream, &region);
116-
117- char *regionLine = region.vaddr;
118- Q_ASSERT(image.bytesPerLine() <= region.stride);
119- for (int i = 0; i < image.height(); ++i) {
120- memcpy(regionLine, image.scanLine(i), image.bytesPerLine());
121- regionLine += region.stride;
122- }
123- }
124-
125- mir_buffer_stream_swap_buffers_sync(bufferStream);
126-
127- {
128- auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y());
129- mir_window_configure_cursor(window, configuration);
130- mir_cursor_configuration_destroy(configuration);
131- }
132-
133- mir_buffer_stream_release_sync(bufferStream);
134+ try {
135+ RenderSurface surface(mConnection, image.width(), image.height());
136+ surface.draw(image);
137+
138+ CursorWindowSpec spec(mConnection, surface, cursor.hotSpot().x(), cursor.hotSpot().y());
139+ spec.apply(window);
140+ } catch(std::exception const& e) {
141+ qWarning("Error applying pixmap cursor: %s", e.what());
142+ }
143 }
144
145 void QMirClientCursor::applyDefaultCursorConfiguration(MirWindow *window)
146
147=== modified file 'src/ubuntumirclient/qmirclientinput.cpp'
148--- src/ubuntumirclient/qmirclientinput.cpp 2017-02-21 18:24:45 +0000
149+++ src/ubuntumirclient/qmirclientinput.cpp 2017-05-27 01:33:26 +0000
150@@ -232,10 +232,6 @@
151 {
152 switch (t)
153 {
154- case mir_event_type_key:
155- return "key";
156- case mir_event_type_motion:
157- return "motion";
158 case mir_event_type_window:
159 return "window";
160 case mir_event_type_resize:
161
162=== modified file 'src/ubuntumirclient/qmirclientintegration.cpp'
163--- src/ubuntumirclient/qmirclientintegration.cpp 2017-04-04 00:46:48 +0000
164+++ src/ubuntumirclient/qmirclientintegration.cpp 2017-05-27 01:33:26 +0000
165@@ -130,8 +130,7 @@
166 QSurfaceFormat::setDefaultFormat(defaultFormat);
167
168 // Initialize EGL.
169- mEglNativeDisplay = mir_connection_get_egl_native_display(mMirConnection);
170- ASSERT((mEglDisplay = eglGetDisplay(mEglNativeDisplay)) != EGL_NO_DISPLAY);
171+ ASSERT((mEglDisplay = eglGetDisplay(mMirConnection)) != EGL_NO_DISPLAY);
172 ASSERT(eglInitialize(mEglDisplay, nullptr, nullptr) == EGL_TRUE);
173
174 // Has debug mode been requsted, either with "-testability" switch or QT_LOAD_TESTABILITY env var
175
176=== modified file 'src/ubuntumirclient/qmirclientintegration.h'
177--- src/ubuntumirclient/qmirclientintegration.h 2017-03-15 09:21:47 +0000
178+++ src/ubuntumirclient/qmirclientintegration.h 2017-05-27 01:33:26 +0000
179@@ -89,7 +89,7 @@
180 // New methods.
181 MirConnection *mirConnection() const { return mMirConnection; }
182 EGLDisplay eglDisplay() const { return mEglDisplay; }
183- EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; }
184+ EGLNativeDisplayType eglNativeDisplay() const { return mMirConnection; }
185 QMirClientAppStateController *appStateController() const { return mAppStateController.data(); }
186 QMirClientScreenObserver *screenObserver() const { return mScreenObserver.data(); }
187 QMirClientDebugExtension *debugExtension() const { return mDebugExtension.data(); }
188@@ -125,7 +125,6 @@
189
190 // EGL related
191 EGLDisplay mEglDisplay{EGL_NO_DISPLAY};
192- EGLNativeDisplayType mEglNativeDisplay;
193 };
194
195 #endif // QMIRCLIENTINTEGRATION_H
196
197=== modified file 'src/ubuntumirclient/qmirclientwindow.cpp'
198--- src/ubuntumirclient/qmirclientwindow.cpp 2017-03-28 17:12:13 +0000
199+++ src/ubuntumirclient/qmirclientwindow.cpp 2017-05-27 01:33:26 +0000
200@@ -75,12 +75,6 @@
201
202 using Spec = std::unique_ptr<MirWindowSpec, MirSpecDeleter>;
203
204-EGLNativeWindowType nativeWindowFor(MirWindow *surf)
205-{
206- auto stream = mir_window_get_buffer_stream(surf);
207- return reinterpret_cast<EGLNativeWindowType>(mir_buffer_stream_get_egl_native_window(stream));
208-}
209-
210 const char *qtWindowStateToStr(Qt::WindowState state)
211 {
212 switch (state) {
213@@ -114,24 +108,6 @@
214 Q_UNREACHABLE();
215 }
216
217-const char *mirPixelFormatToStr(MirPixelFormat pixelFormat)
218-{
219- switch (pixelFormat) {
220- case mir_pixel_format_invalid: return "invalid";
221- case mir_pixel_format_abgr_8888: return "ABGR8888";
222- case mir_pixel_format_xbgr_8888: return "XBGR8888";
223- case mir_pixel_format_argb_8888: return "ARGB8888";
224- case mir_pixel_format_xrgb_8888: return "XRGB8888";
225- case mir_pixel_format_bgr_888: return "BGR888";
226- case mir_pixel_format_rgb_888: return "RGB888";
227- case mir_pixel_format_rgb_565: return "RGB565";
228- case mir_pixel_format_rgba_5551: return "RGBA5551";
229- case mir_pixel_format_rgba_4444: return "RGBA4444";
230- case mir_pixel_formats: Q_UNREACHABLE();
231- }
232- Q_UNREACHABLE();
233-}
234-
235 const char *mirWindowTypeToStr(MirWindowType type)
236 {
237 switch (type) {
238@@ -221,12 +197,23 @@
239 return requiresParent(qtWindowTypeToMirWindowType(type));
240 }
241
242-Spec makeSurfaceSpec(QWindow *window, MirPixelFormat pixelFormat, QMirClientWindow *parentWindowHandle,
243- MirConnection *connection)
244-{
245- const auto geometry = window->geometry();
246- const int width = geometry.width() > 0 ? geometry.width() : 1;
247- const int height = geometry.height() > 0 ? geometry.height() : 1;
248+QRect geometryFor(QWindow *window)
249+{
250+ auto geometry = window->geometry();
251+ if (geometry.width() < 1)
252+ geometry.setWidth(1);
253+ if (geometry.height() < 1)
254+ geometry.setHeight(1);
255+
256+ return geometry;
257+}
258+
259+Spec makeWindowSpec(QWindow *window, QMirClientWindow *parentWindowHandle,
260+ MirRenderSurface *surface, MirConnection *connection)
261+{
262+ const auto geometry = geometryFor(window);
263+ const int width = geometry.width();
264+ const int height = geometry.height();
265 auto type = qtWindowTypeToMirWindowType(window->type());
266
267 MirRectangle location{geometry.x(), geometry.y(), 0, 0};
268@@ -272,7 +259,6 @@
269 // There's no helper function for satellite windows. Guess they're not very popular
270 spec = Spec{mir_create_window_spec(connection)};
271 mir_window_spec_set_type(spec.get(), mir_window_type_satellite);
272- mir_window_spec_set_buffer_usage(spec.get(), mir_buffer_usage_hardware);
273 mir_window_spec_set_parent(spec.get(), parent);
274 mir_window_spec_set_width(spec.get(), width);
275 mir_window_spec_set_height(spec.get(), height);
276@@ -282,9 +268,9 @@
277 break;
278 }
279
280- mir_window_spec_set_pixel_format(spec.get(), pixelFormat);
281+ mir_window_spec_add_render_surface(spec.get(), surface, width, height, 0, 0);
282
283- qCDebug(mirclient, "makeSurfaceSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)",
284+ qCDebug(mirclient, "makeWindowSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)",
285 window, mirWindowTypeToStr(type), window->type(), location.left, location.top, width, height);
286
287 return spec;
288@@ -331,14 +317,29 @@
289 mir_window_spec_set_input_shape(spec, rects, count);
290 }
291
292+MirRenderSurface *createMirSurface(QWindow *window, MirConnection *connection)
293+{
294+ const auto geometry = geometryFor(window);
295+ const int width = geometry.width();
296+ const int height = geometry.height();
297+
298+ auto surface = mir_connection_create_render_surface_sync(connection, width, height);
299+ if (!mir_render_surface_is_valid(surface))
300+ {
301+ auto errorMsg = mir_render_surface_get_error_message(surface);
302+ qFatal("Failed to create mir surface: %s", errorMsg);
303+ }
304+ return surface;
305+}
306+
307 MirWindow *createMirWindow(QWindow *window, int mirOutputId, QMirClientWindow *parentWindowHandle,
308- MirPixelFormat pixelFormat, MirConnection *connection,
309- MirWindowEventCallback inputCallback, void *inputContext)
310+ MirRenderSurface *surface, MirConnection *connection,
311+ MirWindowEventCallback eventCallback, void *context)
312 {
313- auto spec = makeSurfaceSpec(window, pixelFormat, parentWindowHandle, connection);
314+ auto spec = makeWindowSpec(window, parentWindowHandle, surface, connection);
315
316 // Install event handler as early as possible
317- mir_window_spec_set_event_handler(spec.get(), inputCallback, inputContext);
318+ mir_window_spec_set_event_handler(spec.get(), eventCallback, context);
319
320 const auto title = window->title().toUtf8();
321 mir_window_spec_set_name(spec.get(), title.constData());
322@@ -358,9 +359,14 @@
323 mir_window_spec_set_state(spec.get(), mir_window_state_hidden);
324 }
325
326- auto surface = mir_create_window_sync(spec.get());
327- Q_ASSERT(mir_window_is_valid(surface));
328- return surface;
329+ auto mirWindow = mir_create_window_sync(spec.get());
330+ if (!mir_window_is_valid(mirWindow))
331+ {
332+ auto errorMsg = mir_window_get_error_message(mirWindow);
333+ qFatal("Failed to create mir window: %s", errorMsg);
334+ }
335+
336+ return mirWindow;
337 }
338
339 QMirClientWindow *getParentIfNecessary(QWindow *window, QMirClientInput *input)
340@@ -377,18 +383,6 @@
341 return parentWindowHandle;
342 }
343
344-MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat)
345-{
346- switch (pixelFormat) {
347- case mir_pixel_format_abgr_8888:
348- return mir_pixel_format_xbgr_8888;
349- case mir_pixel_format_argb_8888:
350- return mir_pixel_format_xrgb_8888;
351- default: // can do nothing, leave it alone
352- return pixelFormat;
353- }
354-}
355-
356 // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633
357 // we need to guess the panel height (3GU)
358 int panelHeight()
359@@ -426,7 +420,6 @@
360
361 void onSwapBuffersDone();
362 void handleSurfaceResized(int width, int height);
363- int needsRepaint() const;
364
365 MirWindowState state() const { return mir_window_get_state(mMirWindow); }
366 void setState(MirWindowState state);
367@@ -448,7 +441,7 @@
368 QString persistentSurfaceId();
369
370 private:
371- static void surfaceEventCallback(MirWindow* surface, const MirEvent *event, void* context);
372+ static void windowEventCallback(MirWindow* surface, const MirEvent *event, void* context);
373 void postEvent(const MirEvent *event);
374
375 QWindow * const mWindow;
376@@ -458,14 +451,12 @@
377 QMirClientWindow * mParentWindowHandle{nullptr};
378
379 MirWindow* mMirWindow;
380+ MirRenderSurface* mMirSurface;
381 const EGLDisplay mEglDisplay;
382 EGLSurface mEglSurface;
383
384- bool mNeedsRepaint;
385 bool mParented;
386- QSize mBufferSize;
387 QSurfaceFormat mFormat;
388- MirPixelFormat mPixelFormat;
389
390 QMutex mTargetSizeMutex;
391 QSize mTargetSize;
392@@ -479,7 +470,6 @@
393 , mInput(input)
394 , mConnection(connection)
395 , mEglDisplay(display)
396- , mNeedsRepaint(false)
397 , mParented(mWindow->transientParent() || mWindow->parent())
398 , mFormat(mWindow->requestedFormat())
399 , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal)
400@@ -506,50 +496,33 @@
401
402 mFormat = q_glFormatFromConfig(display, config, mFormat);
403
404- // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way
405- // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers.
406- mPixelFormat = mir_connection_get_egl_pixel_format(connection, display, config);
407- // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client.
408- // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer.
409- // This is an optimization for the compositor, as it can avoid blending this surface.
410- if (mWindow->requestedFormat().alphaBufferSize() < 0) {
411- mPixelFormat = disableAlphaBufferIfPossible(mPixelFormat);
412- }
413-
414 const auto outputId = static_cast<QMirClientScreen *>(mWindow->screen()->handle())->mirOutputId();
415
416 mParentWindowHandle = getParentIfNecessary(mWindow, input);
417
418- mMirWindow = createMirWindow(mWindow, outputId, mParentWindowHandle, mPixelFormat, connection, surfaceEventCallback, this);
419- mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirWindow), nullptr);
420+ mMirSurface = createMirSurface(mWindow, connection);
421+ mMirWindow = createMirWindow(mWindow, outputId, mParentWindowHandle, mMirSurface, connection, windowEventCallback, this);
422+ mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast<EGLNativeWindowType>(mMirSurface), nullptr);
423
424 mNeedsExposeCatchup = mir_window_get_visibility(mMirWindow) == mir_window_visibility_occluded;
425
426- // Window manager can give us a final size different from what we asked for
427- // so let's check what we ended up getting
428- MirWindowParameters parameters;
429- mir_window_get_parameters(mMirWindow, &parameters);
430-
431+ // Assume that the buffer size matches the surface size at creation time
432 auto geom = mWindow->geometry();
433- geom.setWidth(parameters.width);
434- geom.setHeight(parameters.height);
435-
436- // Assume that the buffer size matches the surface size at creation time
437- mBufferSize = geom.size();
438- platformWindow->QPlatformWindow::setGeometry(geom);
439- QWindowSystemInterface::handleGeometryChange(mWindow, geom);
440
441 qCDebug(mirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title();
442 qCDebug(mirclientGraphics)
443 << "Requested format:" << mWindow->requestedFormat()
444- << "\nActual format:" << mFormat
445- << "with associated Mir pixel format:" << mirPixelFormatToStr(mPixelFormat);
446+ << "\nActual format:" << mFormat;
447 }
448
449 UbuntuSurface::~UbuntuSurface()
450 {
451- if (mEglSurface != EGL_NO_SURFACE)
452+ if (mEglSurface != EGL_NO_SURFACE) {
453 eglDestroySurface(mEglDisplay, mEglSurface);
454+ }
455+ if (mMirSurface) {
456+ mir_render_surface_release(mMirSurface);
457+ }
458 if (mMirWindow) {
459 mir_window_release_sync(mMirWindow);
460 }
461@@ -606,30 +579,23 @@
462 {
463 QMutexLocker lock(&mTargetSizeMutex);
464
465- // mir's resize event is mainly a signal that we need to redraw our content. We use the
466- // width/height as identifiers to figure out if this is the latest surface resize event
467- // that has posted, discarding any old ones. This avoids issuing too many redraw events.
468- // see TODO in postEvent as the ideal way we should handle this.
469- // The actual buffer size may or may have not changed at this point, so let the rendering
470- // thread drive the window geometry updates.
471- mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height;
472-}
473-
474-int UbuntuSurface::needsRepaint() const
475-{
476- if (mNeedsRepaint) {
477- if (mTargetSize != mBufferSize) {
478- //If the buffer hasn't changed yet, we need at least two redraws,
479- //once to get the new buffer size and propagate the geometry changes
480- //and the second to redraw the content at the new size
481- return 2;
482- } else {
483- // The buffer size has already been updated so we only need one redraw
484- // to render at the new size
485- return 1;
486- }
487+ // There could have been a flurry of resize events, only process the latest event
488+ const bool needsResize = mTargetSize.width() == width && mTargetSize.height() == height;
489+ if (needsResize) {
490+ // Resize the buffers
491+ mir_render_surface_set_size(mMirSurface, width, height);
492+
493+ //Resize the window
494+ Spec spec{mir_create_window_spec(mConnection)};
495+ mir_window_spec_add_render_surface(spec.get(), mMirSurface, width, height, 0, 0);
496+ mir_window_apply_spec(mMirWindow, spec.get());
497+
498+ QRect newGeometry = mPlatformWindow->geometry();
499+ newGeometry.setSize(mTargetSize);
500+
501+ mPlatformWindow->QPlatformWindow::setGeometry(newGeometry);
502+ QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
503 }
504- return 0;
505 }
506
507 void UbuntuSurface::setState(MirWindowState state)
508@@ -653,35 +619,13 @@
509 static int sFrameNumber = 0;
510 ++sFrameNumber;
511
512- EGLint eglSurfaceWidth = -1;
513- EGLint eglSurfaceHeight = -1;
514- eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth);
515- eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight);
516-
517- const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0;
518-
519- if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) {
520-
521- qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)",
522- mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight);
523-
524- mBufferSize.rwidth() = eglSurfaceWidth;
525- mBufferSize.rheight() = eglSurfaceHeight;
526-
527- QRect newGeometry = mPlatformWindow->geometry();
528- newGeometry.setSize(mBufferSize);
529-
530- mPlatformWindow->QPlatformWindow::setGeometry(newGeometry);
531- QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
532- } else {
533- qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)",
534- mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height());
535- }
536+ qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d]",
537+ mWindow, sFrameNumber);
538 }
539
540-void UbuntuSurface::surfaceEventCallback(MirWindow *surface, const MirEvent *event, void* context)
541+void UbuntuSurface::windowEventCallback(MirWindow *window, const MirEvent *event, void* context)
542 {
543- Q_UNUSED(surface);
544+ Q_UNUSED(window);
545 Q_ASSERT(context != nullptr);
546
547 auto s = static_cast<UbuntuSurface *>(context);
548@@ -692,9 +636,8 @@
549 {
550 const auto eventType = mir_event_get_type(event);
551 if (mir_event_type_resize == eventType) {
552- // TODO: The current event queue just accumulates all resize events;
553- // It would be nicer if we could update just one event if that event has not been dispatched.
554- // As a workaround, we use the width/height as an identifier of this latest event
555+ // The event queue just accumulates all resize events;
556+ // Use the width and height as an identifier of this latest event
557 // so the event handler (handleSurfaceResized) can discard/ignore old ones.
558 const auto resizeEvent = mir_event_get_resize_event(event);
559 const auto width = mir_resize_event_get_width(resizeEvent);
560@@ -786,19 +729,6 @@
561 qCDebug(mirclient, "handleSurfaceResize(window=%p, size=(%dx%d)px", window(), width, height);
562
563 mSurface->handleSurfaceResized(width, height);
564-
565- // This resize event could have occurred just after the last buffer swap for this window.
566- // This means the client may still be holding a buffer with the older size. The first redraw call
567- // will then render at the old size. After swapping the client now will get a new buffer with the
568- // updated size but it still needs re-rendering so another redraw may be needed.
569- // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice
570- auto const numRepaints = mSurface->needsRepaint();
571- lock.unlock();
572- qCDebug(mirclient, "handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints);
573- for (int i = 0; i < numRepaints; i++) {
574- qCDebug(mirclient, "handleSurfaceResize(window=%p) repainting size=(%dx%d)dp", window(), geometry().size().width(), geometry().size().height());
575- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size()));
576- }
577 }
578
579 void QMirClientWindow::handleSurfaceExposeChange(bool exposed)
580
581=== modified file 'src/ubuntumirclient/ubuntumirclient.pro'
582--- src/ubuntumirclient/ubuntumirclient.pro 2017-03-29 13:39:50 +0000
583+++ src/ubuntumirclient/ubuntumirclient.pro 2017-05-27 01:33:26 +0000
584@@ -6,7 +6,7 @@
585
586 CONFIG += plugin no_keywords qpa/genericunixfontdatabase
587
588-DEFINES += MESA_EGL_NO_X11_HEADERS
589+DEFINES += MESA_EGL_NO_X11_HEADERS MIR_DEPRECATE_RENDERSURFACES=0 MIR_ENABLE_DEPRECATIONS=0
590 # CONFIG += c++11 # only enables C++0x
591 QMAKE_CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden -std=c++11 -Werror -Wall
592 QMAKE_LFLAGS += -std=c++11 -Wl,-no-undefined

Subscribers

People subscribed via source and target branches