Mir

Merge lp:~kdub/mir/nested-passthrough into lp:mir

Proposed by Kevin DuBois on 2016-09-30
Status: Merged
Approved by: Daniel van Vugt on 2016-10-10
Approved revision: 3741
Merged at revision: 3746
Proposed branch: lp:~kdub/mir/nested-passthrough
Merge into: lp:mir
Prerequisite: lp:~kdub/mir/nested-passthrough-logic
Diff against target: 918 lines (+376/-43)
27 files modified
include/test/mir_test_framework/any_surface.h (+3/-1)
include/test/mir_test_framework/headless_display_buffer_compositor_factory.h (+5/-0)
include/test/mir_test_framework/headless_nested_server_runner.h (+12/-0)
src/client/atomic_callback.h (+3/-3)
src/client/mir_buffer_api.cpp (+2/-0)
src/server/compositor/buffer_map.cpp (+8/-4)
src/server/compositor/buffer_map.h (+3/-1)
src/server/graphics/nested/buffer.cpp (+1/-1)
src/server/graphics/nested/host_connection.h (+1/-0)
src/server/graphics/nested/host_surface_spec.h (+2/-0)
src/server/graphics/nested/ipc_operations.h (+2/-2)
src/server/graphics/nested/mir_client_host_connection.cpp (+192/-5)
src/server/graphics/nested/mir_client_host_connection.h (+1/-0)
src/server/graphics/nested/native_buffer.h (+0/-1)
src/server/graphics/nested/platform.cpp (+52/-2)
tests/acceptance-tests/test_nested_mir.cpp (+17/-0)
tests/include/mir/test/doubles/stub_client_buffer.h (+6/-1)
tests/include/mir/test/doubles/stub_host_connection.h (+5/-0)
tests/integration-tests/test_buffer_scheduling.cpp (+3/-3)
tests/mir_test_framework/any_surface.cpp (+7/-1)
tests/mir_test_framework/headless_display_buffer_compositor_factory.cpp (+22/-2)
tests/mir_test_framework/headless_nested_server_runner.cpp (+17/-3)
tests/mir_test_framework/headless_test.cpp (+1/-1)
tests/unit-tests/compositor/test_client_buffers.cpp (+10/-10)
tests/unit-tests/platforms/nested/test_buffer.cpp (+1/-0)
tests/unit-tests/platforms/nested/test_ipc_operations.cpp (+0/-1)
tests/unit-tests/platforms/nested/test_nested_display_buffer.cpp (+0/-1)
To merge this branch: bzr merge lp:~kdub/mir/nested-passthrough
Reviewer Review Type Date Requested Status
Daniel van Vugt 2016-09-30 Approve on 2016-10-10
Cemil Azizoglu (community) Approve on 2016-10-07
Mir CI Bot continuous-integration Approve on 2016-10-06
Review via email: mp+307315@code.launchpad.net

Commit message

