Mir

Merge lp:~raof/mir/fix-drm-buffer-multiple-attach into lp:mir

Proposed by Chris Halse Rogers
Status: Merged
Approved by: Gerry Boland
Approved revision: no longer in the source branch.
Merged at revision: 4261
Proposed branch: lp:~raof/mir/fix-drm-buffer-multiple-attach
Merge into: lp:mir
Diff against target: 224 lines (+82/-56)
3 files modified
include/platform/mir/graphics/wayland_allocator.h (+1/-1)
src/platforms/mesa/server/buffer_allocator.cpp (+80/-54)
src/platforms/mesa/server/buffer_allocator.h (+1/-1)
To merge this branch: bzr merge lp:~raof/mir/fix-drm-buffer-multiple-attach
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Gerry Boland (community) Approve
Alan Griffiths Approve
Review via email: mp+331123@code.launchpad.net

Commit message

mgm::BufferAllocator: Handle a wl_buffer being attached multiple times.

As with the WlShmBuffer, it's valid for a wl_buffer to be wl_surface.attach()ed to multiple wl_surface-s at the same time. If a buffer is attached twice then the buffer.release() event needs to be sent exactly once, when the compositor is finished with *all* submissions.

So, do what we do with WlShmBuffer - associate a shared_ptr<WaylandBuffer> with each wl_buffer, and hand out references to it rather than creating a new WaylandBuffer on each (committed) attach().

To post a comment you must log in.
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Nice

review: Approve
Revision history for this message
Gerry Boland (gerboland) wrote :

lgtm