nested: optimize fullscreen client surfaces by passing their buffers through the nested server to the host server without composing.
(LP: #1262116)

Description of the change

nested: optimize fullscreen client surfaces by passing their buffers through the nested server to the host server without composing. Currently only enabled for android. EGLStreams does this under-the hood, and mesa enablement is up for review: lp:~kdub/mir/mesa-clientbuffer-eglimage-mapping

Also working on measurements (needs some more reporting changes)

To post a comment you must log in.
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3732
https://mir-jenkins.ubuntu.com/job/mir-ci/1862/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2357/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2420/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2412/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2412/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2412/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2386/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2386/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2386/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2386/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2386/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2386/console

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

review: Needs Fixing (continuous-integration)
lp:~kdub/mir/nested-passthrough updated on 2016-09-30
3733. By Kevin DuBois on 2016-09-30

merge in mir

Kevin DuBois (kdub) wrote :

grr, merge madness

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3733
https://mir-jenkins.ubuntu.com/job/mir-ci/1863/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2358/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2421
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2413
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2413
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2413
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2387/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2387/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2387/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2387/console
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2387/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2387
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2387/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2387/console

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

review: Needs Fixing (continuous-integration)
lp:~kdub/mir/nested-passthrough updated on 2016-09-30
3734. By Kevin DuBois on 2016-09-30

cleanups

3735. By Kevin DuBois on 2016-09-30

merge in base branch, fix 3 conflicts

3736. By Kevin DuBois on 2016-09-30

make the stub platform detect passthrough mapping enabled

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3736
https://mir-jenkins.ubuntu.com/job/mir-ci/1865/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2360/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2423
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2415
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2415
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2415
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2389/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2389/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2389/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2389
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2389/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2389
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2389/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2389/console

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

review: Needs Fixing (continuous-integration)
lp:~kdub/mir/nested-passthrough updated on 2016-09-30
3737. By Kevin DuBois on 2016-09-30

fix up complaint about inconsistent overrides

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3737
https://mir-jenkins.ubuntu.com/job/mir-ci/1866/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2362/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2425
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2417
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2417
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2417
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2391/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2391/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2391/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2391/console
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2391/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2391
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2391/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2391/console

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

review: Needs Fixing (continuous-integration)
Kevin DuBois (kdub) wrote :
lp:~kdub/mir/nested-passthrough updated on 2016-10-04
3738. By Kevin DuBois on 2016-10-04

merge in mir

Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3738
https://mir-jenkins.ubuntu.com/job/mir-ci/1884/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2388/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2451
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2443
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2443
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2443
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2417
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2417/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2417/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2417/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2417
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2417/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2417
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2417/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2417/console

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

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote :

FAILED: Continuous integration, rev:3738
https://mir-jenkins.ubuntu.com/job/mir-ci/1886/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/2390/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2453
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2445
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2445
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2445
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2419
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2419/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2419/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2419/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2419
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2419/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2419
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2419/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2419/console

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

review: Needs Fixing (continuous-integration)
Kevin DuBois (kdub) wrote :

hmm, seems different than the logged bug, investigating further

Daniel van Vugt (vanvugt) wrote :

For the measurements, we can measure latency externally using mirvanity. Although I suspect we don't expect any reduction in latency here(?).

I think CPU and GPU load is also something we aim to reduce but bug 1540207 suggests that we won't see that on desktop. So maybe try looking at CPU/GPU usage on mobile for some positive measurements.

Daniel van Vugt (vanvugt) wrote :

OK, I've just done some fresh high-speed camera testing with mirvanity. Confirmed there is no reduction in latency here. Nesting still introduces two extra frames of lag (triple buffers):

Trunk: 64ms
This branch: 64ms
Trunk (nested): 97ms
This branch (nested): 97ms

But that's OK. Latency reductions will come later with the client-side vsync work I'm doing...

Daniel van Vugt (vanvugt) wrote :

Oh. Is this relevant?

[2016-10-05 11:22:54.841327] <ERROR> mirclient: Caught exception at client library boundary (in mir_buffer_egl_image_parameters): /home/dan/bzr/mir/tmp.nested/src/platforms/mesa/client/client_buffer.cpp(175): Throw in function virtual void mir::client::mesa::ClientBuffer::egl_image_creation_parameters(EGLenum*, void**, EGLint**)
Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::invalid_argument> >
std::exception::what: not implemented yet

[2016-10-05 11:22:54.841628] <ERROR> mirclient: Caught exception at client library boundary (in mir_buffer_egl_image_parameters): /home/dan/bzr/mir/tmp.nested/src/platforms/mesa/client/client_buffer.cpp(175): Throw in function virtual void mir::client::mesa::ClientBuffer::egl_image_creation_parameters(EGLenum*, void**, EGLint**)
Dynamic exception type: boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::invalid_argument> >
std::exception::what: not implemented yet

Daniel van Vugt (vanvugt) :
review: Needs Information
Daniel van Vugt (vanvugt) wrote :

Looks like that exception is fixed in:
lp:~kdub/mir/mesa-clientbuffer-eglimage-mapping

Daniel van Vugt (vanvugt) :
review: Abstain
Daniel van Vugt (vanvugt) wrote :

Win! Merging lp:~kdub/mir/mesa-clientbuffer-eglimage-mapping with this one gets the nesting lag down from 97ms to 64ms. Thus after you combine both branches the nesting lag is eliminated!

review: Approve
Daniel van Vugt (vanvugt) wrote :

Bugger. Found a regression in fullscreen framedropping clients (mir_demo_client_egltriangle -n -f). On trunk it renders at 1200 FPS, but with this branch (and the other one) we are bound to 60 FPS, which is bad for games and other apps that rely on swap interval 0 not blocking.

Although a similar bug 1369763 has existed on android for at least two years. We should avoid breaking desktop as well.

review: Needs Fixing
Daniel van Vugt (vanvugt) wrote :

Actually fixing bug 1369763 is possibly a prerequisite for my future lower latency work. So we really need to fix it everywhere.

Daniel van Vugt (vanvugt) wrote :

Also, since this branch doesn't actually do what the label says until you combine it with lp:~kdub/mir/mesa-clientbuffer-eglimage-mapping, it might be an idea to prereq that.

Daniel van Vugt (vanvugt) wrote :

OK, a few issues, so to summarise:

(0) Please prerequisite lp:~kdub/mir/mesa-clientbuffer-eglimage-mapping to make this branch work on desktop.

(1) Needs Fixing: Framedropping pass-through clients are incorrectly bound to 60 FPS.

(2) Needs Fixing: My nested server got stuck in an infinite loop on shutdown when testing this branch, but that bug might have originated elsewhere?...

[2016-10-05 15:49:42.260127] <ERROR> Mesa/NativeSurface: Caught exception at Mir/EGL driver boundary (in advance_buffer): Dynamic exception type: std::logic_error
std::exception::what: state was not valid

[2016-10-05 15:49:42.262044] <ERROR> Mesa/NativeSurface: Caught exception at Mir/EGL driver boundary (in advance_buffer): Dynamic exception type: std::logic_error
std::exception::what: state was not valid

[2016-10-05 15:49:42.264824] <ERROR> Mesa/NativeSurface: Caught exception at Mir/EGL driver boundary (in advance_buffer): Dynamic exception type: std::logic_error
std::exception::what: state was not valid

Looks similar to bug 1630230.

review: Needs Fixing
lp:~kdub/mir/nested-passthrough updated on 2016-10-06
3739. By Kevin DuBois on 2016-10-04

increase timeout for valgrind

3740. By Kevin DuBois on 2016-10-06

correct problem with getting cb after deletion of native buffer

Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3740
https://mir-jenkins.ubuntu.com/job/mir-ci/1905/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2418
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2481
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2473
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2473
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2473
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2447
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2447/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2447
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2447/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2447
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2447/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2447
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2447/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2447
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2447/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2447
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2447/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Kevin DuBois (kdub) wrote :

with the 60fps degradation, still needs investigation. The fix pushed might have fixed the shutdown problem, and did fix CI. Still investigating a situation with the io threads and shutdown, that I've only seen in the acceptance tests, but should be fixed anyways.

lp:~kdub/mir/nested-passthrough updated on 2016-10-06
3741. By Kevin DuBois on 2016-10-06

dont hold a strong reference to the EventSender from within the compositor system. Once the IPC threads shutdown, trying to flush out any remaining buffers causes memory problems during nested compositor shutdown.

Mir CI Bot (mir-ci-bot) wrote :

PASSED: Continuous integration, rev:3741
https://mir-jenkins.ubuntu.com/job/mir-ci/1906/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/2419
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/2482
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/2474
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/2474
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=yakkety/2474
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2448
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=yakkety/2448/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2448
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/2448/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2448
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=yakkety/2448/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2448
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/2448/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2448
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/2448/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2448
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/2448/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Daniel van Vugt (vanvugt) wrote :

(0) I'm trying to solve this by landing the other branch today, before this one. That way this landing will actually be the revision in which nested passthrough also started working.

(1) I don't mind too much if this bug remains unresolved briefly. Since I started looking at how NBS does swap intervals yesterday I now realize we have a couple of other existing bugs in this area to fix already. So making that three bugs instead of two isn't a major problem. Especially if multiple bugs get resolved all at once.

(2) Can't reproduce that error now. Thanks.

Daniel van Vugt (vanvugt) wrote :

(3) Just worth noting; a pixel format with alpha may well be able to pass-through but in some cases (at least always on desktop) will be rejected by bypass:

+bool mgn::MirClientHostConnection::supports_passthrough()
467 +{
468 + auto buffer = create_buffer(mg::BufferProperties(geom::Size{1, 1} , mir_pixel_format_abgr_8888, mg::BufferUsage::software));

Cemil Azizoglu (cemil-azizoglu) wrote :

LGTM... Looking forward to more complete performance numbers.

review: Approve
Kevin DuBois (kdub) wrote :

@Daniel
for (1) the issue is that the client is swapinterval0, and the chain representing that client in the host server is operating with 'swapinterval1'. The spare buffers quickly all end up getting stuck in the host's queue, instead of returning from the host on new submissions.

I'm plumbing up a way for the host and the client to agree on swapinterval at the moment. will restack on that branch, and then we don't have to have the issue.

for (3) can probably add this in a subsequent branch.

@Cemil
Will propose updates to the latency suite to accommodate nested passthrough, hopefully before the sprint.

Daniel van Vugt (vanvugt) wrote :

(3) I wonder if there ever might be some future platform which can't pass-through non-bypassable buffers (abgr). Doesn't seem to be important yet but it wouldn't hurt us to remove all doubt and probe using xbgr only.

Cemil:
You won't get more accurate (or encouraging) performance numbers than my above measurements. Although sadly mirvanity only runs on desktop (no Video4Linux support on Android!?).

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/test/mir_test_framework/any_surface.h'
2--- include/test/mir_test_framework/any_surface.h 2016-01-29 08:18:22 +0000
3+++ include/test/mir_test_framework/any_surface.h 2016-10-06 14:43:17 +0000
4@@ -20,10 +20,12 @@
5 #define MIR_TEST_FRAMEWORK_ANY_SURFACE_H_
6
7 #include "mir_toolkit/mir_client_library.h"
8+#include "mir/geometry/size.h"
9
10 namespace mir_test_framework
11 {
12-MirSurface *make_any_surface(MirConnection *connection);
13+MirSurface* make_any_surface(MirConnection *connection);
14+MirSurface* make_surface(MirConnection *connection, mir::geometry::Size size, MirPixelFormat format);
15 }
16
17 #endif // MIR_TEST_FRAMEWORK_ANY_SURFACE_H_
18
19=== modified file 'include/test/mir_test_framework/headless_display_buffer_compositor_factory.h'
20--- include/test/mir_test_framework/headless_display_buffer_compositor_factory.h 2016-09-19 04:16:15 +0000
21+++ include/test/mir_test_framework/headless_display_buffer_compositor_factory.h 2016-10-06 14:43:17 +0000
22@@ -22,10 +22,15 @@
23
24 namespace mir_test_framework
25 {
26+class PassthroughTracker;
27 struct HeadlessDisplayBufferCompositorFactory : mir::compositor::DisplayBufferCompositorFactory
28 {
29+ HeadlessDisplayBufferCompositorFactory();
30+ HeadlessDisplayBufferCompositorFactory(std::shared_ptr<PassthroughTracker> const& tracker);
31 std::unique_ptr<mir::compositor::DisplayBufferCompositor> create_compositor_for(
32 mir::graphics::DisplayBuffer& display_buffer) override;
33+private:
34+ std::shared_ptr<PassthroughTracker> const tracker;
35 };
36 }
37 #endif /* MIR_TEST_FRAMEWORK_HEADLESS_DISPLAY_BUFFER_COMPOSITOR_FACTORY_H_ */
38
39=== modified file 'include/test/mir_test_framework/headless_nested_server_runner.h'
40--- include/test/mir_test_framework/headless_nested_server_runner.h 2016-01-29 08:18:22 +0000
41+++ include/test/mir_test_framework/headless_nested_server_runner.h 2016-10-06 14:43:17 +0000
42@@ -20,13 +20,25 @@
43 #define MIR_TEST_FRAMEWORK_HEADLESS_NESTED_SERVER_RUNNER_H_
44
45 #include "mir_test_framework/async_server_runner.h"
46+#include <atomic>
47
48 namespace mir_test_framework
49 {
50+struct PassthroughTracker
51+{
52+ bool wait_for_passthrough_frames(size_t num_frames, std::chrono::milliseconds ms);
53+ void note_passthrough();
54+private:
55+ std::mutex mutex;
56+ std::condition_variable cv;
57+ size_t num_passthrough;
58+};
59+
60 class HeadlessNestedServerRunner : public AsyncServerRunner
61 {
62 public:
63 HeadlessNestedServerRunner(std::string const& connect_string);
64+ std::shared_ptr<PassthroughTracker> const passthrough_tracker;
65 };
66 }
67
68
69=== modified file 'src/client/atomic_callback.h'
70--- src/client/atomic_callback.h 2016-06-06 12:49:18 +0000
71+++ src/client/atomic_callback.h 2016-10-06 14:43:17 +0000
72@@ -44,20 +44,20 @@
73
74 void set_callback(std::function<void(Args...)> const& fn)
75 {
76- std::lock_guard<std::mutex> lk(guard);
77+ std::lock_guard<std::recursive_mutex> lk(guard);
78
79 callback = fn;
80 }
81
82 void operator()(Args&&... args) const
83 {
84- std::lock_guard<std::mutex> lk(guard);
85+ std::lock_guard<std::recursive_mutex> lk(guard);
86
87 callback(std::forward<Args>(args)...);
88 }
89
90 private:
91- std::mutex mutable guard;
92+ std::recursive_mutex mutable guard;
93 std::function<void(Args...)> callback;
94 };
95 }
96
97=== modified file 'src/client/mir_buffer_api.cpp'
98--- src/client/mir_buffer_api.cpp 2016-09-30 07:03:28 +0000
99+++ src/client/mir_buffer_api.cpp 2016-10-06 14:43:17 +0000
100@@ -49,11 +49,13 @@
101 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
102 }
103
104+void ignore(MirBuffer*, void*){}
105 void mir_buffer_release(MirBuffer* b)
106 try
107 {
108 mir::require(b);
109 auto buffer = reinterpret_cast<mcl::MirBuffer*>(b);
110+ buffer->set_callback(ignore, nullptr);
111 auto connection = buffer->allocating_connection();
112 connection->release_buffer(buffer);
113 }
114
115=== modified file 'src/server/compositor/buffer_map.cpp'
116--- src/server/compositor/buffer_map.cpp 2016-06-24 17:32:47 +0000
117+++ src/server/compositor/buffer_map.cpp 2016-10-06 14:43:17 +0000
118@@ -53,11 +53,13 @@
119 std::unique_lock<decltype(mutex)> lk(mutex);
120 auto buffer = allocator->alloc_buffer(properties);
121 buffers[buffer->id()] = {buffer, Owner::client};
122- sink->add_buffer(*buffer);
123+ if (auto s = sink.lock())
124+ s->add_buffer(*buffer);
125 return buffer->id();
126 } catch (std::exception& e)
127 {
128- sink->error_buffer(properties, e.what());
129+ if (auto s = sink.lock())
130+ s->error_buffer(properties, e.what());
131 throw;
132 }
133 }
134@@ -66,7 +68,8 @@
135 {
136 std::unique_lock<decltype(mutex)> lk(mutex);
137 auto it = checked_buffers_find(id, lk);
138- sink->remove_buffer(*it->second.buffer);
139+ if (auto s = sink.lock())
140+ s->remove_buffer(*it->second.buffer);
141 buffers.erase(it);
142 }
143
144@@ -79,7 +82,8 @@
145 auto buffer = it->second.buffer;
146 it->second.owner = Owner::client;
147 lk.unlock();
148- sink->update_buffer(*buffer);
149+ if (auto s = sink.lock())
150+ s->update_buffer(*buffer);
151 }
152 }
153
154
155=== modified file 'src/server/compositor/buffer_map.h'
156--- src/server/compositor/buffer_map.h 2016-06-02 05:33:50 +0000
157+++ src/server/compositor/buffer_map.h 2016-10-06 14:43:17 +0000
158@@ -58,7 +58,9 @@
159 Map buffers;
160 Map::iterator checked_buffers_find(graphics::BufferID, std::unique_lock<std::mutex> const&);
161
162- std::shared_ptr<frontend::BufferSink> const sink;
163+ //would be better to schedule the async buffer callbacks in the ipc subsystem,
164+ //instead of driving from within the compositor threads (LP: #1395421)
165+ std::weak_ptr<frontend::BufferSink> const sink;
166 std::shared_ptr<graphics::GraphicBufferAllocator> const allocator;
167 };
168 }
169
170=== modified file 'src/server/graphics/nested/buffer.cpp'
171--- src/server/graphics/nested/buffer.cpp 2016-09-22 18:17:43 +0000
172+++ src/server/graphics/nested/buffer.cpp 2016-10-06 14:43:17 +0000
173@@ -181,7 +181,7 @@
174
175 std::shared_ptr<mg::NativeBuffer> mgn::Buffer::native_buffer_handle() const
176 {
177- return nullptr;
178+ return buffer;
179 }
180
181 geom::Size mgn::Buffer::size() const
182
183=== modified file 'src/server/graphics/nested/host_connection.h'
184--- src/server/graphics/nested/host_connection.h 2016-09-22 16:27:13 +0000
185+++ src/server/graphics/nested/host_connection.h 2016-10-06 14:43:17 +0000
186@@ -77,6 +77,7 @@
187 virtual void set_input_event_callback(std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const& cb) = 0;
188 virtual void emit_input_event(MirEvent const& event, mir::geometry::Rectangle const& source_frame) = 0;
189 virtual std::shared_ptr<NativeBuffer> create_buffer(graphics::BufferProperties const&) = 0;
190+ virtual bool supports_passthrough() = 0;
191
192 protected:
193 HostConnection() = default;
194
195=== modified file 'src/server/graphics/nested/host_surface_spec.h'
196--- src/server/graphics/nested/host_surface_spec.h 2016-09-08 18:32:45 +0000
197+++ src/server/graphics/nested/host_surface_spec.h 2016-10-06 14:43:17 +0000
198@@ -19,6 +19,7 @@
199 #ifndef MIR_GRAPHICS_NESTED_HOST_SURFACE_SPEC_H_
200 #define MIR_GRAPHICS_NESTED_HOST_SURFACE_SPEC_H_
201
202+#include "mir_toolkit/client_types.h"
203 #include "mir/geometry/size.h"
204 #include "mir/geometry/displacement.h"
205
206@@ -36,6 +37,7 @@
207 virtual ~HostSurfaceSpec() = default;
208 virtual void add_chain(HostChain&, geometry::Displacement disp, geometry::Size size) = 0;
209 virtual void add_stream(HostStream&, geometry::Displacement disp) = 0;
210+ virtual MirSurfaceSpec* handle() = 0;
211 protected:
212 HostSurfaceSpec() = default;
213 HostSurfaceSpec(HostSurfaceSpec const&) = delete;
214
215=== modified file 'src/server/graphics/nested/ipc_operations.h'
216--- src/server/graphics/nested/ipc_operations.h 2016-09-13 12:40:23 +0000
217+++ src/server/graphics/nested/ipc_operations.h 2016-10-06 14:43:17 +0000
218@@ -33,8 +33,8 @@
219 public:
220 IpcOperations(std::shared_ptr<graphics::PlatformIpcOperations> const& host_operations);
221
222- void pack_buffer(BufferIpcMessage& message, Buffer const& buffer, BufferIpcMsgType msg_type) const override;
223- void unpack_buffer(BufferIpcMessage& message, Buffer const& buffer) const override;
224+ void pack_buffer(BufferIpcMessage& message, graphics::Buffer const& buffer, BufferIpcMsgType msg_type) const override;
225+ void unpack_buffer(BufferIpcMessage& message, graphics::Buffer const& buffer) const override;
226 std::shared_ptr<PlatformIPCPackage> connection_ipc_package() override;
227 PlatformOperationMessage platform_operation(
228 unsigned int const opcode, PlatformOperationMessage const& message) override;
229
230=== modified file 'src/server/graphics/nested/mir_client_host_connection.cpp'
231--- src/server/graphics/nested/mir_client_host_connection.cpp 2016-10-04 11:56:53 +0000
232+++ src/server/graphics/nested/mir_client_host_connection.cpp 2016-10-06 14:43:17 +0000
233@@ -20,11 +20,16 @@
234 #include "host_surface.h"
235 #include "host_stream.h"
236 #include "host_chain.h"
237+#include "host_surface_spec.h"
238+#include "native_buffer.h"
239 #include "mir_toolkit/mir_client_library.h"
240 #include "mir_toolkit/mir_buffer.h"
241+#include "mir_toolkit/mir_buffer_private.h"
242+#include "mir_toolkit/mir_presentation_chain.h"
243 #include "mir/raii.h"
244 #include "mir/graphics/platform_operation_message.h"
245 #include "mir/graphics/cursor_image.h"
246+#include "mir/graphics/buffer.h"
247 #include "mir/input/device.h"
248 #include "mir/input/device_capability.h"
249 #include "mir/input/pointer_configuration.h"
250@@ -38,9 +43,11 @@
251
252 #include <algorithm>
253 #include <stdexcept>
254+#include <condition_variable>
255
256 #include <cstring>
257
258+namespace geom = mir::geometry;
259 namespace mg = mir::graphics;
260 namespace mgn = mir::graphics::nested;
261 namespace mi = mir::input;
262@@ -114,8 +121,9 @@
263 mir_surface_release_sync(mir_surface);
264 }
265
266- void apply_spec(mgn::HostSurfaceSpec&) override
267+ void apply_spec(mgn::HostSurfaceSpec& spec) override
268 {
269+ mir_surface_apply_spec(mir_surface, spec.handle());
270 }
271
272 EGLNativeWindowType egl_native_window() override
273@@ -477,18 +485,197 @@
274 return std::make_unique<MirClientHostStream>(mir_connection, properties);
275 }
276
277+struct Chain : mgn::HostChain
278+{
279+ Chain(MirConnection* connection) :
280+ chain(mir_connection_create_presentation_chain_sync(connection))
281+ {
282+ }
283+ ~Chain()
284+ {
285+ mir_presentation_chain_release(chain);
286+ }
287+
288+ void submit_buffer(mgn::NativeBuffer& buffer)
289+ {
290+ mir_presentation_chain_submit_buffer(chain, buffer.client_handle());
291+ }
292+
293+ MirPresentationChain* handle()
294+ {
295+ return chain;
296+ }
297+private:
298+ MirPresentationChain* chain;
299+};
300+
301 std::unique_ptr<mgn::HostChain> mgn::MirClientHostConnection::create_chain() const
302 {
303- BOOST_THROW_EXCEPTION(std::runtime_error("not implemented yet"));
304+ return std::make_unique<Chain>(mir_connection);
305+}
306+
307+namespace
308+{
309+class HostBuffer : public mgn::NativeBuffer
310+{
311+public:
312+ HostBuffer(MirConnection* mir_connection, mg::BufferProperties const& properties)
313+ {
314+ mir_connection_allocate_buffer(
315+ mir_connection,
316+ properties.size.width.as_int(),
317+ properties.size.height.as_int(),
318+ properties.format,
319+ (properties.usage == mg::BufferUsage::hardware) ? mir_buffer_usage_hardware : mir_buffer_usage_software,
320+ buffer_available, this);
321+ std::unique_lock<std::mutex> lk(mut);
322+ cv.wait(lk, [&]{ return handle; });
323+ if (!mir_buffer_is_valid(handle))
324+ {
325+ mir_buffer_release(handle);
326+ BOOST_THROW_EXCEPTION(std::runtime_error("could not allocate MirBuffer"));
327+ }
328+ }
329+ ~HostBuffer()
330+ {
331+ mir_buffer_release(handle);
332+ }
333+
334+ void sync(MirBufferAccess access, std::chrono::nanoseconds ns) override
335+ {
336+ mir_buffer_wait_for_access(handle, access, ns.count());
337+ }
338+
339+ MirBuffer* client_handle() const override
340+ {
341+ return handle;
342+ }
343+
344+ MirGraphicsRegion get_graphics_region() override
345+ {
346+ return mir_buffer_get_graphics_region(handle, mir_read_write);
347+ }
348+
349+ geom::Size size() const override
350+ {
351+ return { mir_buffer_get_width(handle), mir_buffer_get_height(handle) };
352+ }
353+
354+ MirPixelFormat format() const override
355+ {
356+ return mir_buffer_get_pixel_format(handle);
357+ }
358+
359+ std::tuple<EGLenum, EGLClientBuffer, EGLint*> egl_image_creation_hints() const override
360+ {
361+ EGLenum type;
362+ EGLClientBuffer client_buffer = nullptr;;
363+ EGLint* attrs = nullptr;
364+ mir_buffer_egl_image_parameters(handle, &type, &client_buffer, &attrs);
365+
366+ return std::tuple<EGLenum, EGLClientBuffer, EGLint*>{type, client_buffer, attrs};
367+ }
368+
369+ static void buffer_available(MirBuffer* buffer, void* context)
370+ {
371+ auto host_buffer = static_cast<HostBuffer*>(context);
372+ host_buffer->available(buffer);
373+ }
374+
375+ void available(MirBuffer* buffer)
376+ {
377+ std::unique_lock<std::mutex> lk(mut);
378+ if (!handle)
379+ {
380+ handle = buffer;
381+ cv.notify_all();
382+ }
383+
384+ auto g = f;
385+ lk.unlock();
386+ if (g)
387+ g();
388+ }
389+
390+ void on_ownership_notification(std::function<void()> const& fn) override
391+ {
392+ std::unique_lock<std::mutex> lk(mut);
393+ f = fn;
394+ }
395+
396+ MirBufferPackage* package() const override
397+ {
398+ return mir_buffer_get_buffer_package(handle);
399+ }
400+
401+ void set_fence(mir::Fd fd) override
402+ {
403+ mir_buffer_associate_fence(handle, fd, mir_read_write);
404+ }
405+
406+ mir::Fd fence() const override
407+ {
408+ return mir::Fd{mir::IntOwnedFd{mir_buffer_get_fence(handle)}};
409+ }
410+
411+private:
412+ std::function<void()> f;
413+ MirBuffer* handle = nullptr;
414+ std::mutex mut;
415+ std::condition_variable cv;
416+};
417+
418+class SurfaceSpec : public mgn::HostSurfaceSpec
419+{
420+public:
421+ SurfaceSpec(MirConnection* connection) :
422+ spec(mir_connection_create_spec_for_changes(connection))
423+ {
424+ }
425+
426+ ~SurfaceSpec()
427+ {
428+ mir_surface_spec_release(spec);
429+ }
430+
431+ void add_chain(mgn::HostChain& chain, geom::Displacement disp, geom::Size size) override
432+ {
433+ mir_surface_spec_add_presentation_chain(
434+ spec, size.width.as_int(), size.height.as_int(),
435+ disp.dx.as_int(), disp.dy.as_int(), chain.handle());
436+ }
437+
438+ void add_stream(mgn::HostStream& stream, geom::Displacement disp) override
439+ {
440+ mir_surface_spec_add_buffer_stream(spec, disp.dx.as_int(), disp.dy.as_int(), stream.handle());
441+ }
442+
443+ MirSurfaceSpec* handle() override
444+ {
445+ return spec;
446+ }
447+private:
448+ MirSurfaceSpec* spec;
449+};
450 }
451
452 std::shared_ptr<mgn::NativeBuffer> mgn::MirClientHostConnection::create_buffer(
453- mg::BufferProperties const&)
454+ mg::BufferProperties const& properties)
455 {
456- BOOST_THROW_EXCEPTION(std::runtime_error("not implemented yet"));
457+ return std::make_shared<HostBuffer>(mir_connection, properties);
458 }
459
460 std::unique_ptr<mgn::HostSurfaceSpec> mgn::MirClientHostConnection::create_surface_spec()
461 {
462- BOOST_THROW_EXCEPTION(std::runtime_error("not implemented yet"));
463+ return std::make_unique<SurfaceSpec>(mir_connection);
464+}
465+
466+bool mgn::MirClientHostConnection::supports_passthrough()
467+{
468+ auto buffer = create_buffer(mg::BufferProperties(geom::Size{1, 1} , mir_pixel_format_abgr_8888, mg::BufferUsage::software));
469+
470+ auto hints = buffer->egl_image_creation_hints();
471+ if (std::get<1>(hints) == nullptr && std::get<2>(hints) == nullptr)
472+ return false;
473+ return true;
474 }
475
476=== modified file 'src/server/graphics/nested/mir_client_host_connection.h'
477--- src/server/graphics/nested/mir_client_host_connection.h 2016-10-04 11:56:53 +0000
478+++ src/server/graphics/nested/mir_client_host_connection.h 2016-10-06 14:43:17 +0000
479@@ -86,6 +86,7 @@
480 void set_input_event_callback(std::function<void(MirEvent const&, mir::geometry::Rectangle const&)> const& cb) override;
481 void emit_input_event(MirEvent const& cb, mir::geometry::Rectangle const& source_frame) override;
482 std::shared_ptr<NativeBuffer> create_buffer(graphics::BufferProperties const&) override;
483+ bool supports_passthrough() override;
484
485 private:
486 void update_input_config(UniqueInputConfig input_config);
487
488=== modified file 'src/server/graphics/nested/native_buffer.h'
489--- src/server/graphics/nested/native_buffer.h 2016-09-30 12:26:56 +0000
490+++ src/server/graphics/nested/native_buffer.h 2016-10-06 14:43:17 +0000
491@@ -43,7 +43,6 @@
492 virtual ~NativeBuffer() = default;
493 virtual void sync(MirBufferAccess, std::chrono::nanoseconds) = 0;
494 virtual MirBuffer* client_handle() const = 0;
495- virtual MirNativeBuffer* get_native_handle() = 0;
496 virtual MirGraphicsRegion get_graphics_region() = 0;
497 virtual geometry::Size size() const = 0;
498 virtual MirPixelFormat format() const = 0;
499
500=== modified file 'src/server/graphics/nested/platform.cpp'
501--- src/server/graphics/nested/platform.cpp 2016-07-19 20:56:18 +0000
502+++ src/server/graphics/nested/platform.cpp 2016-10-06 14:43:17 +0000
503@@ -19,10 +19,16 @@
504 #include "platform.h"
505 #include "host_connection.h"
506 #include "display.h"
507+#include "buffer.h"
508+#include "native_buffer.h"
509+#include "ipc_operations.h"
510 #include "mir/shared_library.h"
511 #include "mir/graphics/graphic_buffer_allocator.h"
512 #include "mir/graphics/display.h"
513 #include "mir/graphics/platform_ipc_operations.h"
514+#include "mir/graphics/buffer_ipc_message.h"
515+#include "mir/graphics/platform_ipc_operations.h"
516+#include "mir/graphics/platform_operation_message.h"
517
518 namespace mg = mir::graphics;
519 namespace mgn = mir::graphics::nested;
520@@ -39,9 +45,53 @@
521 {
522 }
523
524+namespace
525+{
526+class BufferAllocator : public mg::GraphicBufferAllocator
527+{
528+public:
529+ BufferAllocator(
530+ std::shared_ptr<mgn::HostConnection> const& connection,
531+ std::shared_ptr<mg::GraphicBufferAllocator> const& guest_allocator) :
532+ connection(connection),
533+ guest_allocator(guest_allocator)
534+ {
535+ }
536+
537+ std::shared_ptr<mg::Buffer> alloc_buffer(mg::BufferProperties const& buffer_properties) override
538+ {
539+ if ((buffer_properties.size.width >= mir::geometry::Width{480}) &&
540+ (buffer_properties.size.height >= mir::geometry::Height{480}))
541+ {
542+ return std::make_shared<mgn::Buffer>(connection, buffer_properties);
543+ }
544+ else
545+ {
546+ return guest_allocator->alloc_buffer(buffer_properties);
547+ }
548+ }
549+
550+ std::vector<MirPixelFormat> supported_pixel_formats() override
551+ {
552+ return guest_allocator->supported_pixel_formats();
553+ }
554+
555+private:
556+ std::shared_ptr<mgn::HostConnection> const connection;
557+ std::shared_ptr<mg::GraphicBufferAllocator> const guest_allocator;
558+};
559+}
560+
561 mir::UniqueModulePtr<mg::GraphicBufferAllocator> mgn::Platform::create_buffer_allocator()
562 {
563- return guest_platform->create_buffer_allocator();
564+ if (connection->supports_passthrough())
565+ {
566+ return mir::make_module_ptr<BufferAllocator>(connection, guest_platform->create_buffer_allocator());
567+ }
568+ else
569+ {
570+ return guest_platform->create_buffer_allocator();
571+ }
572 }
573
574 mir::UniqueModulePtr<mg::Display> mgn::Platform::create_display(
575@@ -58,5 +108,5 @@
576
577 mir::UniqueModulePtr<mg::PlatformIpcOperations> mgn::Platform::make_ipc_operations() const
578 {
579- return guest_platform->make_ipc_operations();
580+ return mir::make_module_ptr<mgn::IpcOperations>(guest_platform->make_ipc_operations());
581 }
582
583=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
584--- tests/acceptance-tests/test_nested_mir.cpp 2016-09-28 14:07:37 +0000
585+++ tests/acceptance-tests/test_nested_mir.cpp 2016-10-06 14:43:17 +0000
586@@ -640,6 +640,13 @@
587
588 struct ClientWithAPaintedSurface : virtual Client
589 {
590+ ClientWithAPaintedSurface(NestedMirRunner& nested_mir, geom::Size size, MirPixelFormat format) :
591+ Client(nested_mir),
592+ surface(mtf::make_surface(connection, size, format))
593+ {
594+ mir_buffer_stream_swap_buffers_sync(mir_surface_get_buffer_stream(surface));
595+ }
596+
597 ClientWithAPaintedSurface(NestedMirRunner& nested_mir) :
598 Client(nested_mir),
599 surface(mtf::make_any_surface(connection))
600@@ -1504,3 +1511,13 @@
601 EXPECT_TRUE(host_config_change.raised());
602 Mock::VerifyAndClearExpectations(&display);
603 }
604+
605+TEST_F(NestedServer, uses_passthrough_when_surface_size_is_appropriate)
606+{
607+ using namespace std::chrono_literals;
608+ NestedMirRunner nested_mir{new_connection()};
609+ nested_mir.wait_until_ready();
610+ ClientWithAPaintedSurface client(
611+ nested_mir, display_geometry.front().size, mir_pixel_format_xbgr_8888);
612+ EXPECT_TRUE(nested_mir.passthrough_tracker->wait_for_passthrough_frames(1, 5s));
613+}
614
615=== modified file 'tests/include/mir/test/doubles/stub_client_buffer.h'
616--- tests/include/mir/test/doubles/stub_client_buffer.h 2016-09-30 07:03:28 +0000
617+++ tests/include/mir/test/doubles/stub_client_buffer.h 2016-10-06 14:43:17 +0000
618@@ -85,7 +85,12 @@
619 void set_fence(Fd, MirBufferAccess) override {}
620 Fd get_fence() const override { return mir::Fd(mir::Fd::invalid); }
621 bool wait_fence(MirBufferAccess, std::chrono::nanoseconds) override { return true; }
622- void egl_image_creation_parameters(EGLenum*, EGLClientBuffer*, EGLint**) {}
623+ void egl_image_creation_parameters(EGLenum*, EGLClientBuffer*, EGLint** attrs)
624+ {
625+ static EGLint image_attrs[] = { EGL_NONE };
626+ if (attrs)
627+ *attrs = image_attrs;
628+ }
629
630 std::shared_ptr<MirBufferPackage> const package_;
631 geometry::Size size_;
632
633=== modified file 'tests/include/mir/test/doubles/stub_host_connection.h'
634--- tests/include/mir/test/doubles/stub_host_connection.h 2016-09-23 16:50:05 +0000
635+++ tests/include/mir/test/doubles/stub_host_connection.h 2016-10-06 14:43:17 +0000
636@@ -156,9 +156,14 @@
637 {
638 void add_chain(graphics::nested::HostChain&, geometry::Displacement, geometry::Size) override {}
639 void add_stream(graphics::nested::HostStream&, geometry::Displacement) override {}
640+ MirSurfaceSpec* handle() { return nullptr; }
641 };
642 return std::make_unique<NullSpec>();
643 }
644+ bool supports_passthrough()
645+ {
646+ return true;
647+ }
648 };
649
650 struct MockHostConnection : StubHostConnection
651
652=== modified file 'tests/integration-tests/test_buffer_scheduling.cpp'
653--- tests/integration-tests/test_buffer_scheduling.cpp 2016-09-28 00:41:48 +0000
654+++ tests/integration-tests/test_buffer_scheduling.cpp 2016-10-06 14:43:17 +0000
655@@ -588,9 +588,8 @@
656 BufferScheduling()
657 {
658 ipc = std::make_shared<StubIpcSystem>();
659- map = std::make_shared<mc::BufferMap>(
660- std::make_shared<StubEventSink>(ipc),
661- std::make_shared<mtd::StubBufferAllocator>());
662+ sink = std::make_shared<StubEventSink>(ipc);
663+ map = std::make_shared<mc::BufferMap>(sink, std::make_shared<mtd::StubBufferAllocator>());
664 auto submit_stream = std::make_shared<mc::Stream>(
665 drop_policy,
666 map,
667@@ -648,6 +647,7 @@
668 mcl::ClientBufferDepository depository{mt::fake_shared(client_buffer_factory), nbuffers};
669 std::shared_ptr<mc::BufferStream> stream;
670 std::shared_ptr<StubIpcSystem> ipc;
671+ std::shared_ptr<mf::BufferSink> sink;
672 std::unique_ptr<ProducerSystem> producer;
673 std::unique_ptr<ConsumerSystem> consumer;
674 std::unique_ptr<ConsumerSystem> second_consumer;
675
676=== modified file 'tests/mir_test_framework/any_surface.cpp'
677--- tests/mir_test_framework/any_surface.cpp 2016-08-23 03:44:55 +0000
678+++ tests/mir_test_framework/any_surface.cpp 2016-10-06 14:43:17 +0000
679@@ -32,10 +32,16 @@
680
681 MirSurface* mtf::make_any_surface(MirConnection *connection)
682 {
683+ return mtf::make_surface(connection, mir::geometry::Size{width, height}, format);
684+}
685+
686+MirSurface* mtf::make_surface(
687+ MirConnection *connection, mir::geometry::Size size, MirPixelFormat f)
688+{
689 using namespace std::literals::string_literals;
690
691 auto spec = mir_connection_create_spec_for_normal_surface(connection,
692- width, height, format);
693+ size.width.as_int(), size.height.as_int(), f);
694 auto surface = mir_surface_create_sync(spec);
695 mir_surface_spec_release(spec);
696
697
698=== modified file 'tests/mir_test_framework/headless_display_buffer_compositor_factory.cpp'
699--- tests/mir_test_framework/headless_display_buffer_compositor_factory.cpp 2016-09-19 06:09:48 +0000
700+++ tests/mir_test_framework/headless_display_buffer_compositor_factory.cpp 2016-10-06 14:43:17 +0000
701@@ -17,6 +17,7 @@
702 */
703
704 #include "mir_test_framework/headless_display_buffer_compositor_factory.h"
705+#include "mir_test_framework/headless_nested_server_runner.h"
706 #include "mir/renderer/gl/render_target.h"
707 #include "mir/graphics/display_buffer.h"
708 #include "mir/compositor/display_buffer_compositor.h"
709@@ -30,13 +31,27 @@
710 namespace mc = mir::compositor;
711 namespace geom = mir::geometry;
712
713+mtf::HeadlessDisplayBufferCompositorFactory::HeadlessDisplayBufferCompositorFactory() :
714+ tracker(nullptr)
715+{
716+}
717+
718+mtf::HeadlessDisplayBufferCompositorFactory::HeadlessDisplayBufferCompositorFactory(
719+ std::shared_ptr<PassthroughTracker> const& tracker) :
720+ tracker(tracker)
721+{
722+}
723+
724 std::unique_ptr<mir::compositor::DisplayBufferCompositor>
725 mtf::HeadlessDisplayBufferCompositorFactory::create_compositor_for(mg::DisplayBuffer& db)
726 {
727 struct HeadlessDBC : mir::compositor::DisplayBufferCompositor
728 {
729- HeadlessDBC(mg::DisplayBuffer& db) :
730+ HeadlessDBC(
731+ mg::DisplayBuffer& db,
732+ std::shared_ptr<mtf::PassthroughTracker> const& tracker) :
733 db(db),
734+ tracker(tracker),
735 render_target(dynamic_cast<mrg::RenderTarget*>(
736 db.native_display_buffer()))
737 {
738@@ -73,7 +88,11 @@
739 {
740 auto renderlist = filter(seq, db.view_area());
741 if (db.overlay(renderlist))
742+ {
743+ if (tracker)
744+ tracker->note_passthrough();
745 return;
746+ }
747
748 // Invoke GL renderer specific functions if the DisplayBuffer supports them
749 if (render_target)
750@@ -87,7 +106,8 @@
751 render_target->swap_buffers();
752 }
753 mg::DisplayBuffer& db;
754+ std::shared_ptr<PassthroughTracker> const tracker;
755 mrg::RenderTarget* const render_target;
756 };
757- return std::make_unique<HeadlessDBC>(db);
758+ return std::make_unique<HeadlessDBC>(db, tracker);
759 }
760
761=== modified file 'tests/mir_test_framework/headless_nested_server_runner.cpp'
762--- tests/mir_test_framework/headless_nested_server_runner.cpp 2016-09-19 04:16:15 +0000
763+++ tests/mir_test_framework/headless_nested_server_runner.cpp 2016-10-06 14:43:17 +0000
764@@ -22,12 +22,26 @@
765
766 namespace mtf = mir_test_framework;
767
768-mtf::HeadlessNestedServerRunner::HeadlessNestedServerRunner(std::string const& connect_string)
769+mtf::HeadlessNestedServerRunner::HeadlessNestedServerRunner(std::string const& connect_string) :
770+ passthrough_tracker(std::make_shared<mtf::PassthroughTracker>())
771 {
772 add_to_environment("MIR_SERVER_PLATFORM_GRAPHICS_LIB", mtf::server_platform("graphics-dummy.so").c_str());
773 add_to_environment("MIR_SERVER_HOST_SOCKET", connect_string.c_str());
774- server.override_the_display_buffer_compositor_factory([]
775+ server.override_the_display_buffer_compositor_factory([this]
776 {
777- return std::make_shared<mtf::HeadlessDisplayBufferCompositorFactory>();
778+ return std::make_shared<mtf::HeadlessDisplayBufferCompositorFactory>(passthrough_tracker);
779 });
780 }
781+
782+void mtf::PassthroughTracker::note_passthrough()
783+{
784+ std::unique_lock<std::mutex> lk(mutex);
785+ num_passthrough++;
786+ cv.notify_all();
787+}
788+
789+bool mtf::PassthroughTracker::wait_for_passthrough_frames(size_t nframes, std::chrono::milliseconds ms)
790+{
791+ std::unique_lock<std::mutex> lk(mutex);
792+ return cv.wait_for(lk, ms, [&] { return num_passthrough >= nframes; } );
793+}
794
795=== modified file 'tests/mir_test_framework/headless_test.cpp'
796--- tests/mir_test_framework/headless_test.cpp 2016-09-19 04:16:15 +0000
797+++ tests/mir_test_framework/headless_test.cpp 2016-10-06 14:43:17 +0000
798@@ -34,7 +34,7 @@
799 add_to_environment("MIR_SERVER_PLATFORM_GRAPHICS_LIB", mtf::server_platform("graphics-dummy.so").c_str());
800 add_to_environment("MIR_SERVER_PLATFORM_INPUT_LIB", mtf::server_platform("input-stub.so").c_str());
801 add_to_environment("MIR_SERVER_ENABLE_KEY_REPEAT", "false");
802- server.override_the_display_buffer_compositor_factory([]
803+ server.override_the_display_buffer_compositor_factory([this]
804 {
805 return std::make_shared<mtf::HeadlessDisplayBufferCompositorFactory>();
806 });
807
808=== modified file 'tests/unit-tests/compositor/test_client_buffers.cpp'
809--- tests/unit-tests/compositor/test_client_buffers.cpp 2016-06-24 17:32:47 +0000
810+++ tests/unit-tests/compositor/test_client_buffers.cpp 2016-10-06 14:43:17 +0000
811@@ -59,11 +59,11 @@
812
813 struct ClientBuffers : public Test
814 {
815- testing::NiceMock<mtd::MockEventSink> mock_sink;
816+ std::shared_ptr<mtd::MockEventSink> mock_sink = std::make_shared<testing::NiceMock<mtd::MockEventSink>>();
817 mg::BufferProperties properties{geom::Size{42,43}, mir_pixel_format_abgr_8888, mg::BufferUsage::hardware};
818 MockBufferAllocator mock_allocator;
819 StubBufferAllocator stub_allocator;
820- mc::BufferMap map{mt::fake_shared(mock_sink), mt::fake_shared(stub_allocator)};
821+ mc::BufferMap map{mock_sink, mt::fake_shared(stub_allocator)};
822 };
823
824 TEST_F(ClientBuffers, sends_full_buffer_on_allocation)
825@@ -71,8 +71,8 @@
826 auto stub_buffer = std::make_shared<mtd::StubBuffer>();
827 EXPECT_CALL(mock_allocator, alloc_buffer(Ref(properties)))
828 .WillOnce(Return(stub_buffer));
829- EXPECT_CALL(mock_sink, add_buffer(Ref(*stub_buffer)));
830- mc::BufferMap map{mt::fake_shared(mock_sink), mt::fake_shared(mock_allocator)};
831+ EXPECT_CALL(*mock_sink, add_buffer(Ref(*stub_buffer)));
832+ mc::BufferMap map{mock_sink, mt::fake_shared(mock_allocator)};
833 EXPECT_THAT(map.add_buffer(properties), Eq(stub_buffer->id()));
834 }
835
836@@ -107,7 +107,7 @@
837 ASSERT_THAT(stub_allocator.map, SizeIs(1));
838 ASSERT_THAT(stub_allocator.ids, SizeIs(1));
839 auto buffer = map[stub_allocator.ids[0]];
840- EXPECT_CALL(mock_sink, update_buffer(Ref(*buffer)));
841+ EXPECT_CALL(*mock_sink, update_buffer(Ref(*buffer)));
842 map.send_buffer(stub_allocator.ids[0]);
843 }
844
845@@ -118,7 +118,7 @@
846 ASSERT_THAT(stub_allocator.ids, SizeIs(1));
847 auto buffer = map[stub_allocator.ids[0]];
848
849- EXPECT_CALL(mock_sink, remove_buffer(Ref(*buffer)));
850+ EXPECT_CALL(*mock_sink, remove_buffer(Ref(*buffer)));
851 map.remove_buffer(stub_allocator.ids[0]);
852 map.send_buffer(stub_allocator.ids[0]);
853 }
854@@ -126,7 +126,7 @@
855 TEST_F(ClientBuffers, can_remove_buffer_from_send_callback)
856 {
857 map.add_buffer(properties);
858- ON_CALL(mock_sink, update_buffer(_))
859+ ON_CALL(*mock_sink, update_buffer(_))
860 .WillByDefault(Invoke(
861 [&] (mg::Buffer& buffer)
862 {
863@@ -138,7 +138,7 @@
864
865 TEST_F(ClientBuffers, ignores_unknown_receive)
866 {
867- EXPECT_CALL(mock_sink, add_buffer(_))
868+ EXPECT_CALL(*mock_sink, add_buffer(_))
869 .Times(1);
870 map.add_buffer(properties);
871 map.remove_buffer(stub_allocator.ids[0]);
872@@ -150,8 +150,8 @@
873 std::string error_msg = "a reason";
874 EXPECT_CALL(mock_allocator, alloc_buffer(Ref(properties)))
875 .WillOnce(Throw(std::runtime_error(error_msg)));
876- EXPECT_CALL(mock_sink, error_buffer(properties, StrEq(error_msg)));
877- mc::BufferMap map{mt::fake_shared(mock_sink), mt::fake_shared(mock_allocator)};
878+ EXPECT_CALL(*mock_sink, error_buffer(properties, StrEq(error_msg)));
879+ mc::BufferMap map{mock_sink, mt::fake_shared(mock_allocator)};
880 EXPECT_THROW({
881 map.add_buffer(properties);
882 }, std::runtime_error);
883
884=== modified file 'tests/unit-tests/platforms/nested/test_buffer.cpp'
885--- tests/unit-tests/platforms/nested/test_buffer.cpp 2016-09-30 12:26:56 +0000
886+++ tests/unit-tests/platforms/nested/test_buffer.cpp 2016-10-06 14:43:17 +0000
887@@ -208,6 +208,7 @@
888
889 EXPECT_CALL(mock_egl, eglGetCurrentDisplay());
890 EXPECT_CALL(mock_egl, eglGetCurrentContext());
891+ EXPECT_CALL(mock_egl, eglCreateImageKHR(_,_,_,_,_));
892 EXPECT_CALL(*client_buffer, sync(mir_read, _));
893 EXPECT_CALL(mock_egl, glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, _));
894
895
896=== modified file 'tests/unit-tests/platforms/nested/test_ipc_operations.cpp'
897--- tests/unit-tests/platforms/nested/test_ipc_operations.cpp 2016-09-30 12:53:35 +0000
898+++ tests/unit-tests/platforms/nested/test_ipc_operations.cpp 2016-10-06 14:43:17 +0000
899@@ -47,7 +47,6 @@
900 public:
901 void sync(MirBufferAccess, std::chrono::nanoseconds) override {}
902 MirBuffer* client_handle() const override { return nullptr; }
903- MirNativeBuffer* get_native_handle() override { return nullptr; }
904 MirGraphicsRegion get_graphics_region() override
905 {
906 return MirGraphicsRegion { 0, 0, 0, mir_pixel_format_invalid, nullptr };
907
908=== modified file 'tests/unit-tests/platforms/nested/test_nested_display_buffer.cpp'
909--- tests/unit-tests/platforms/nested/test_nested_display_buffer.cpp 2016-09-30 12:53:35 +0000
910+++ tests/unit-tests/platforms/nested/test_nested_display_buffer.cpp 2016-10-06 14:43:17 +0000
911@@ -122,7 +122,6 @@
912 geom::Size size() const override { return {}; }
913 MirPixelFormat format() const override { return mir_pixel_format_invalid; }
914 void on_ownership_notification(std::function<void()> const& f) override { fn = f; }
915- MirNativeBuffer* get_native_handle() override { return nullptr; }
916 MirBufferPackage* package() const override { return nullptr; }
917 mir::Fd fence() const override { return mir::Fd{mir::Fd::invalid}; }
918 void set_fence(mir::Fd) override {}

Subscribers

People subscribed via source and target branches