review: Approve
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:4258
https://mir-jenkins.ubuntu.com/job/mir-ci/3674/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/5033/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/5269
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/5257
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/5257
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/5257
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/5076/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5076
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/5076/artifact/output/*zip*/output.zip
    ABORTED: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/5076/console
    ABORTED: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/5076/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5076
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/5076/artifact/output/*zip*/output.zip
    ABORTED: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/5076/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5076
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/5076/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://mir-jenkins.ubuntu.com/job/mir-ci/3674/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Mir CI Bot (mir-ci-bot) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/platform/mir/graphics/wayland_allocator.h'
--- include/platform/mir/graphics/wayland_allocator.h 2017-09-01 07:00:55 +0000
+++ include/platform/mir/graphics/wayland_allocator.h 2017-09-21 08:03:22 +0000
@@ -37,7 +37,7 @@
37 virtual ~WaylandAllocator() = default;37 virtual ~WaylandAllocator() = default;
3838
39 virtual void bind_display(wl_display* display) = 0;39 virtual void bind_display(wl_display* display) = 0;
40 virtual std::unique_ptr<Buffer> buffer_from_resource (wl_resource* buffer, std::function<void ()>&& on_consumed) = 0;40 virtual std::shared_ptr<Buffer> buffer_from_resource (wl_resource* buffer, std::function<void ()>&& on_consumed) = 0;
41};41};
42}42}
43}43}
4444
=== modified file 'src/platforms/mesa/server/buffer_allocator.cpp'
--- src/platforms/mesa/server/buffer_allocator.cpp 2017-09-01 07:00:55 +0000
+++ src/platforms/mesa/server/buffer_allocator.cpp 2017-09-21 08:03:22 +0000
@@ -332,66 +332,54 @@
332 public mir::renderer::gl::TextureSource332 public mir::renderer::gl::TextureSource
333{333{
334public:334public:
335 WaylandBuffer(335 static std::shared_ptr<mg::Buffer> mir_buffer_from_wl_buffer(
336 EGLDisplay dpy,336 EGLDisplay dpy,
337 wl_resource* buffer,337 wl_resource* buffer,
338 std::shared_ptr<mg::EGLExtensions> const& extensions,338 std::shared_ptr<mg::EGLExtensions> const& extensions,
339 std::function<void()>&& on_consumed)339 std::function<void()>&& on_consumed)
340 : buffer{buffer},
341 dpy{dpy},
342 egl_image{EGL_NO_IMAGE_KHR},
343 extensions{extensions},
344 on_consumed{std::move(on_consumed)}
345 {340 {
341 std::shared_ptr<WaylandBuffer> mir_buffer;
342 DestructionShim* shim;
343
346 if (auto notifier = wl_resource_get_destroy_listener(buffer, &on_buffer_destroyed))344 if (auto notifier = wl_resource_get_destroy_listener(buffer, &on_buffer_destroyed))
347 {345 {
348 DestructionShim* shim;346 // We've already constructed a shim for this buffer, update it.
349
350 shim = wl_container_of(notifier, shim, destruction_listener);347 shim = wl_container_of(notifier, shim, destruction_listener);
351348
352 if (shim->associated_buffer)349 if (!(mir_buffer = shim->associated_buffer.lock()))
353 BOOST_THROW_EXCEPTION(std::logic_error("Attempt to associate a single wl_buffer with multiple WaylandBuffer wrappers"));350 {
354351 /*
355 shim->associated_buffer = this;352 * We've seen this wl_buffer before, but all the WaylandBuffers associated with it
356 buffer_mutex = shim->mutex;353 * have been destroyed.
354 *
355 * Recreate a new WaylandBuffer to track the new compositor lifetime.
356 */
357 mir_buffer = std::shared_ptr<WaylandBuffer>{
358 new WaylandBuffer{
359 dpy,
360 buffer,
361 extensions,
362 std::move(on_consumed)}};
363 shim->associated_buffer = mir_buffer;
364 }
357 }365 }
358 else366 else
359 {367 {
360 auto shim = new DestructionShim;368 mir_buffer = std::shared_ptr<WaylandBuffer>{
369 new WaylandBuffer{
370 dpy,
371 buffer,
372 extensions,
373 std::move(on_consumed)}};
374 shim = new DestructionShim;
361 shim->destruction_listener.notify = &on_buffer_destroyed;375 shim->destruction_listener.notify = &on_buffer_destroyed;
362 shim->associated_buffer = this;376 shim->associated_buffer = mir_buffer;
363 buffer_mutex = shim->mutex;
364377
365 wl_resource_add_destroy_listener(buffer, &shim->destruction_listener);378 wl_resource_add_destroy_listener(buffer, &shim->destruction_listener);
366 }379 }
367380
368 if (extensions->wayland->eglQueryWaylandBufferWL(dpy, buffer, EGL_WIDTH, &width) == EGL_FALSE)381 mir_buffer->buffer_mutex = shim->mutex;
369 {382 return mir_buffer;
370 BOOST_THROW_EXCEPTION(mg::egl_error("Failed to query WaylandAllocator buffer width"));
371 }
372 if (extensions->wayland->eglQueryWaylandBufferWL(dpy, buffer, EGL_HEIGHT, &height) == EGL_FALSE)
373 {
374 BOOST_THROW_EXCEPTION(mg::egl_error("Failed to query WaylandAllocator buffer height"));
375 }
376
377 EGLint texture_format;
378 if (!extensions->wayland->eglQueryWaylandBufferWL(dpy, buffer, EGL_TEXTURE_FORMAT, &texture_format))
379 {
380 BOOST_THROW_EXCEPTION(mg::egl_error("Failed to query WL buffer format"));
381 }
382
383 if (texture_format == EGL_TEXTURE_RGB)
384 {
385 format = mir_pixel_format_xrgb_8888;
386 }
387 else if (texture_format == EGL_TEXTURE_RGBA)
388 {
389 format = mir_pixel_format_argb_8888;
390 }
391 else
392 {
393 BOOST_THROW_EXCEPTION((std::invalid_argument{"YUV buffers are unimplemented"}));
394 }
395 }383 }
396384
397 ~WaylandBuffer()385 ~WaylandBuffer()
@@ -403,12 +391,6 @@
403 if (buffer)391 if (buffer)
404 {392 {
405 wl_resource_queue_event(buffer, WL_BUFFER_RELEASE);393 wl_resource_queue_event(buffer, WL_BUFFER_RELEASE);
406 auto notifier = wl_resource_get_destroy_listener(buffer, &on_buffer_destroyed);
407 DestructionShim* shim;
408
409 shim = wl_container_of(notifier, shim, destruction_listener);
410
411 shim->associated_buffer = nullptr;
412 }394 }
413 }395 }
414396
@@ -477,6 +459,46 @@
477 }459 }
478460
479private:461private:
462 WaylandBuffer(
463 EGLDisplay dpy,
464 wl_resource* buffer,
465 std::shared_ptr<mg::EGLExtensions> const& extensions,
466 std::function<void()>&& on_consumed)
467 : buffer{buffer},
468 dpy{dpy},
469 egl_image{EGL_NO_IMAGE_KHR},
470 extensions{extensions},
471 on_consumed{std::move(on_consumed)}
472 {
473 if (extensions->wayland->eglQueryWaylandBufferWL(dpy, buffer, EGL_WIDTH, &width) == EGL_FALSE)
474 {
475 BOOST_THROW_EXCEPTION(mg::egl_error("Failed to query WaylandAllocator buffer width"));
476 }
477 if (extensions->wayland->eglQueryWaylandBufferWL(dpy, buffer, EGL_HEIGHT, &height) == EGL_FALSE)
478 {
479 BOOST_THROW_EXCEPTION(mg::egl_error("Failed to query WaylandAllocator buffer height"));
480 }
481
482 EGLint texture_format;
483 if (!extensions->wayland->eglQueryWaylandBufferWL(dpy, buffer, EGL_TEXTURE_FORMAT, &texture_format))
484 {
485 BOOST_THROW_EXCEPTION(mg::egl_error("Failed to query WL buffer format"));
486 }
487
488 if (texture_format == EGL_TEXTURE_RGB)
489 {
490 format = mir_pixel_format_xrgb_8888;
491 }
492 else if (texture_format == EGL_TEXTURE_RGBA)
493 {
494 format = mir_pixel_format_argb_8888;
495 }
496 else
497 {
498 BOOST_THROW_EXCEPTION((std::invalid_argument{"YUV buffers are unimplemented"}));
499 }
500 }
501
480 static void on_buffer_destroyed(wl_listener* listener, void*)502 static void on_buffer_destroyed(wl_listener* listener, void*)
481 {503 {
482 static_assert(504 static_assert(
@@ -488,9 +510,9 @@
488510
489 {511 {
490 std::lock_guard<std::mutex> lock{*shim->mutex};512 std::lock_guard<std::mutex> lock{*shim->mutex};
491 if (shim->associated_buffer)513 if (auto mir_buffer = shim->associated_buffer.lock())
492 {514 {
493 shim->associated_buffer->buffer = nullptr;515 mir_buffer->buffer = nullptr;
494 }516 }
495 }517 }
496518
@@ -500,7 +522,7 @@
500 struct DestructionShim522 struct DestructionShim
501 {523 {
502 std::shared_ptr<std::mutex> const mutex = std::make_shared<std::mutex>();524 std::shared_ptr<std::mutex> const mutex = std::make_shared<std::mutex>();
503 WaylandBuffer* associated_buffer;525 std::weak_ptr<WaylandBuffer> associated_buffer;
504 wl_listener destruction_listener;526 wl_listener destruction_listener;
505 };527 };
506528
@@ -542,9 +564,13 @@
542 }564 }
543}565}
544566
545std::unique_ptr<mg::Buffer> mgm::BufferAllocator::buffer_from_resource (wl_resource* buffer, std::function<void ()>&& on_consumed)567std::shared_ptr<mg::Buffer> mgm::BufferAllocator::buffer_from_resource (wl_resource* buffer, std::function<void ()>&& on_consumed)
546{568{
547 if (egl_extensions->wayland)569 if (egl_extensions->wayland)
548 return std::make_unique<WaylandBuffer>(dpy, buffer, egl_extensions, std::move(on_consumed));570 return WaylandBuffer::mir_buffer_from_wl_buffer(
571 dpy,
572 buffer,
573 egl_extensions,
574 std::move(on_consumed));
549 return nullptr;575 return nullptr;
550}576}
551577
=== modified file 'src/platforms/mesa/server/buffer_allocator.h'
--- src/platforms/mesa/server/buffer_allocator.h 2017-08-31 07:40:41 +0000
+++ src/platforms/mesa/server/buffer_allocator.h 2017-09-21 08:03:22 +0000
@@ -63,7 +63,7 @@
63 std::vector<MirPixelFormat> supported_pixel_formats() override;63 std::vector<MirPixelFormat> supported_pixel_formats() override;
6464
65 void bind_display(wl_display* display) override;65 void bind_display(wl_display* display) override;
66 std::unique_ptr<Buffer> buffer_from_resource (wl_resource* buffer, std::function<void ()>&& on_consumed) override;66 std::shared_ptr<Buffer> buffer_from_resource (wl_resource* buffer, std::function<void ()>&& on_consumed) override;
67private:67private:
68 std::shared_ptr<Buffer> alloc_hardware_buffer(68 std::shared_ptr<Buffer> alloc_hardware_buffer(
69 graphics::BufferProperties const& buffer_properties);69 graphics::BufferProperties const& buffer_properties);

Subscribers

People subscribed via source and target branches