Mir

Merge lp:~raof/mir/better-buffer-plumbing into lp:mir

Proposed by Chris Halse Rogers on 2017-07-18
Status: Merged
Approved by: Alan Griffiths on 2017-07-19
Approved revision: 4223
Merged at revision: 4208
Proposed branch: lp:~raof/mir/better-buffer-plumbing
Merge into: lp:mir
Prerequisite: lp:~raof/mir/dont-ack-release-buffer
Diff against target: 3607 lines (+1033/-1089)
44 files modified
examples/server_example_canonical_window_manager.cpp (+5/-3)
examples/server_example_canonical_window_manager.h (+7/-1)
examples/server_example_window_management.cpp (+6/-1)
include/server/mir/frontend/client_buffers.h (+0/-46)
include/server/mir/frontend/session.h (+0/-6)
include/server/mir/scene/buffer_stream_factory.h (+4/-6)
include/server/mir/scene/session.h (+0/-6)
include/server/mir/shell/window_management_info.h (+5/-1)
include/test/mir/test/doubles/stub_session.h (+0/-6)
src/client/mir_connection.cpp (+0/-1)
src/server/compositor/CMakeLists.txt (+0/-1)
src/server/compositor/buffer_map.cpp (+0/-114)
src/server/compositor/buffer_map.h (+0/-65)
src/server/compositor/buffer_stream_factory.cpp (+5/-12)
src/server/compositor/buffer_stream_factory.h (+4/-5)
src/server/compositor/dropping_schedule.cpp (+1/-12)
src/server/compositor/dropping_schedule.h (+1/-3)
src/server/compositor/multi_monitor_arbiter.cpp (+1/-5)
src/server/compositor/multi_monitor_arbiter.h (+0/-2)
src/server/compositor/stream.cpp (+7/-25)
src/server/compositor/stream.h (+1/-2)
src/server/frontend/default_ipc_factory.cpp (+3/-1)
src/server/frontend/session_mediator.cpp (+127/-32)
src/server/frontend/session_mediator.h (+6/-2)
src/server/scene/application_session.cpp (+1/-53)
src/server/scene/application_session.h (+0/-7)
src/server/shell/window_management_info.cpp (+13/-26)
tests/include/mir/test/doubles/stub_buffer_stream_factory.h (+9/-30)
tests/integration-tests/compositor/test_swapping_swappers.cpp (+1/-2)
tests/integration-tests/test_buffer_scheduling.cpp (+25/-14)
tests/integration-tests/test_session.cpp (+1/-1)
tests/integration-tests/test_submit_buffer.cpp (+146/-108)
tests/integration-tests/test_surface_stack_with_compositor.cpp (+2/-5)
tests/integration-tests/test_swapinterval.cpp (+3/-8)
tests/mir_test_framework/stub_session.cpp (+0/-25)
tests/unit-tests/client/test_mir_connection.cpp (+0/-1)
tests/unit-tests/compositor/CMakeLists.txt (+0/-1)
tests/unit-tests/compositor/test_client_buffers.cpp (+0/-118)
tests/unit-tests/compositor/test_dropping_schedule.cpp (+6/-45)
tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp (+171/-112)
tests/unit-tests/compositor/test_stream.cpp (+27/-68)
tests/unit-tests/frontend/test_session_mediator.cpp (+437/-82)
tests/unit-tests/scene/test_application_session.cpp (+7/-14)
tests/unit-tests/scene/test_surface_stack.cpp (+1/-11)
To merge this branch: bzr merge lp:~raof/mir/better-buffer-plumbing
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration 2017-07-18 Approve on 2017-07-19
Alan Griffiths 2017-07-18 Approve on 2017-07-18
Brandon Schaefer 2017-07-18 Pending
Review via email: mp+327576@code.launchpad.net

This proposal supersedes a proposal from 2017-07-04.

Commit message

Move full responsibility for buffer IPC into the frontend.

Currently buffer IPC is split between the frontend and various things which shared an mf::BufferMap.

This branch consolidates everything so that, outside the SessionMediator, everything is dealing with
a std::shared_ptr<mg::Buffer>.

In addition to consolidating IPC into the frontend where it belongs, this makes it easy
to submit client-allocated buffers.

To post a comment you must log in.
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:4210
https://mir-jenkins.ubuntu.com/job/mir-ci/3472/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4745/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4903
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4892
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4892
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4892
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4782/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4782
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4782/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4782
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4782/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4782/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4782
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4782/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4782
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4782/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4782
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4782/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4782/console

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

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:4211
https://mir-jenkins.ubuntu.com/job/mir-ci/3475/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4748/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4906
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4895
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4895
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4895
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4785/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4785/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4785/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4785/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4785/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4785
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4785/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4785
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4785/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4785/console

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

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:4212
https://mir-jenkins.ubuntu.com/job/mir-ci/3476/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4749/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4907
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4896
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4896
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4896
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4786/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4786
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4786/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4786
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4786/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4786
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4786/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4786/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4786
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4786/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4786
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4786/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4786
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4786/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

PASSED: Continuous integration, rev:4214
https://mir-jenkins.ubuntu.com/job/mir-ci/3477/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4750
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4908
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4897
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4897
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4897
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4787/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4787
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4787/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Brandon Schaefer (brandontschaefer) wrote : Posted in a previous version of this proposal

Nice, lgtm. Now we can accept gbm buffers easier then the way it looked before :)

review: Approve
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

The name "mir::graphics::GraphicBufferAllocator" seems tautological why not "mir::graphics::BufferAllocator"?

Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> The name "mir::graphics::GraphicBufferAllocator" seems tautological why not
> "mir::graphics::BufferAllocator"?

/sigh I guess that's pre-existing.

Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

nits

+ // We can't reasonably answer this question -
+ // Suitability for cursor use is a per-buffer property, not a per-stream property.
return true;

Instead of hard coding this to true wouldn't it be less misleading to remove the calls to this function?

~~~~

Looks like this changes the mirserver ABI - there ought to be removals from the symbols script (e.g. mir::frontend::ClientBuffers) and a bump to the SONAME.

But that can be done separately.

Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

This breaks when starting a load of clients. (I built lp:miral against it and...)

$ cat `which mir_demo_client_all`
#!/bin/sh
mir_demo_client_animated_cursor&mir_demo_client_eglsquare&mir_demo_client_prerendered_frames&mir_demo_client_basic&mir_demo_client_eglstateswitcher&mir_demo_client_progressbar&mir_demo_client_camera&mir_demo_client_egltriangle&mir_demo_client_prompt_session&mir_demo_client_cursors&mir_demo_client_fingerpaint&mir_demo_client_release_at_exit&mir_demo_client_display_config&mir_demo_client_flicker&mir_demo_client_scroll&mir_demo_client_eglcounter&mir_demo_client_input_shapes&mir_demo_client_target&mir_demo_client_eglflash&mir_demo_client_multistream&mir_demo_client_tooltip&mir_demo_client_eglplasma&mir_demo_client_multiwin&mir_demo_client_touch_validator&

$miral-app

[in the miral terminal]
$ mir_demo_client_all

Expect: all the demos clients start
Actual: miral-shell crashes

I don't see this without this MP.

review: Needs Fixing
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

Interesting. I'll investigate!

Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:4215
https://mir-jenkins.ubuntu.com/job/mir-ci/3484/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4759/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4920
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4909
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4909
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4909
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4796/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4796
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4796/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4796/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4796
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4796/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4796
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4796/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4796/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4796
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4796/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4796
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4796/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Works much better but...

$ miral-app -launcher mir_demo_client_multistream

Wait about 30sec and it locks up

review: Needs Fixing
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

Huh. Artful build failures are due to Artful (specifically, dh_strip_nondeterminism) being broken.

Urgh. Let's try multistream!

Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

Ah, good. This also happens with mir_demo_server, which is easier to deal with.

But only multistream? Not the EGL demos, as far as I can tell. Odd.

Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

Thinking about it - a client setting a bad BufferStreamID shouldn't crash the server. It should simply kill the session.

Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

Setting a bad BufferStreamID doesn't crash the server. At least, not that alone.

Hah! The hang in mir_demo_client_multistream is a client buffer leak, leading to fd starvation. Yay!

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

PASSED: Continuous integration, rev:4221
https://mir-jenkins.ubuntu.com/job/mir-ci/3490/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4765
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4936
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4926
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4926
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4926
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4803/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4803
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4803/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Alan Griffiths (alan-griffiths) wrote :

> SessionMediator: std::logic_error is not derived from std::runtime_error.
>
> So we need to catch std::exception in order to actually send error-buffers rather than crash
> the server!

Surely logic errors need to be found and avoided before release? Crashing the server seems a good way to motivate this.

Alan Griffiths (alan-griffiths) wrote :

Looks mostly good, except that mir_demo_client_animated_cursor seems to be in slow motion.

Alan Griffiths (alan-griffiths) wrote :

> Looks mostly good, except that mir_demo_client_animated_cursor seems to be in
> slow motion.

Hmm that appears to happen on trunk too. Seems recent (0.27 from archive is fine.)

Alan Griffiths (alan-griffiths) wrote :

I'm down to nits, approving on the basis that I trust you:

There's a trivial merge conflict with latest trunk.

~~~~

+ // We can't reasonably answer this question -
+ // Suitability for cursor use is a per-buffer property, not a per-stream property.
return true;

Instead of hard coding this to true wouldn't it be less misleading to remove the calls to this function?

~~~~

Looks like this changes the mirserver ABI - there ought to be removals from the symbols script (e.g. mir::frontend::ClientBuffers) and a bump to the SONAME.

But that can be done separately.

review: Approve
Chris Halse Rogers (raof) wrote :

Yeah. There's even more follow-up to be done. I thought this was probably getting big enough, and the follow up could be done in follow up :)

lp:~raof/mir/better-buffer-plumbing updated on 2017-07-19
4222. By Chris Halse Rogers on 2017-07-19

Merge trunk, resolving trivial example/render_surfaces.cpp conflict

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

PASSED: Continuous integration, rev:4222
https://mir-jenkins.ubuntu.com/job/mir-ci/3493/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4772
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4944
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4933
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4933
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4933
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4809/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4809
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4809/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
lp:~raof/mir/better-buffer-plumbing updated on 2017-07-19
4223. By Chris Halse Rogers on 2017-07-19

Merge prereq

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

PASSED: Continuous integration, rev:4223
https://mir-jenkins.ubuntu.com/job/mir-ci/3496/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4777
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4949
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4938
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4938
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4938
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4814/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4814
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4814/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
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
1=== modified file 'examples/server_example_canonical_window_manager.cpp'
2--- examples/server_example_canonical_window_manager.cpp 2017-05-25 04:33:43 +0000
3+++ examples/server_example_canonical_window_manager.cpp 2017-07-19 05:46:21 +0000
4@@ -54,9 +54,11 @@
5
6 me::CanonicalWindowManagerPolicyCopy::CanonicalWindowManagerPolicyCopy(
7 WindowManagerTools* const tools,
8- std::shared_ptr<shell::DisplayLayout> const& display_layout) :
9+ std::shared_ptr<shell::DisplayLayout> const& display_layout,
10+ std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator) :
11 tools{tools},
12- display_layout{display_layout}
13+ display_layout{display_layout},
14+ allocator{allocator}
15 {
16 }
17
18@@ -276,7 +278,7 @@
19 surface_map.emplace(titlebar, SurfaceInfo{session, titlebar, {}}).first->second;
20 titlebar_info.is_titlebar = true;
21 titlebar_info.parent = surface;
22- titlebar_info.init_titlebar(session, titlebar);
23+ titlebar_info.init_titlebar(*allocator, titlebar);
24 }
25
26 void me::CanonicalWindowManagerPolicyCopy::handle_new_surface(std::shared_ptr<ms::Session> const& session, std::shared_ptr<ms::Surface> const& surface)
27
28=== modified file 'examples/server_example_canonical_window_manager.h'
29--- examples/server_example_canonical_window_manager.h 2017-05-08 03:04:26 +0000
30+++ examples/server_example_canonical_window_manager.h 2017-07-19 05:46:21 +0000
31@@ -32,6 +32,10 @@
32 namespace mir
33 {
34 namespace shell { class DisplayLayout; }
35+namespace graphics
36+{
37+class GraphicBufferAllocator;
38+}
39 namespace examples
40 {
41 // standard window management algorithm:
42@@ -48,7 +52,8 @@
43
44 explicit CanonicalWindowManagerPolicyCopy(
45 WindowManagerTools* const tools,
46- std::shared_ptr<shell::DisplayLayout> const& display_layout);
47+ std::shared_ptr<shell::DisplayLayout> const& display_layout,
48+ std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator);
49
50 void click(geometry::Point cursor);
51
52@@ -118,6 +123,7 @@
53
54 WindowManagerTools* const tools;
55 std::shared_ptr<shell::DisplayLayout> const display_layout;
56+ std::shared_ptr<graphics::GraphicBufferAllocator> const allocator;
57
58 geometry::Rectangle display_area;
59 geometry::Point old_cursor{};
60
61=== modified file 'examples/server_example_window_management.cpp'
62--- examples/server_example_window_management.cpp 2017-05-08 03:04:26 +0000
63+++ examples/server_example_window_management.cpp 2017-07-19 05:46:21 +0000
64@@ -28,6 +28,8 @@
65 #include "mir/scene/surface_creation_parameters.h"
66 #include "mir/shell/display_layout.h"
67 #include "mir/shell/system_compositor_window_manager.h"
68+#include "mir/graphics/platform.h"
69+#include "mir/graphics/graphic_buffer_allocator.h"
70
71 namespace me = mir::examples;
72 namespace mf = mir::frontend;
73@@ -134,7 +136,10 @@
74 }
75 else if (selection == wm_canonical)
76 {
77- return std::make_shared<CanonicalWindowManager>(focus_controller, server.the_shell_display_layout());
78+ return std::make_shared<CanonicalWindowManager>(
79+ focus_controller,
80+ server.the_shell_display_layout(),
81+ server.the_graphics_platform()->create_buffer_allocator());
82 }
83 else if (selection == wm_system_compositor)
84 {
85
86=== removed file 'include/server/mir/frontend/client_buffers.h'
87--- include/server/mir/frontend/client_buffers.h 2017-05-08 03:04:26 +0000
88+++ include/server/mir/frontend/client_buffers.h 1970-01-01 00:00:00 +0000
89@@ -1,46 +0,0 @@
90-/*
91- * Copyright © 2015 Canonical Ltd.
92- *
93- * This program is free software: you can redistribute it and/or modify
94- * it under the terms of the GNU General Public License version 3 as
95- * published by the Free Software Foundation.
96- *
97- * This program is distributed in the hope that it will be useful,
98- * but WITHOUT ANY WARRANTY; without even the implied warranty of
99- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
100- * GNU General Public License for more details.
101- *
102- * You should have received a copy of the GNU General Public License
103- * along with this program. If not, see <http://www.gnu.org/licenses/>.
104- *
105- * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
106- */
107-
108-#ifndef MIR_FRONTEND_CLIENT_BUFFERS_H_
109-#define MIR_FRONTEND_CLIENT_BUFFERS_H_
110-
111-#include "mir/graphics/buffer_id.h"
112-#include <memory>
113-
114-namespace mir
115-{
116-namespace graphics { class Buffer; }
117-namespace frontend
118-{
119-class ClientBuffers
120-{
121-public:
122- virtual graphics::BufferID add_buffer(std::shared_ptr<graphics::Buffer> const& properties) = 0;
123- virtual void remove_buffer(graphics::BufferID id) = 0;
124- virtual std::shared_ptr<graphics::Buffer> get(graphics::BufferID) const = 0;
125- virtual void send_buffer(graphics::BufferID id) = 0;
126- virtual void receive_buffer(graphics::BufferID id) = 0;
127-
128- ClientBuffers(ClientBuffers const&) = delete;
129- ClientBuffers& operator=(ClientBuffers const&) = delete;
130- virtual ~ClientBuffers() = default;
131- ClientBuffers() = default;
132-};
133-}
134-}
135-#endif /* MIR_FRONTEND_CLIENT_BUFFERS_H_ */
136
137=== modified file 'include/server/mir/frontend/session.h'
138--- include/server/mir/frontend/session.h 2017-05-08 03:04:26 +0000
139+++ include/server/mir/frontend/session.h 2017-07-19 05:46:21 +0000
140@@ -57,12 +57,6 @@
141 virtual BufferStreamId create_buffer_stream(graphics::BufferProperties const& props) = 0;
142 virtual void destroy_buffer_stream(BufferStreamId stream) = 0;
143
144- virtual graphics::BufferID create_buffer(graphics::BufferProperties const& properties) = 0;
145- virtual graphics::BufferID create_buffer(geometry::Size, MirPixelFormat) = 0;
146- virtual graphics::BufferID create_buffer(geometry::Size, uint32_t native_format, uint32_t native_flags) = 0;
147- virtual void destroy_buffer(graphics::BufferID) = 0;
148- virtual std::shared_ptr<graphics::Buffer> get_buffer(graphics::BufferID) = 0;
149-
150 virtual std::string name() const = 0;
151
152 virtual void send_display_config(graphics::DisplayConfiguration const&) = 0;
153
154=== modified file 'include/server/mir/scene/buffer_stream_factory.h'
155--- include/server/mir/scene/buffer_stream_factory.h 2017-05-08 03:04:26 +0000
156+++ include/server/mir/scene/buffer_stream_factory.h 2017-07-19 05:46:21 +0000
157@@ -28,7 +28,6 @@
158 {
159 namespace compositor { class BufferStream; }
160 namespace graphics { struct BufferProperties; }
161-namespace frontend { class ClientBuffers; class BufferSink; }
162 namespace scene
163 {
164 class BufferStreamFactory
165@@ -37,13 +36,12 @@
166 virtual ~BufferStreamFactory() = default;
167
168 virtual std::shared_ptr<compositor::BufferStream> create_buffer_stream(
169- frontend::BufferStreamId, std::shared_ptr<frontend::ClientBuffers> const& sink,
170- int nbuffers, graphics::BufferProperties const& buffer_properties) = 0;
171+ frontend::BufferStreamId,
172+ int nbuffers,
173+ graphics::BufferProperties const& buffer_properties) = 0;
174 virtual std::shared_ptr<compositor::BufferStream> create_buffer_stream(
175- frontend::BufferStreamId, std::shared_ptr<frontend::ClientBuffers> const& sink,
176+ frontend::BufferStreamId,
177 graphics::BufferProperties const& buffer_properties) = 0;
178- virtual std::shared_ptr<frontend::ClientBuffers> create_buffer_map(
179- std::shared_ptr<frontend::BufferSink> const& sink) = 0;
180
181 protected:
182 BufferStreamFactory() = default;
183
184=== modified file 'include/server/mir/scene/session.h'
185--- include/server/mir/scene/session.h 2017-05-08 03:04:26 +0000
186+++ include/server/mir/scene/session.h 2017-07-19 05:46:21 +0000
187@@ -65,12 +65,6 @@
188 virtual void destroy_buffer_stream(frontend::BufferStreamId stream) = 0;
189 virtual void configure_streams(Surface& surface, std::vector<shell::StreamSpecification> const& config) = 0;
190 virtual void destroy_surface(std::weak_ptr<Surface> const& surface) = 0;
191-
192- virtual graphics::BufferID create_buffer(graphics::BufferProperties const& properties) = 0;
193- virtual graphics::BufferID create_buffer(geometry::Size, MirPixelFormat) = 0;
194- virtual graphics::BufferID create_buffer(geometry::Size, uint32_t native_format, uint32_t native_flags) = 0;
195- virtual void destroy_buffer(graphics::BufferID) = 0;
196- virtual std::shared_ptr<graphics::Buffer> get_buffer(graphics::BufferID) = 0;
197 };
198 }
199 }
200
201=== modified file 'include/server/mir/shell/window_management_info.h'
202--- include/server/mir/shell/window_management_info.h 2017-05-08 03:04:26 +0000
203+++ include/server/mir/shell/window_management_info.h 2017-07-19 05:46:21 +0000
204@@ -28,6 +28,10 @@
205 namespace mir
206 {
207 namespace scene { class Session; class Surface; struct SurfaceCreationParameters; }
208+namespace graphics
209+{
210+class GraphicBufferAllocator;
211+}
212 namespace shell
213 {
214 struct SurfaceInfo
215@@ -78,7 +82,7 @@
216 mir::optional_value<graphics::DisplayConfigurationOutputId> output_id;
217 mir::optional_value<MirPointerConfinementState> confine_pointer;
218
219- void init_titlebar(std::shared_ptr<scene::Session> const& session, std::shared_ptr<scene::Surface> const& surface);
220+ void init_titlebar(graphics::GraphicBufferAllocator& allocator, std::shared_ptr<scene::Surface> const& surface);
221 void paint_titlebar(int intensity);
222
223 private:
224
225=== modified file 'include/test/mir/test/doubles/stub_session.h'
226--- include/test/mir/test/doubles/stub_session.h 2017-05-08 03:04:26 +0000
227+++ include/test/mir/test/doubles/stub_session.h 2017-07-19 05:46:21 +0000
228@@ -89,12 +89,6 @@
229
230 void send_input_config(MirInputConfig const& config) override;
231
232- graphics::BufferID create_buffer(graphics::BufferProperties const& properties) override;
233- graphics::BufferID create_buffer(geometry::Size, MirPixelFormat) override;
234- graphics::BufferID create_buffer(geometry::Size, uint32_t native_format, uint32_t native_flags) override;
235- void destroy_buffer(graphics::BufferID) override;
236- std::shared_ptr<graphics::Buffer> get_buffer(graphics::BufferID) override;
237-
238 pid_t pid;
239 };
240 }
241
242=== modified file 'src/client/mir_connection.cpp'
243--- src/client/mir_connection.cpp 2017-07-19 05:46:21 +0000
244+++ src/client/mir_connection.cpp 2017-07-19 05:46:21 +0000
245@@ -1305,7 +1305,6 @@
246 MirBufferCallback callback, void* context)
247 {
248 mp::BufferAllocation request;
249- request.mutable_id()->set_value(-1);
250 auto buffer_request = request.add_buffer_requests();
251 buffer_request->set_width(size.width.as_int());
252 buffer_request->set_height(size.height.as_int());
253
254=== modified file 'src/server/compositor/CMakeLists.txt'
255--- src/server/compositor/CMakeLists.txt 2017-05-08 03:04:26 +0000
256+++ src/server/compositor/CMakeLists.txt 2017-07-19 05:46:21 +0000
257@@ -18,7 +18,6 @@
258 compositing_screencast.cpp
259 stream.cpp
260 multi_monitor_arbiter.cpp
261- buffer_map.cpp
262 dropping_schedule.cpp
263 queueing_schedule.cpp
264 )
265
266=== removed file 'src/server/compositor/buffer_map.cpp'
267--- src/server/compositor/buffer_map.cpp 2017-07-19 05:46:21 +0000
268+++ src/server/compositor/buffer_map.cpp 1970-01-01 00:00:00 +0000
269@@ -1,114 +0,0 @@
270-/*
271- * Copyright © 2015 Canonical Ltd.
272- *
273- * This program is free software: you can redistribute it and/or modify
274- * it under the terms of the GNU General Public License version 3 as
275- * published by the Free Software Foundation.
276- *
277- * This program is distributed in the hope that it will be useful,
278- * but WITHOUT ANY WARRANTY; without even the implied warranty of
279- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
280- * GNU General Public License for more details.
281- *
282- * You should have received a copy of the GNU General Public License
283- * along with this program. If not, see <http://www.gnu.org/licenses/>.
284- *
285- * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
286- */
287-
288-#include "mir/graphics/buffer.h"
289-#include "mir/frontend/buffer_sink.h"
290-#include "buffer_map.h"
291-#include <boost/throw_exception.hpp>
292-#include <algorithm>
293-
294-namespace mc = mir::compositor;
295-namespace mf = mir::frontend;
296-namespace mg = mir::graphics;
297-
298-namespace mir
299-{
300-namespace compositor
301-{
302-enum class BufferMap::Owner
303-{
304- server,
305- client
306-};
307-}
308-}
309-
310-mc::BufferMap::BufferMap(std::shared_ptr<mf::BufferSink> const& sink) :
311- sink(sink)
312-{
313-}
314-
315-mg::BufferID mc::BufferMap::add_buffer(std::shared_ptr<mg::Buffer> const& buffer)
316-{
317- try
318- {
319- std::unique_lock<decltype(mutex)> lk(mutex);
320- buffers[buffer->id()] = {buffer, Owner::client};
321- if (auto s = sink.lock())
322- s->add_buffer(*buffer);
323- return buffer->id();
324- } catch (std::exception& e)
325- {
326- if (auto s = sink.lock())
327- s->error_buffer(buffer->size(), buffer->pixel_format(), e.what());
328- throw;
329- }
330-}
331-
332-void mc::BufferMap::remove_buffer(mg::BufferID id)
333-{
334- std::unique_lock<decltype(mutex)> lk(mutex);
335- auto it = checked_buffers_find(id, lk);
336- buffers.erase(it);
337-}
338-
339-void mc::BufferMap::send_buffer(mg::BufferID id)
340-{
341- std::unique_lock<decltype(mutex)> lk(mutex);
342- auto it = buffers.find(id);
343- if (it != buffers.end())
344- {
345- auto buffer = it->second.buffer;
346- it->second.owner = Owner::client;
347- lk.unlock();
348- if (auto s = sink.lock())
349- s->update_buffer(*buffer);
350- }
351-}
352-
353-void mc::BufferMap::receive_buffer(graphics::BufferID id)
354-{
355- std::unique_lock<decltype(mutex)> lk(mutex);
356- auto it = buffers.find(id);
357- if (it != buffers.end())
358- it->second.owner = Owner::server;
359-}
360-
361-std::shared_ptr<mg::Buffer> mc::BufferMap::get(mg::BufferID id) const
362-{
363- std::unique_lock<decltype(mutex)> lk(mutex);
364- return checked_buffers_find(id, lk)->second.buffer;
365-}
366-
367-mc::BufferMap::Map::iterator mc::BufferMap::checked_buffers_find(
368- mg::BufferID id, std::unique_lock<std::mutex> const&)
369-{
370- auto it = buffers.find(id);
371- if (it == buffers.end())
372- BOOST_THROW_EXCEPTION(std::logic_error("cannot find buffer by id"));
373- return it;
374-}
375-
376-mc::BufferMap::Map::const_iterator mc::BufferMap::checked_buffers_find(
377- mg::BufferID id, std::unique_lock<std::mutex> const&) const
378-{
379- auto it = buffers.find(id);
380- if (it == buffers.end())
381- BOOST_THROW_EXCEPTION(std::logic_error("cannot find buffer by id"));
382- return it;
383-}
384
385=== removed file 'src/server/compositor/buffer_map.h'
386--- src/server/compositor/buffer_map.h 2017-05-08 03:04:26 +0000
387+++ src/server/compositor/buffer_map.h 1970-01-01 00:00:00 +0000
388@@ -1,65 +0,0 @@
389-/*
390- * Copyright © 2015 Canonical Ltd.
391- *
392- * This program is free software: you can redistribute it and/or modify
393- * it under the terms of the GNU General Public License version 3 as
394- * published by the Free Software Foundation.
395- *
396- * This program is distributed in the hope that it will be useful,
397- * but WITHOUT ANY WARRANTY; without even the implied warranty of
398- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
399- * GNU General Public License for more details.
400- *
401- * You should have received a copy of the GNU General Public License
402- * along with this program. If not, see <http://www.gnu.org/licenses/>.
403- *
404- * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
405- */
406-
407-#ifndef MIR_COMPOSITOR_BUFFER_MAP_H_
408-#define MIR_COMPOSITOR_BUFFER_MAP_H_
409-
410-#include "mir/frontend/client_buffers.h"
411-#include <mutex>
412-#include <map>
413-
414-namespace mir
415-{
416-namespace frontend { class BufferSink; }
417-namespace compositor
418-{
419-class BufferMap : public frontend::ClientBuffers
420-{
421-public:
422- BufferMap(std::shared_ptr<frontend::BufferSink> const& sink);
423-
424- graphics::BufferID add_buffer(std::shared_ptr<graphics::Buffer> const& buffer) override;
425- void remove_buffer(graphics::BufferID id) override;
426-
427- void receive_buffer(graphics::BufferID id) override;
428- void send_buffer(graphics::BufferID id) override;
429-
430- std::shared_ptr<graphics::Buffer> get(graphics::BufferID) const override;
431-
432-private:
433- std::mutex mutable mutex;
434-
435- enum class Owner;
436- struct MapEntry
437- {
438- std::shared_ptr<graphics::Buffer> buffer;
439- Owner owner;
440- };
441- typedef std::map<graphics::BufferID, MapEntry> Map;
442- //used to keep strong reference
443- Map buffers;
444- Map::iterator checked_buffers_find(graphics::BufferID, std::unique_lock<std::mutex> const&);
445- Map::const_iterator checked_buffers_find(graphics::BufferID, std::unique_lock<std::mutex> const&) const;
446-
447- //would be better to schedule the async buffer callbacks in the ipc subsystem,
448- //instead of driving from within the compositor threads (LP: #1395421)
449- std::weak_ptr<frontend::BufferSink> const sink;
450-};
451-}
452-}
453-#endif /* MIR_COMPOSITOR_BUFFER_MAP_H_ */
454
455=== modified file 'src/server/compositor/buffer_stream_factory.cpp'
456--- src/server/compositor/buffer_stream_factory.cpp 2017-05-08 03:04:26 +0000
457+++ src/server/compositor/buffer_stream_factory.cpp 2017-07-19 05:46:21 +0000
458@@ -21,7 +21,6 @@
459 #include "buffer_stream_factory.h"
460 #include "mir/graphics/buffer_properties.h"
461 #include "stream.h"
462-#include "buffer_map.h"
463 #include "mir/graphics/buffer.h"
464 #include "mir/graphics/buffer_id.h"
465 #include "mir/graphics/graphic_buffer_allocator.h"
466@@ -40,23 +39,17 @@
467 }
468
469 std::shared_ptr<mc::BufferStream> mc::BufferStreamFactory::create_buffer_stream(
470- mf::BufferStreamId id, std::shared_ptr<mf::ClientBuffers> const& buffers,
471+ mf::BufferStreamId id,
472 mg::BufferProperties const& buffer_properties)
473 {
474- return create_buffer_stream(id, buffers, 0, buffer_properties);
475+ return create_buffer_stream(id, 0, buffer_properties);
476 }
477
478 std::shared_ptr<mc::BufferStream> mc::BufferStreamFactory::create_buffer_stream(
479- mf::BufferStreamId, std::shared_ptr<mf::ClientBuffers> const& buffers,
480- int, mg::BufferProperties const& buffer_properties)
481+ mf::BufferStreamId,
482+ int,
483+ mg::BufferProperties const& buffer_properties)
484 {
485 return std::make_shared<mc::Stream>(
486- buffers,
487 buffer_properties.size, buffer_properties.format);
488 }
489-
490-std::shared_ptr<mf::ClientBuffers> mc::BufferStreamFactory::create_buffer_map(
491- std::shared_ptr<mf::BufferSink> const& sink)
492-{
493- return std::make_shared<mc::BufferMap>(sink);
494-}
495
496=== modified file 'src/server/compositor/buffer_stream_factory.h'
497--- src/server/compositor/buffer_stream_factory.h 2017-05-08 03:04:26 +0000
498+++ src/server/compositor/buffer_stream_factory.h 2017-07-19 05:46:21 +0000
499@@ -42,13 +42,12 @@
500 virtual ~BufferStreamFactory() {}
501
502 virtual std::shared_ptr<compositor::BufferStream> create_buffer_stream(
503- frontend::BufferStreamId, std::shared_ptr<frontend::ClientBuffers> const& sink,
504- int nbuffers, graphics::BufferProperties const& buffer_properties) override;
505+ frontend::BufferStreamId,
506+ int nbuffers,
507+ graphics::BufferProperties const& buffer_properties) override;
508 virtual std::shared_ptr<BufferStream> create_buffer_stream(
509- frontend::BufferStreamId, std::shared_ptr<frontend::ClientBuffers> const& sink,
510+ frontend::BufferStreamId,
511 graphics::BufferProperties const&) override;
512- virtual std::shared_ptr<frontend::ClientBuffers> create_buffer_map(
513- std::shared_ptr<frontend::BufferSink> const& sink) override;
514 };
515
516 }
517
518=== modified file 'src/server/compositor/dropping_schedule.cpp'
519--- src/server/compositor/dropping_schedule.cpp 2017-05-08 03:04:26 +0000
520+++ src/server/compositor/dropping_schedule.cpp 2017-07-19 05:46:21 +0000
521@@ -17,16 +17,13 @@
522 */
523
524 #include "dropping_schedule.h"
525-#include "mir/frontend/client_buffers.h"
526 #include "mir/graphics/buffer.h"
527
528 #include <boost/throw_exception.hpp>
529-namespace mf = mir::frontend;
530 namespace mg = mir::graphics;
531 namespace mc = mir::compositor;
532
533-mc::DroppingSchedule::DroppingSchedule(std::shared_ptr<mf::ClientBuffers> const& client_buffers) :
534- sender(client_buffers)
535+mc::DroppingSchedule::DroppingSchedule()
536 {
537 }
538
539@@ -42,14 +39,6 @@
540 {
541 std::future<void> drop;
542 std::lock_guard<decltype(mutex)> lk(mutex);
543- if ((the_only_buffer != buffer) && the_only_buffer)
544- {
545- drop = std::async(std::launch::deferred,
546- [sender=sender, dropped=the_only_buffer]()
547- {
548- sender->send_buffer(dropped->id());
549- });
550- }
551 the_only_buffer = buffer;
552 return drop;
553 }
554
555=== modified file 'src/server/compositor/dropping_schedule.h'
556--- src/server/compositor/dropping_schedule.h 2017-05-08 03:04:26 +0000
557+++ src/server/compositor/dropping_schedule.h 2017-07-19 05:46:21 +0000
558@@ -25,13 +25,12 @@
559 namespace mir
560 {
561 namespace graphics { class Buffer; }
562-namespace frontend { class ClientBuffers; }
563 namespace compositor
564 {
565 class DroppingSchedule : public Schedule
566 {
567 public:
568- DroppingSchedule(std::shared_ptr<frontend::ClientBuffers> const&);
569+ DroppingSchedule();
570 void schedule(std::shared_ptr<graphics::Buffer> const& buffer) override;
571 std::future<void> schedule_nonblocking(
572 std::shared_ptr<graphics::Buffer> const& buffer) override;
573@@ -40,7 +39,6 @@
574
575 private:
576 std::mutex mutable mutex;
577- std::shared_ptr<frontend::ClientBuffers> const sender;
578 std::shared_ptr<graphics::Buffer> the_only_buffer;
579 };
580 }
581
582=== modified file 'src/server/compositor/multi_monitor_arbiter.cpp'
583--- src/server/compositor/multi_monitor_arbiter.cpp 2017-05-26 12:45:45 +0000
584+++ src/server/compositor/multi_monitor_arbiter.cpp 2017-07-19 05:46:21 +0000
585@@ -20,7 +20,6 @@
586 #include "mir/graphics/buffer.h"
587 #include "mir/graphics/graphic_buffer_allocator.h"
588 #include "mir/frontend/event_sink.h"
589-#include "mir/frontend/client_buffers.h"
590 #include "schedule.h"
591 #include <boost/throw_exception.hpp>
592 #include <algorithm>
593@@ -30,9 +29,7 @@
594 namespace mf = mir::frontend;
595
596 mc::MultiMonitorArbiter::MultiMonitorArbiter(
597- std::shared_ptr<frontend::ClientBuffers> const& map,
598 std::shared_ptr<Schedule> const& schedule) :
599- map(map),
600 schedule(schedule)
601 {
602 }
603@@ -43,7 +40,7 @@
604 for(auto it = onscreen_buffers.begin(); it != onscreen_buffers.end(); it++)
605 {
606 if (it->use_count == 0)
607- map->send_buffer(it->buffer->id());
608+ it->buffer.reset();
609 }
610
611 }
612@@ -96,7 +93,6 @@
613 if ((it->use_count == 0) &&
614 (it != onscreen_buffers.begin() || schedule->num_scheduled())) //ensure monitors always have a buffer
615 {
616- map->send_buffer(it->buffer->id());
617 it = onscreen_buffers.erase(it);
618 }
619 else
620
621=== modified file 'src/server/compositor/multi_monitor_arbiter.h'
622--- src/server/compositor/multi_monitor_arbiter.h 2017-05-25 05:49:36 +0000
623+++ src/server/compositor/multi_monitor_arbiter.h 2017-07-19 05:46:21 +0000
624@@ -38,7 +38,6 @@
625 {
626 public:
627 MultiMonitorArbiter(
628- std::shared_ptr<frontend::ClientBuffers> const& map,
629 std::shared_ptr<Schedule> const& schedule);
630 ~MultiMonitorArbiter();
631
632@@ -56,7 +55,6 @@
633 void clean_onscreen_buffers(std::lock_guard<std::mutex> const&);
634
635 std::mutex mutable mutex;
636- std::shared_ptr<frontend::ClientBuffers> const map;
637 struct ScheduleEntry
638 {
639 ScheduleEntry(std::shared_ptr<graphics::Buffer> const& buffer, unsigned int use_count) :
640
641=== modified file 'src/server/compositor/stream.cpp'
642--- src/server/compositor/stream.cpp 2017-05-25 05:49:36 +0000
643+++ src/server/compositor/stream.cpp 2017-07-19 05:46:21 +0000
644@@ -21,7 +21,6 @@
645 #include "queueing_schedule.h"
646 #include "dropping_schedule.h"
647 #include "temporary_buffers.h"
648-#include "mir/frontend/client_buffers.h"
649 #include "mir/graphics/buffer.h"
650 #include <boost/throw_exception.hpp>
651
652@@ -37,22 +36,17 @@
653 };
654
655 mc::Stream::Stream(
656- std::shared_ptr<frontend::ClientBuffers> map, geom::Size size, MirPixelFormat pf) :
657+ geom::Size size, MirPixelFormat pf) :
658 schedule_mode(ScheduleMode::Queueing),
659 schedule(std::make_shared<mc::QueueingSchedule>()),
660- buffers(map),
661- arbiter(std::make_shared<mc::MultiMonitorArbiter>(buffers, schedule)),
662+ arbiter(std::make_shared<mc::MultiMonitorArbiter>(schedule)),
663 size(size),
664 pf(pf),
665 first_frame_posted(false)
666 {
667 }
668
669-mc::Stream::~Stream()
670-{
671- while(schedule->num_scheduled())
672- buffers->send_buffer(schedule->next_buffer()->id());
673-}
674+mc::Stream::~Stream() = default;
675
676 unsigned int mc::Stream::client_owned_buffer_count(std::lock_guard<decltype(mutex)> const&) const
677 {
678@@ -72,9 +66,8 @@
679 {
680 std::lock_guard<decltype(mutex)> lk(mutex);
681 first_frame_posted = true;
682- buffers->receive_buffer(buffer->id());
683- deferred_io = schedule->schedule_nonblocking(buffers->get(buffer->id()));
684 pf = buffer->pixel_format();
685+ deferred_io = schedule->schedule_nonblocking(buffer);
686 }
687 observers.frame_posted(1, buffer->size());
688
689@@ -134,7 +127,7 @@
690 std::lock_guard<decltype(mutex)> lk(mutex);
691 if (dropping && schedule_mode == ScheduleMode::Queueing)
692 {
693- transition_schedule(std::make_shared<mc::DroppingSchedule>(buffers), lk);
694+ transition_schedule(std::make_shared<mc::DroppingSchedule>(), lk);
695 schedule_mode = ScheduleMode::Dropping;
696 }
697 else if (!dropping && schedule_mode == ScheduleMode::Dropping)
698@@ -182,9 +175,6 @@
699 transferred_buffers.pop_back();
700 }
701
702- for (auto &buffer : transferred_buffers)
703- buffers->send_buffer(buffer->id());
704-
705 arbiter->advance_schedule();
706 }
707
708@@ -214,15 +204,7 @@
709
710 bool mc::Stream::suitable_for_cursor() const
711 {
712- if (associated_buffers.empty())
713- {
714- return true;
715- }
716- else
717- {
718- for (auto it : associated_buffers)
719- if (buffers->get(it)->pixel_format() != mir_pixel_format_argb_8888)
720- return false;
721- }
722+ // We can't reasonably answer this question -
723+ // Suitability for cursor use is a per-buffer property, not a per-stream property.
724 return true;
725 }
726
727=== modified file 'src/server/compositor/stream.h'
728--- src/server/compositor/stream.h 2017-05-22 11:53:51 +0000
729+++ src/server/compositor/stream.h 2017-07-19 05:46:21 +0000
730@@ -39,7 +39,7 @@
731 class Stream : public BufferStream
732 {
733 public:
734- Stream(std::shared_ptr<frontend::ClientBuffers>, geometry::Size sz, MirPixelFormat format);
735+ Stream(geometry::Size sz, MirPixelFormat format);
736 ~Stream();
737
738 void submit_buffer(std::shared_ptr<graphics::Buffer> const& buffer) override;
739@@ -68,7 +68,6 @@
740 std::mutex mutable mutex;
741 ScheduleMode schedule_mode;
742 std::shared_ptr<Schedule> schedule;
743- std::shared_ptr<frontend::ClientBuffers> const buffers;
744 std::shared_ptr<MultiMonitorArbiter> const arbiter;
745 geometry::Size size;
746 MirPixelFormat pf;
747
748=== modified file 'src/server/frontend/default_ipc_factory.cpp'
749--- src/server/frontend/default_ipc_factory.cpp 2017-05-08 03:04:26 +0000
750+++ src/server/frontend/default_ipc_factory.cpp 2017-07-19 05:46:21 +0000
751@@ -26,6 +26,7 @@
752 #include "resource_cache.h"
753 #include "mir/frontend/session_authorizer.h"
754 #include "mir/frontend/event_sink.h"
755+#include "event_sink_factory.h"
756 #include "mir/graphics/graphic_buffer_allocator.h"
757 #include "mir/cookie/authority.h"
758
759@@ -150,5 +151,6 @@
760 anr_detector,
761 cookie_authority,
762 input_changer,
763- extensions);
764+ extensions,
765+ buffer_allocator);
766 }
767
768=== modified file 'src/server/frontend/session_mediator.cpp'
769--- src/server/frontend/session_mediator.cpp 2017-06-01 13:04:37 +0000
770+++ src/server/frontend/session_mediator.cpp 2017-07-19 05:46:21 +0000
771@@ -59,6 +59,7 @@
772 #include "mir/fd.h"
773 #include "mir/cookie/authority.h"
774 #include "mir/module_properties.h"
775+#include "mir/graphics/graphic_buffer_allocator.h"
776
777 #include "mir/geometry/rectangles.h"
778 #include "protobuf_buffer_packer.h"
779@@ -110,7 +111,8 @@
780 std::shared_ptr<scene::ApplicationNotRespondingDetector> const& anr_detector,
781 std::shared_ptr<mir::cookie::Authority> const& cookie_authority,
782 std::shared_ptr<mf::InputConfigurationChanger> const& input_changer,
783- std::vector<mir::ExtensionDescription> const& extensions) :
784+ std::vector<mir::ExtensionDescription> const& extensions,
785+ std::shared_ptr<mg::GraphicBufferAllocator> const& allocator) :
786 client_pid_(0),
787 shell(shell),
788 ipc_operations(ipc_operations),
789@@ -128,7 +130,8 @@
790 anr_detector{anr_detector},
791 cookie_authority(cookie_authority),
792 input_changer(input_changer),
793- extensions(extensions)
794+ extensions(extensions),
795+ allocator{allocator}
796 {
797 }
798
799@@ -374,6 +377,58 @@
800 buffering_sender->uncork();
801 }
802
803+namespace
804+{
805+ class AutoSendBuffer : public mg::Buffer
806+ {
807+ public:
808+ AutoSendBuffer(
809+ std::shared_ptr<mg::Buffer> const& wrapped,
810+ std::weak_ptr<mf::BufferSink> const& sink)
811+ : buffer{wrapped},
812+ sink{sink}
813+ {
814+ }
815+ ~AutoSendBuffer()
816+ {
817+ if (auto live_sink = sink.lock())
818+ {
819+ live_sink->update_buffer(*buffer);
820+ }
821+ }
822+
823+ std::shared_ptr<mir::graphics::NativeBuffer> native_buffer_handle() const override
824+ {
825+ return buffer->native_buffer_handle();
826+ }
827+
828+ mir::graphics::BufferID id() const override
829+ {
830+ return buffer->id();
831+ }
832+
833+ mir::geometry::Size size() const override
834+ {
835+ return buffer->size();
836+ }
837+
838+ MirPixelFormat pixel_format() const override
839+ {
840+ return buffer->pixel_format();
841+ }
842+
843+ mir::graphics::NativeBufferBase *native_buffer_base() override
844+ {
845+ return buffer->native_buffer_base();
846+ }
847+
848+ private:
849+ std::shared_ptr<mg::Buffer> const buffer;
850+ std::weak_ptr<mf::BufferSink> const sink;
851+ };
852+
853+}
854+
855 void mf::SessionMediator::submit_buffer(
856 mir::protobuf::BufferRequest const* request,
857 mir::protobuf::Void*,
858@@ -388,15 +443,37 @@
859 auto stream = session->get_buffer_stream(stream_id);
860
861 mfd::ProtobufBufferPacker request_msg{const_cast<mir::protobuf::Buffer*>(&request->buffer())};
862- auto b = session->get_buffer(buffer_id);
863+ auto b = buffer_cache.at(buffer_id);
864 ipc_operations->unpack_buffer(request_msg, *b);
865
866- stream->submit_buffer(b);
867+ stream->submit_buffer(std::make_shared<AutoSendBuffer>(b, event_sink));
868
869 done->Run();
870 }
871
872-void mf::SessionMediator::allocate_buffers(
873+namespace
874+{
875+bool validate_buffer_request(mir::protobuf::BufferStreamParameters const& req)
876+{
877+ // A valid buffer request has either flags & native_format set
878+ // or buffer_usage & pixel_format set, not both.
879+ return
880+ (
881+ req.has_pixel_format() &&
882+ req.has_buffer_usage() &&
883+ !req.has_native_format() &&
884+ !req.has_flags()
885+ ) ||
886+ (
887+ !req.has_pixel_format() &&
888+ !req.has_buffer_usage() &&
889+ req.has_native_format() &&
890+ req.has_flags()
891+ );
892+}
893+}
894+
895+void mf::SessionMediator::allocate_buffers(
896 mir::protobuf::BufferAllocation const* request,
897 mir::protobuf::Void*,
898 google::protobuf::Closure* done)
899@@ -409,36 +486,54 @@
900 for (auto i = 0; i < request->buffer_requests().size(); i++)
901 {
902 auto const& req = request->buffer_requests(i);
903+ std::shared_ptr<mg::Buffer> buffer;
904+ try
905+ {
906+ if (!validate_buffer_request(req))
907+ {
908+ BOOST_THROW_EXCEPTION(std::logic_error("Invalid buffer request"));
909+ }
910
911- mg::BufferID id;
912- if (req.has_flags() && req.has_native_format())
913- {
914- id = session->create_buffer({req.width(), req.height()}, req.native_format(), req.flags());
915- }
916- else if (req.has_buffer_usage() && req.has_pixel_format())
917- {
918- auto const usage = static_cast<mg::BufferUsage>(req.buffer_usage());
919- geom::Size const size{req.width(), req.height()};
920- auto const pf = static_cast<MirPixelFormat>(req.pixel_format());
921- if (usage == mg::BufferUsage::software)
922+ if (req.has_flags() && req.has_native_format())
923 {
924- id = session->create_buffer(size, pf);
925+ buffer = allocator->alloc_buffer(
926+ {req.width(), req.height()},
927+ req.native_format(),
928+ req.flags());
929 }
930 else
931 {
932- //legacy route, server-selected pf and usage
933- id = session->create_buffer(mg::BufferProperties{size, pf, mg::BufferUsage::hardware});
934- }
935- }
936- else
937- {
938- BOOST_THROW_EXCEPTION(std::logic_error("Invalid buffer request"));
939- }
940-
941- if (request->has_id())
942- {
943- auto stream = session->get_buffer_stream(mf::BufferStreamId(request->id().value()));
944- stream->associate_buffer(id);
945+ auto const usage = static_cast<mg::BufferUsage>(req.buffer_usage());
946+ geom::Size const size{req.width(), req.height()};
947+ auto const pf = static_cast<MirPixelFormat>(req.pixel_format());
948+ if (usage == mg::BufferUsage::software)
949+ {
950+ buffer = allocator->alloc_software_buffer(size, pf);
951+ }
952+ else
953+ {
954+ //legacy route, server-selected pf and usage
955+ buffer =
956+ allocator->alloc_buffer(mg::BufferProperties{size, pf, mg::BufferUsage::hardware});
957+ }
958+ }
959+
960+ if (request->has_id())
961+ {
962+ auto stream = session->get_buffer_stream(mf::BufferStreamId(request->id().value()));
963+ stream->associate_buffer(buffer->id());
964+ }
965+
966+ // TODO: Throw if insert fails (duplicate ID)?
967+ buffer_cache.insert(std::make_pair(buffer->id(), buffer));
968+ event_sink->add_buffer(*buffer);
969+ }
970+ catch (std::exception const& err)
971+ {
972+ event_sink->error_buffer(
973+ geom::Size{req.width(), req.height()},
974+ static_cast<MirPixelFormat>(req.pixel_format()),
975+ err.what());
976 }
977 }
978 done->Run();
979@@ -473,7 +568,7 @@
980 for (auto i = 0; i < request->buffers().size(); i++)
981 {
982 mg::BufferID buffer_id{static_cast<uint32_t>(request->buffers(i).buffer_id())};
983- session->destroy_buffer(buffer_id);
984+ buffer_cache.erase(buffer_id);
985 }
986 done->Run();
987 }
988@@ -869,7 +964,7 @@
989 {
990 auto session = weak_session.lock();
991 ScreencastSessionId const screencast_session_id{request->id().value()};
992- auto buffer = session->get_buffer(mg::BufferID{request->buffer_id()});
993+ auto buffer = buffer_cache.at(mg::BufferID{request->buffer_id()});
994 screencast->capture(screencast_session_id, buffer);
995 done->Run();
996 }
997
998=== modified file 'src/server/frontend/session_mediator.h'
999--- src/server/frontend/session_mediator.h 2017-05-08 03:04:26 +0000
1000+++ src/server/frontend/session_mediator.h 2017-07-19 05:46:21 +0000
1001@@ -28,6 +28,7 @@
1002 #include "mir/frontend/surface_id.h"
1003 #include "mir/frontend/buffer_stream_id.h"
1004 #include "mir/graphics/platform_ipc_operations.h"
1005+#include "mir/graphics/buffer_id.h"
1006 #include "mir/protobuf/display_server_debug.h"
1007 #include "mir_toolkit/common.h"
1008
1009@@ -77,6 +78,7 @@
1010 class PromptSession;
1011 class BufferStream;
1012 class InputConfigurationChanger;
1013+class BufferMap;
1014
1015 namespace detail
1016 {
1017@@ -124,8 +126,8 @@
1018 std::shared_ptr<scene::ApplicationNotRespondingDetector> const& anr_detector,
1019 std::shared_ptr<cookie::Authority> const& cookie_authority,
1020 std::shared_ptr<InputConfigurationChanger> const& input_changer,
1021- std::vector<mir::ExtensionDescription> const& extensions
1022- );
1023+ std::vector<mir::ExtensionDescription> const& extensions,
1024+ std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator);
1025
1026 ~SessionMediator() noexcept;
1027
1028@@ -299,6 +301,8 @@
1029 std::shared_ptr<cookie::Authority> const cookie_authority;
1030 std::shared_ptr<InputConfigurationChanger> const input_changer;
1031 std::vector<mir::ExtensionDescription> const extensions;
1032+ std::unordered_map<graphics::BufferID, std::shared_ptr<graphics::Buffer>> buffer_cache;
1033+ std::shared_ptr<graphics::GraphicBufferAllocator> const allocator;
1034
1035 ScreencastBufferTracker screencast_buffer_tracker;
1036
1037
1038=== modified file 'src/server/scene/application_session.cpp'
1039--- src/server/scene/application_session.cpp 2017-05-25 08:58:03 +0000
1040+++ src/server/scene/application_session.cpp 2017-07-19 05:46:21 +0000
1041@@ -20,7 +20,6 @@
1042 #include "snapshot_strategy.h"
1043 #include "default_session_container.h"
1044 #include "output_properties_cache.h"
1045-#include "../compositor/buffer_map.h"
1046
1047 #include "mir/scene/surface.h"
1048 #include "mir/scene/surface_event_source.h"
1049@@ -68,7 +67,6 @@
1050 snapshot_strategy(snapshot_strategy),
1051 session_listener(session_listener),
1052 event_sink(sink),
1053- buffers(buffer_stream_factory->create_buffer_map(sink)),
1054 gralloc(gralloc),
1055 next_surface_id(0)
1056 {
1057@@ -372,7 +370,7 @@
1058 mf::BufferStreamId ms::ApplicationSession::create_buffer_stream(mg::BufferProperties const& props)
1059 {
1060 auto const id = static_cast<mf::BufferStreamId>(next_id().as_value());
1061- auto stream = buffer_stream_factory->create_buffer_stream(id, buffers, props);
1062+ auto stream = buffer_stream_factory->create_buffer_stream(id, props);
1063
1064 std::unique_lock<std::mutex> lock(surfaces_and_streams_mutex);
1065 streams[id] = stream;
1066@@ -429,56 +427,6 @@
1067 surface_stack->remove_surface(surface);
1068 }
1069
1070-mg::BufferID ms::ApplicationSession::create_buffer(mg::BufferProperties const& properties)
1071-{
1072- try
1073- {
1074- return buffers->add_buffer(gralloc->alloc_buffer(properties));
1075- }
1076- catch (std::exception& e)
1077- {
1078- event_sink->error_buffer(properties.size, properties.format, e.what());
1079- throw;
1080- }
1081-}
1082-
1083-mg::BufferID ms::ApplicationSession::create_buffer(mir::geometry::Size size, MirPixelFormat format)
1084-{
1085- try
1086- {
1087- return buffers->add_buffer(gralloc->alloc_software_buffer(size, format));
1088- }
1089- catch (std::exception& e)
1090- {
1091- event_sink->error_buffer(size, format, e.what());
1092- throw;
1093- }
1094-}
1095-
1096-mg::BufferID ms::ApplicationSession::create_buffer(
1097- mir::geometry::Size size, uint32_t native_format, uint32_t native_flags)
1098-{
1099- try
1100- {
1101- return buffers->add_buffer(gralloc->alloc_buffer(size, native_format, native_flags));
1102- }
1103- catch (std::exception& e)
1104- {
1105- event_sink->error_buffer(size, static_cast<MirPixelFormat>(native_format), e.what());
1106- throw;
1107- }
1108-}
1109-
1110-void ms::ApplicationSession::destroy_buffer(mg::BufferID id)
1111-{
1112- buffers->remove_buffer(id);
1113-}
1114-
1115-std::shared_ptr<mg::Buffer> ms::ApplicationSession::get_buffer(mg::BufferID id)
1116-{
1117- return buffers->get(id);
1118-}
1119-
1120 void ms::ApplicationSession::send_error(mir::ClientVisibleError const& error)
1121 {
1122 event_sink->handle_error(error);
1123
1124=== modified file 'src/server/scene/application_session.h'
1125--- src/server/scene/application_session.h 2017-05-08 03:04:26 +0000
1126+++ src/server/scene/application_session.h 2017-07-19 05:46:21 +0000
1127@@ -100,12 +100,6 @@
1128 void destroy_buffer_stream(frontend::BufferStreamId stream) override;
1129 void configure_streams(Surface& surface, std::vector<shell::StreamSpecification> const& config) override;
1130 void destroy_surface(std::weak_ptr<Surface> const& surface) override;
1131-
1132- graphics::BufferID create_buffer(graphics::BufferProperties const& properties) override;
1133- graphics::BufferID create_buffer(geometry::Size, MirPixelFormat) override;
1134- graphics::BufferID create_buffer(geometry::Size, uint32_t native_format, uint32_t native_flags) override;
1135- void destroy_buffer(graphics::BufferID) override;
1136- std::shared_ptr<graphics::Buffer> get_buffer(graphics::BufferID) override;
1137 protected:
1138 ApplicationSession(ApplicationSession const&) = delete;
1139 ApplicationSession& operator=(ApplicationSession const&) = delete;
1140@@ -119,7 +113,6 @@
1141 std::shared_ptr<SnapshotStrategy> const snapshot_strategy;
1142 std::shared_ptr<SessionListener> const session_listener;
1143 std::shared_ptr<frontend::EventSink> const event_sink;
1144- std::shared_ptr<frontend::ClientBuffers> const buffers;
1145 std::shared_ptr<graphics::GraphicBufferAllocator> const gralloc;
1146
1147 frontend::SurfaceId next_id();
1148
1149=== modified file 'src/server/shell/window_management_info.cpp'
1150--- src/server/shell/window_management_info.cpp 2017-05-08 03:04:26 +0000
1151+++ src/server/shell/window_management_info.cpp 2017-07-19 05:46:21 +0000
1152@@ -24,6 +24,7 @@
1153
1154 #include "mir/graphics/buffer.h"
1155 #include "mir/renderer/sw/pixel_source.h"
1156+#include "mir/graphics/graphic_buffer_allocator.h"
1157
1158 #include <atomic>
1159
1160@@ -173,54 +174,40 @@
1161 {
1162 AllocatingPainter(
1163 std::shared_ptr<frontend::BufferStream> const& buffer_stream,
1164- std::shared_ptr<scene::Session> const& session,
1165+ mg::GraphicBufferAllocator& allocator,
1166 Size size) :
1167 buffer_stream(buffer_stream),
1168- session(session),
1169- properties({
1170- size,
1171- buffer_stream->pixel_format(),
1172- mg::BufferUsage::software
1173- }),
1174- front_buffer(session->create_buffer(properties)),
1175- back_buffer(session->create_buffer(properties))
1176+ front_buffer{allocator.alloc_software_buffer(size, buffer_stream->pixel_format())},
1177+ back_buffer{allocator.alloc_software_buffer(size, buffer_stream->pixel_format())}
1178 {
1179 }
1180
1181 void paint(int intensity) override
1182 {
1183- auto buffer = session->get_buffer(back_buffer);
1184-
1185- auto const format = buffer->pixel_format();
1186- auto const sz = buffer->size().height.as_int() *
1187- buffer->size().width.as_int() * MIR_BYTES_PER_PIXEL(format);
1188+ auto const format = back_buffer->pixel_format();
1189+ auto const sz = back_buffer->size().height.as_int() *
1190+ back_buffer->size().width.as_int() * MIR_BYTES_PER_PIXEL(format);
1191 std::vector<unsigned char> pixels(sz, intensity);
1192- if (auto pixel_source = dynamic_cast<mrs::PixelSource*>(buffer->native_buffer_base()))
1193+ if (auto pixel_source = dynamic_cast<mrs::PixelSource*>(back_buffer->native_buffer_base()))
1194 pixel_source->write(pixels.data(), sz);
1195- buffer_stream->submit_buffer(buffer);
1196+ buffer_stream->submit_buffer(back_buffer);
1197
1198 std::swap(front_buffer, back_buffer);
1199 }
1200
1201- ~AllocatingPainter()
1202- {
1203- session->destroy_buffer(front_buffer);
1204- session->destroy_buffer(back_buffer);
1205- }
1206-
1207 std::shared_ptr<frontend::BufferStream> const buffer_stream;
1208 std::shared_ptr<scene::Session> const session;
1209 mg::BufferProperties properties;
1210- mg::BufferID front_buffer;
1211- mg::BufferID back_buffer;
1212+ std::shared_ptr<mg::Buffer> front_buffer;
1213+ std::shared_ptr<mg::Buffer> back_buffer;
1214 };
1215
1216 void msh::SurfaceInfo::init_titlebar(
1217- std::shared_ptr<scene::Session> const& session,
1218+ mg::GraphicBufferAllocator& allocator,
1219 std::shared_ptr<scene::Surface> const& surface)
1220 {
1221 auto stream = surface->primary_buffer_stream();
1222- stream_painter = std::make_shared<AllocatingPainter>(stream, session, surface->size());
1223+ stream_painter = std::make_shared<AllocatingPainter>(stream, allocator, surface->size());
1224 }
1225
1226 void msh::SurfaceInfo::paint_titlebar(int intensity)
1227
1228=== modified file 'tests/include/mir/test/doubles/stub_buffer_stream_factory.h'
1229--- tests/include/mir/test/doubles/stub_buffer_stream_factory.h 2017-05-08 03:04:26 +0000
1230+++ tests/include/mir/test/doubles/stub_buffer_stream_factory.h 2017-07-19 05:46:21 +0000
1231@@ -19,7 +19,6 @@
1232 #ifndef MIR_TEST_DOUBLES_STUB_BUFFER_STREAM_FACTORY_H_
1233 #define MIR_TEST_DOUBLES_STUB_BUFFER_STREAM_FACTORY_H_
1234
1235-#include "mir/frontend/client_buffers.h"
1236 #include "mir/scene/buffer_stream_factory.h"
1237 #include "stub_buffer_stream.h"
1238
1239@@ -30,40 +29,20 @@
1240 namespace doubles
1241 {
1242
1243-struct StubClientBuffers : frontend::ClientBuffers
1244-{
1245- graphics::BufferID add_buffer(std::shared_ptr<graphics::Buffer> const&) override
1246- {
1247- return {};
1248- }
1249- void remove_buffer(graphics::BufferID) override
1250- {
1251- }
1252- std::shared_ptr<graphics::Buffer> get(graphics::BufferID) const override
1253- {
1254- return buffer;
1255- }
1256- void send_buffer(graphics::BufferID) override
1257- {
1258- }
1259- void receive_buffer(graphics::BufferID) override
1260- {
1261- }
1262- std::shared_ptr<graphics::Buffer> buffer;
1263-};
1264-
1265 struct StubBufferStreamFactory : public scene::BufferStreamFactory
1266 {
1267 std::shared_ptr<compositor::BufferStream> create_buffer_stream(
1268- frontend::BufferStreamId i, std::shared_ptr<frontend::ClientBuffers> const& s,
1269- int, graphics::BufferProperties const& p) { return create_buffer_stream(i, s, p); }
1270+ frontend::BufferStreamId i,
1271+ int,
1272+ graphics::BufferProperties const& p)
1273+ {
1274+ return create_buffer_stream(i, p);
1275+ }
1276 std::shared_ptr<compositor::BufferStream> create_buffer_stream(
1277- frontend::BufferStreamId, std::shared_ptr<frontend::ClientBuffers> const&,
1278- graphics::BufferProperties const&) { return std::make_shared<StubBufferStream>(); }
1279- std::shared_ptr<frontend::ClientBuffers> create_buffer_map(
1280- std::shared_ptr<frontend::BufferSink> const&)
1281+ frontend::BufferStreamId,
1282+ graphics::BufferProperties const&)
1283 {
1284- return std::make_shared<StubClientBuffers>();
1285+ return std::make_shared<StubBufferStream>();
1286 }
1287 };
1288 }
1289
1290=== modified file 'tests/integration-tests/compositor/test_swapping_swappers.cpp'
1291--- tests/integration-tests/compositor/test_swapping_swappers.cpp 2017-05-08 03:04:26 +0000
1292+++ tests/integration-tests/compositor/test_swapping_swappers.cpp 2017-07-19 05:46:21 +0000
1293@@ -19,7 +19,6 @@
1294 #include "multithread_harness.h"
1295
1296 #include "src/server/compositor/stream.h"
1297-#include "src/server/compositor/buffer_map.h"
1298 #include "mir/graphics/graphic_buffer_allocator.h"
1299
1300 #include <gmock/gmock.h>
1301@@ -30,6 +29,7 @@
1302 #include <atomic>
1303
1304 namespace mc = mir::compositor;
1305+namespace mf = mir::frontend;
1306 namespace mg = mir::graphics;
1307 namespace mt = mir::testing;
1308 namespace geom = mir::geometry;
1309@@ -42,7 +42,6 @@
1310 void SetUp()
1311 {
1312 stream = std::make_shared<mc::Stream>(
1313- std::make_shared<mc::BufferMap>(nullptr),
1314 geom::Size{380, 210}, mir_pixel_format_abgr_8888);
1315 }
1316
1317
1318=== modified file 'tests/integration-tests/test_buffer_scheduling.cpp'
1319--- tests/integration-tests/test_buffer_scheduling.cpp 2017-05-25 05:49:36 +0000
1320+++ tests/integration-tests/test_buffer_scheduling.cpp 2017-07-19 05:46:21 +0000
1321@@ -16,17 +16,15 @@
1322 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
1323 */
1324
1325-#include "mir/frontend/client_buffers.h"
1326 #include "mir/frontend/event_sink.h"
1327 #include "mir/frontend/buffer_sink.h"
1328 #include "mir/renderer/sw/pixel_source.h"
1329 #include "src/client/buffer_vault.h"
1330 #include "src/client/buffer_factory.h"
1331-#include "src/client/buffer_factory.h"
1332 #include "src/client/protobuf_to_native_buffer.h"
1333 #include "src/client/connection_surface_map.h"
1334 #include "src/server/compositor/stream.h"
1335-#include "src/server/compositor/buffer_map.h"
1336+#include "src/server/compositor/temporary_buffers.h"
1337 #include "mir/test/doubles/stub_client_buffer_factory.h"
1338 #include "mir/test/doubles/mock_client_buffer_factory.h"
1339 #include "mir/test/doubles/stub_buffer_allocator.h"
1340@@ -48,12 +46,6 @@
1341 namespace
1342 {
1343
1344-enum class TestType
1345-{
1346- ExchangeSemantics,
1347- SubmitSemantics
1348-};
1349-
1350 enum class Access
1351 {
1352 blocked,
1353@@ -462,6 +454,24 @@
1354 return never_blocks;
1355 }
1356
1357+class AutoSendBuffer : public mc::TemporaryBuffer
1358+{
1359+public:
1360+ AutoSendBuffer(
1361+ std::shared_ptr<mg::Buffer> const& wrapped,
1362+ std::shared_ptr<mf::BufferSink> const& sink)
1363+ : TemporaryBuffer(wrapped),
1364+ sink{sink}
1365+ {
1366+ }
1367+
1368+ ~AutoSendBuffer()
1369+ {
1370+ sink->update_buffer(*buffer);
1371+ }
1372+private:
1373+ std::shared_ptr<mf::BufferSink> const sink;
1374+};
1375
1376 //test infrastructure
1377 struct BufferScheduling : public Test, ::testing::WithParamInterface<int>
1378@@ -470,9 +480,7 @@
1379 {
1380 ipc = std::make_shared<StubIpcSystem>();
1381 sink = std::make_shared<StubEventSink>(ipc);
1382- map = std::make_shared<mc::BufferMap>(sink);
1383 auto submit_stream = std::make_shared<mc::Stream>(
1384- map,
1385 geom::Size{100,100},
1386 mir_pixel_format_abgr_8888);
1387 auto weak_stream = std::weak_ptr<mc::Stream>(submit_stream);
1388@@ -483,12 +491,15 @@
1389 if (!submit_stream)
1390 return;
1391 mg::BufferID id{static_cast<unsigned int>(buffer.buffer_id())};
1392- submit_stream->submit_buffer(map->get(id));
1393+ submit_stream->submit_buffer(
1394+ std::make_shared<AutoSendBuffer>(map.at(id), sink));
1395 });
1396 ipc->on_allocate(
1397 [this](geom::Size sz)
1398 {
1399- map->add_buffer(std::make_shared<mtd::StubBuffer>(sz));
1400+ auto const buffer = std::make_shared<mtd::StubBuffer>(sz);
1401+ map[buffer->id()] = buffer;
1402+ sink->add_buffer(*buffer);
1403 });
1404
1405 consumer = std::make_unique<ScheduledConsumer>(submit_stream);
1406@@ -529,7 +540,7 @@
1407 std::unique_ptr<ConsumerSystem> consumer;
1408 std::unique_ptr<ConsumerSystem> second_consumer;
1409 std::unique_ptr<ConsumerSystem> third_consumer;
1410- std::shared_ptr<mc::BufferMap> map;
1411+ std::unordered_map<mg::BufferID, std::shared_ptr<mg::Buffer>> map;
1412 };
1413
1414 struct WithAnyNumberOfBuffers : BufferScheduling {};
1415
1416=== modified file 'tests/integration-tests/test_session.cpp'
1417--- tests/integration-tests/test_session.cpp 2017-05-08 03:04:26 +0000
1418+++ tests/integration-tests/test_session.cpp 2017-07-19 05:46:21 +0000
1419@@ -80,7 +80,7 @@
1420 struct StubGLBufferStreamFactory : public mtd::StubBufferStreamFactory
1421 {
1422 std::shared_ptr<mc::BufferStream> create_buffer_stream(
1423- mf::BufferStreamId, std::shared_ptr<mf::ClientBuffers> const&,
1424+ mf::BufferStreamId,
1425 mg::BufferProperties const&) override
1426 {
1427 return std::make_shared<StubGLBufferStream>();
1428
1429=== modified file 'tests/integration-tests/test_submit_buffer.cpp'
1430--- tests/integration-tests/test_submit_buffer.cpp 2017-05-08 03:04:26 +0000
1431+++ tests/integration-tests/test_submit_buffer.cpp 2017-07-19 05:46:21 +0000
1432@@ -32,7 +32,6 @@
1433 #include "mir/frontend/event_sink.h"
1434 #include "mir/compositor/buffer_stream.h"
1435 #include "src/server/compositor/stream.h"
1436-#include "src/server/compositor/buffer_map.h"
1437 #include "mir_toolkit/mir_client_library.h"
1438 #include "mir_toolkit/debug/surface.h"
1439 #include "src/client/mir_connection.h"
1440@@ -70,96 +69,17 @@
1441 {}
1442
1443 std::shared_ptr<mc::BufferStream> create_buffer_stream(
1444- mf::BufferStreamId i, std::shared_ptr<mf::ClientBuffers> const& s,
1445+ mf::BufferStreamId i,
1446 int, mg::BufferProperties const& p) override
1447 {
1448- return create_buffer_stream(i, s, p);
1449+ return create_buffer_stream(i, p);
1450 }
1451
1452 std::shared_ptr<mc::BufferStream> create_buffer_stream(
1453- mf::BufferStreamId, std::shared_ptr<mf::ClientBuffers> const& sink,
1454+ mf::BufferStreamId,
1455 mg::BufferProperties const& properties) override
1456 {
1457- return std::make_shared<mc::Stream>(sink, properties.size, properties.format);
1458- }
1459-
1460- std::shared_ptr<mf::ClientBuffers> create_buffer_map(std::shared_ptr<mf::BufferSink> const& sink) override
1461- {
1462- struct BufferMap : mf::ClientBuffers
1463- {
1464- BufferMap(
1465- std::shared_ptr<mf::BufferSink> const& sink,
1466- std::vector<mg::BufferID> const& ids) :
1467- sink(sink),
1468- buffer_id_seq(ids)
1469- {
1470- std::reverse(buffer_id_seq.begin(), buffer_id_seq.end());
1471- }
1472-
1473- mg::BufferID add_buffer(std::shared_ptr<mg::Buffer> const& buffer) override
1474- {
1475- struct BufferIdWrapper : mg::Buffer
1476- {
1477- BufferIdWrapper(std::shared_ptr<mg::Buffer> const& b, mg::BufferID id) :
1478- wrapped(b),
1479- id_(id)
1480- {
1481- }
1482-
1483- std::shared_ptr<mg::NativeBuffer> native_buffer_handle() const override
1484- {
1485- return wrapped->native_buffer_handle();
1486- }
1487- mg::BufferID id() const override
1488- {
1489- return id_;
1490- }
1491- geom::Size size() const override
1492- {
1493- return wrapped->size();
1494- }
1495- MirPixelFormat pixel_format() const override
1496- {
1497- return wrapped->pixel_format();
1498- }
1499- mg::NativeBufferBase* native_buffer_base() override
1500- {
1501- return wrapped->native_buffer_base();
1502- }
1503- std::shared_ptr<mg::Buffer> const wrapped;
1504- mg::BufferID const id_;
1505- };
1506-
1507- auto id = buffer_id_seq.back();
1508- buffer_id_seq.pop_back();
1509- b = std::make_shared<BufferIdWrapper>(buffer, id);
1510- sink->add_buffer(*b);
1511- return id;
1512- }
1513-
1514- void remove_buffer(mg::BufferID) override
1515- {
1516- }
1517-
1518- std::shared_ptr<mg::Buffer> get(mg::BufferID) const override
1519- {
1520- return b;
1521- }
1522-
1523- void send_buffer(mg::BufferID) override
1524- {
1525- }
1526-
1527- void receive_buffer(mg::BufferID) override
1528- {
1529- }
1530-
1531- std::shared_ptr<mg::Buffer> b;
1532- std::shared_ptr<mf::BufferSink> const sink;
1533- std::shared_ptr<mtd::StubBufferAllocator> alloc{std::make_shared<mtd::StubBufferAllocator>()};
1534- std::vector<mg::BufferID> buffer_id_seq;
1535- };
1536- return std::make_shared<BufferMap>(sink, buffer_id_seq);
1537+ return std::make_shared<mc::Stream>(properties.size, properties.format);
1538 }
1539
1540 std::vector<mg::BufferID> const buffer_id_seq;
1541@@ -204,6 +124,66 @@
1542 std::shared_ptr<mg::PlatformIpcOperations> const underlying_ops;
1543 };
1544
1545+class RecordingBufferAllocator : public mg::GraphicBufferAllocator
1546+{
1547+public:
1548+ RecordingBufferAllocator(
1549+ std::shared_ptr<mg::GraphicBufferAllocator> const& wrapped,
1550+ std::vector<std::weak_ptr<mg::Buffer>>& allocated_buffers,
1551+ std::mutex& buffer_mutex)
1552+ : allocated_buffers{allocated_buffers},
1553+ underlying_allocator{wrapped},
1554+ buffer_mutex{buffer_mutex}
1555+ {
1556+ }
1557+
1558+ std::shared_ptr<mg::Buffer> alloc_buffer(
1559+ mg::BufferProperties const& buffer_properties) override
1560+ {
1561+ auto const buf = underlying_allocator->alloc_buffer(buffer_properties);
1562+ {
1563+ std::lock_guard<std::mutex> lock{buffer_mutex};
1564+ allocated_buffers.push_back(buf);
1565+ }
1566+ return buf;
1567+ }
1568+
1569+ std::vector<MirPixelFormat> supported_pixel_formats() override
1570+ {
1571+ return underlying_allocator->supported_pixel_formats();
1572+ }
1573+
1574+ std::shared_ptr<mg::Buffer> alloc_buffer(
1575+ geom::Size size,
1576+ uint32_t native_format,
1577+ uint32_t native_flags) override
1578+ {
1579+ auto const buf = underlying_allocator->alloc_buffer(size, native_format, native_flags);
1580+ {
1581+ std::lock_guard<std::mutex> lock{buffer_mutex};
1582+ allocated_buffers.push_back(buf);
1583+ }
1584+ return buf;
1585+ }
1586+
1587+ std::shared_ptr<mg::Buffer> alloc_software_buffer(
1588+ geom::Size size,
1589+ MirPixelFormat format) override
1590+ {
1591+ auto const buf = underlying_allocator->alloc_software_buffer(size, format);
1592+ {
1593+ std::lock_guard<std::mutex> lock{buffer_mutex};
1594+ allocated_buffers.push_back(buf);
1595+ }
1596+ return buf;
1597+ }
1598+
1599+ std::vector<std::weak_ptr<mg::Buffer>>& allocated_buffers;
1600+private:
1601+ std::shared_ptr<mg::GraphicBufferAllocator> const underlying_allocator;
1602+ std::mutex& buffer_mutex;
1603+};
1604+
1605 struct StubPlatform : public mg::Platform
1606 {
1607 StubPlatform(std::shared_ptr<mir::Fd> const& last_fd)
1608@@ -214,7 +194,10 @@
1609
1610 mir::UniqueModulePtr<mg::GraphicBufferAllocator> create_buffer_allocator() override
1611 {
1612- return underlying_platform->create_buffer_allocator();
1613+ return mir::make_module_ptr<RecordingBufferAllocator>(
1614+ underlying_platform->create_buffer_allocator(),
1615+ allocated_buffers,
1616+ buffer_mutex);
1617 }
1618
1619 mir::UniqueModulePtr<mg::PlatformIpcOperations> make_ipc_operations() const override
1620@@ -231,20 +214,28 @@
1621 return underlying_platform->create_display(policy, config);
1622 }
1623
1624+ std::vector<std::weak_ptr<mg::Buffer>> get_allocated_buffers()
1625+ {
1626+ std::lock_guard<std::mutex> lock{buffer_mutex};
1627+ return allocated_buffers;
1628+ }
1629+
1630 mg::NativeRenderingPlatform* native_rendering_platform() override { return nullptr; }
1631 mg::NativeDisplayPlatform* native_display_platform() override { return nullptr; }
1632 std::vector<mir::ExtensionDescription> extensions() const override { return {}; }
1633
1634 std::shared_ptr<mir::Fd> const last_fd;
1635 std::shared_ptr<mg::Platform> const underlying_platform;
1636+
1637+private:
1638+ std::mutex buffer_mutex;
1639+ std::vector<std::weak_ptr<mg::Buffer>> allocated_buffers;
1640 };
1641
1642 struct ExchangeServerConfiguration : mtf::StubbedServerConfiguration
1643 {
1644 ExchangeServerConfiguration(
1645- std::vector<mg::BufferID> const& id_seq,
1646 std::shared_ptr<mir::Fd> const& last_unpacked_fd) :
1647- stream_factory{std::make_shared<StubStreamFactory>(id_seq)},
1648 platform{std::make_shared<StubPlatform>(last_unpacked_fd)}
1649 {
1650 }
1651@@ -254,24 +245,20 @@
1652 return platform;
1653 }
1654
1655- std::shared_ptr<msc::BufferStreamFactory> the_buffer_stream_factory() override
1656- {
1657- return stream_factory;
1658- }
1659-
1660- std::shared_ptr<StubStreamFactory> const stream_factory;
1661- std::shared_ptr<mg::Platform> const platform;
1662+ std::shared_ptr<StubPlatform> const platform;
1663 };
1664
1665 struct SubmitBuffer : mir_test_framework::InProcessServer
1666 {
1667- std::vector<mg::BufferID> const buffer_id_exchange_seq{
1668- mg::BufferID{4}, mg::BufferID{8}, mg::BufferID{9}, mg::BufferID{3}, mg::BufferID{4}};
1669-
1670 std::shared_ptr<mir::Fd> last_unpacked_fd{std::make_shared<mir::Fd>()};
1671- ExchangeServerConfiguration server_configuration{buffer_id_exchange_seq, last_unpacked_fd};
1672+ ExchangeServerConfiguration server_configuration{last_unpacked_fd};
1673 mir::DefaultServerConfiguration& server_config() override { return server_configuration; }
1674
1675+ std::vector<std::weak_ptr<mg::Buffer>> get_allocated_buffers()
1676+ {
1677+ return server_configuration.platform->get_allocated_buffers();
1678+ }
1679+
1680 void request_completed()
1681 {
1682 std::unique_lock<decltype(mutex)> lk(mutex);
1683@@ -287,7 +274,7 @@
1684 google::protobuf::NewCallback(this, &SubmitBuffer::request_completed));
1685
1686 arrived = false;
1687- return cv.wait_for(lk, std::chrono::seconds(5), [this]() {return arrived;});
1688+ return cv.wait_for(lk, std::chrono::seconds(500), [this]() {return arrived;});
1689 }
1690
1691 bool allocate_buffers(mclr::DisplayServer& server, mp::BufferAllocation& request)
1692@@ -318,13 +305,18 @@
1693 mp::BufferRequest buffer_request;
1694 };
1695 template<class Clock>
1696-bool spin_wait_for_id(mg::BufferID id, MirWindow* window, std::chrono::time_point<Clock> const& pt)
1697+bool spin_wait_for_id(
1698+ std::function<std::vector<mg::BufferID>()> const& id_generator,
1699+ MirWindow* window,
1700+ std::chrono::time_point<Clock> const& pt)
1701 {
1702 while(Clock::now() < pt)
1703 {
1704- //auto z = mir_debug_window_current_buffer_id(window);
1705- if (mir_debug_window_current_buffer_id(window) == id.as_value())
1706- return true;
1707+ for (auto const& id : id_generator())
1708+ {
1709+ if (mir_debug_window_current_buffer_id(window) == id.as_value())
1710+ return true;
1711+ }
1712 std::this_thread::yield();
1713 }
1714 return false;
1715@@ -353,7 +345,17 @@
1716 for (auto i = 0; i < buffer_request.buffer().fd().size(); i++)
1717 ::close(buffer_request.buffer().fd(i));
1718
1719- buffer_request.mutable_buffer()->set_buffer_id(buffer_id_exchange_seq.begin()->as_value());
1720+ mp::BufferAllocation allocation_request;
1721+ auto allocate = allocation_request.add_buffer_requests();
1722+ allocate->set_buffer_usage(static_cast<int32_t>(mg::BufferUsage::software));
1723+ allocate->set_pixel_format(mir_pixel_format_abgr_8888);
1724+ allocate->set_width(320);
1725+ allocate->set_height(240);
1726+
1727+ ASSERT_THAT(allocate_buffers(server, allocation_request), DidNotTimeOut());
1728+
1729+ buffer_request.mutable_buffer()->set_buffer_id(
1730+ get_allocated_buffers().back().lock()->id().as_value());
1731 buffer_request.mutable_buffer()->add_fd(file);
1732
1733 ASSERT_THAT(submit_buffer(server, buffer_request), DidNotTimeOut());
1734@@ -377,10 +379,22 @@
1735 auto rpc_channel = connection->rpc_channel();
1736 mclr::DisplayServer server(rpc_channel);
1737
1738+ for(int i = 0; i < 5; ++i)
1739+ {
1740+ mp::BufferAllocation allocation_request;
1741+ auto allocate = allocation_request.add_buffer_requests();
1742+ allocate->set_buffer_usage(static_cast<int32_t>(mg::BufferUsage::software));
1743+ allocate->set_pixel_format(mir_pixel_format_abgr_8888);
1744+ allocate->set_width(320);
1745+ allocate->set_height(240);
1746+
1747+ allocate_buffers(server, allocation_request);
1748+ }
1749+
1750 mp::BufferRequest request;
1751- for (auto const& id : buffer_id_exchange_seq)
1752+ for (auto weak_buffer : get_allocated_buffers())
1753 {
1754- buffer_request.mutable_buffer()->set_buffer_id(id.as_value());
1755+ buffer_request.mutable_buffer()->set_buffer_id(weak_buffer.lock()->id().as_value());
1756 ASSERT_THAT(submit_buffer(server, buffer_request), DidNotTimeOut());
1757 }
1758
1759@@ -396,8 +410,32 @@
1760 auto window = mtf::make_any_surface(connection);
1761
1762 auto timeout = std::chrono::steady_clock::now() + 5s;
1763- EXPECT_TRUE(spin_wait_for_id(buffer_id_exchange_seq.back(), window, timeout))
1764- << "failed to see the last scheduled buffer become the current one";
1765+
1766+ EXPECT_TRUE(
1767+ spin_wait_for_id(
1768+ [this]()
1769+ {
1770+ /* We expect to receive one of the implicitly allocated buffers
1771+ * We don't care which one we get.
1772+ *
1773+ * We need to repeatedly check the allocated buffers, because
1774+ * buffer allocation is asynchronous WRT window creation.
1775+ */
1776+ std::vector<mg::BufferID> candidate_ids;
1777+ for (auto const weak_buffer : get_allocated_buffers())
1778+ {
1779+ auto const buffer = weak_buffer.lock();
1780+ if (buffer)
1781+ {
1782+ // If there are any expired buffers we don't care about them
1783+ candidate_ids.push_back(buffer->id());
1784+ }
1785+ }
1786+ return candidate_ids;
1787+ },
1788+ window,
1789+ timeout))
1790+ << "failed to see buffer";
1791
1792 mir_window_release_sync(window);
1793 mir_connection_release(connection);
1794
1795=== modified file 'tests/integration-tests/test_surface_stack_with_compositor.cpp'
1796--- tests/integration-tests/test_surface_stack_with_compositor.cpp 2017-05-08 03:04:26 +0000
1797+++ tests/integration-tests/test_surface_stack_with_compositor.cpp 2017-07-19 05:46:21 +0000
1798@@ -24,7 +24,6 @@
1799 #include "src/server/scene/basic_surface.h"
1800 #include "src/server/compositor/default_display_buffer_compositor_factory.h"
1801 #include "src/server/compositor/multi_threaded_compositor.h"
1802-#include "src/server/compositor/buffer_map.h"
1803 #include "src/server/compositor/stream.h"
1804 #include "mir/test/fake_shared.h"
1805 #include "mir/test/doubles/mock_buffer_stream.h"
1806@@ -47,6 +46,7 @@
1807 namespace mr = mir::report;
1808 namespace mc = mir::compositor;
1809 namespace mg = mir::graphics;
1810+namespace mf = mir::frontend;
1811 namespace geom = mir::geometry;
1812 using namespace testing;
1813
1814@@ -123,8 +123,7 @@
1815 {
1816 SurfaceStackCompositor() :
1817 timeout{std::chrono::system_clock::now() + std::chrono::seconds(5)},
1818- buffers(std::make_shared<mc::BufferMap>(std::make_shared<NiceMock<mtd::MockEventSink>>())),
1819- stream(std::make_shared<mc::Stream>(buffers, geom::Size{ 1, 1 }, mir_pixel_format_abgr_8888 )),
1820+ stream(std::make_shared<mc::Stream>(geom::Size{ 1, 1 }, mir_pixel_format_abgr_8888 )),
1821 mock_buffer_stream(std::make_shared<NiceMock<mtd::MockBufferStream>>()),
1822 streams({ { stream, {0,0}, {} } }),
1823 stub_surface{std::make_shared<ms::BasicSurface>(
1824@@ -136,7 +135,6 @@
1825 null_scene_report)},
1826 stub_buffer(std::make_shared<mtd::StubBuffer>())
1827 {
1828- buffers->add_buffer(stub_buffer);
1829 ON_CALL(*mock_buffer_stream, lock_compositor_buffer(_))
1830 .WillByDefault(Return(mt::fake_shared(*stub_buffer)));
1831 }
1832@@ -145,7 +143,6 @@
1833 std::shared_ptr<mc::CompositorReport> null_comp_report{mr::null_compositor_report()};
1834 StubRendererFactory renderer_factory;
1835 std::chrono::system_clock::time_point timeout;
1836- std::shared_ptr<mc::BufferMap> buffers;
1837 std::shared_ptr<mc::Stream> stream;
1838 std::shared_ptr<mtd::MockBufferStream> mock_buffer_stream;
1839 std::list<ms::StreamInfo> const streams;
1840
1841=== modified file 'tests/integration-tests/test_swapinterval.cpp'
1842--- tests/integration-tests/test_swapinterval.cpp 2017-05-08 03:04:26 +0000
1843+++ tests/integration-tests/test_swapinterval.cpp 2017-07-19 05:46:21 +0000
1844@@ -67,24 +67,19 @@
1845 }
1846
1847 std::shared_ptr<mc::BufferStream> create_buffer_stream(
1848- mf::BufferStreamId id, std::shared_ptr<mf::ClientBuffers> const& sink,
1849+ mf::BufferStreamId id,
1850 int, mg::BufferProperties const& p) override
1851 {
1852- return create_buffer_stream(id, sink, p);
1853+ return create_buffer_stream(id, p);
1854 }
1855
1856 std::shared_ptr<mc::BufferStream> create_buffer_stream(
1857- mf::BufferStreamId, std::shared_ptr<mf::ClientBuffers> const&,
1858+ mf::BufferStreamId,
1859 mg::BufferProperties const&) override
1860 {
1861 return std::make_shared<StubBufferStream>(framedropping_enabled);
1862 }
1863
1864- std::shared_ptr<mf::ClientBuffers> create_buffer_map(std::shared_ptr<mf::BufferSink> const&) override
1865- {
1866- return std::make_shared<mtd::StubClientBuffers>();
1867- }
1868-
1869 private:
1870 std::atomic<bool>& framedropping_enabled;
1871 };
1872
1873=== modified file 'tests/mir_test_framework/stub_session.cpp'
1874--- tests/mir_test_framework/stub_session.cpp 2017-05-08 03:04:26 +0000
1875+++ tests/mir_test_framework/stub_session.cpp 2017-07-19 05:46:21 +0000
1876@@ -143,31 +143,6 @@
1877 {
1878 }
1879
1880-mir::graphics::BufferID mtd::StubSession::create_buffer(mir::graphics::BufferProperties const&)
1881-{
1882- return mir::graphics::BufferID(3);
1883-}
1884-
1885-mir::graphics::BufferID mtd::StubSession::create_buffer(mir::geometry::Size, uint32_t, uint32_t)
1886-{
1887- return mir::graphics::BufferID(3);
1888-}
1889-
1890-mir::graphics::BufferID mtd::StubSession::create_buffer(mir::geometry::Size, MirPixelFormat)
1891-{
1892- return mir::graphics::BufferID(3);
1893-}
1894-
1895-void mtd::StubSession::destroy_buffer(mir::graphics::BufferID)
1896-{
1897-}
1898-
1899-std::shared_ptr<mir::graphics::Buffer> mtd::StubSession::get_buffer(graphics::BufferID)
1900-{
1901- return std::make_shared<mtd::StubBuffer>(
1902- std::make_shared<mir_test_framework::NativeBuffer>(graphics::BufferProperties{}));
1903-}
1904-
1905 namespace
1906 {
1907 // Ensure we don't accidentally have an abstract class
1908
1909=== modified file 'tests/unit-tests/client/test_mir_connection.cpp'
1910--- tests/unit-tests/client/test_mir_connection.cpp 2017-05-25 06:28:52 +0000
1911+++ tests/unit-tests/client/test_mir_connection.cpp 2017-07-19 05:46:21 +0000
1912@@ -873,7 +873,6 @@
1913 auto native_format = 342u;
1914 auto native_flags = 0x44;
1915 mp::BufferAllocation mp_alloc;
1916- mp_alloc.mutable_id()->set_value(-1);
1917 auto params = mp_alloc.add_buffer_requests();
1918 params->set_width(size.width.as_int());
1919 params->set_height(size.height.as_int());
1920
1921=== modified file 'tests/unit-tests/compositor/CMakeLists.txt'
1922--- tests/unit-tests/compositor/CMakeLists.txt 2017-05-08 03:04:26 +0000
1923+++ tests/unit-tests/compositor/CMakeLists.txt 2017-07-19 05:46:21 +0000
1924@@ -7,7 +7,6 @@
1925 ${CMAKE_CURRENT_SOURCE_DIR}/test_screencast_display_buffer.cpp
1926 ${CMAKE_CURRENT_SOURCE_DIR}/test_compositing_screencast.cpp
1927 ${CMAKE_CURRENT_SOURCE_DIR}/test_multi_monitor_arbiter.cpp
1928- ${CMAKE_CURRENT_SOURCE_DIR}/test_client_buffers.cpp
1929 ${CMAKE_CURRENT_SOURCE_DIR}/test_dropping_schedule.cpp
1930 ${CMAKE_CURRENT_SOURCE_DIR}/test_queueing_schedule.cpp
1931 )
1932
1933=== removed file 'tests/unit-tests/compositor/test_client_buffers.cpp'
1934--- tests/unit-tests/compositor/test_client_buffers.cpp 2017-07-19 05:46:21 +0000
1935+++ tests/unit-tests/compositor/test_client_buffers.cpp 1970-01-01 00:00:00 +0000
1936@@ -1,118 +0,0 @@
1937-/*
1938- * Copyright © 2015 Canonical Ltd.
1939- *
1940- * This program is free software: you can redistribute it and/or modify
1941- * it under the terms of the GNU General Public License version 3 as
1942- * published by the Free Software Foundation.
1943- *
1944- * This program is distributed in the hope that it will be useful,
1945- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1946- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1947- * GNU General Public License for more details.
1948- *
1949- * You should have received a copy of the GNU General Public License
1950- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1951- *
1952- * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
1953- */
1954-
1955-#include "mir/test/doubles/mock_event_sink.h"
1956-#include "mir/test/fake_shared.h"
1957-#include "mir/test/doubles/stub_buffer_allocator.h"
1958-#include "src/server/compositor/buffer_map.h"
1959-#include "mir/graphics/display_configuration.h"
1960-
1961-#include <gtest/gtest.h>
1962-using namespace testing;
1963-namespace mt = mir::test;
1964-namespace mtd = mir::test::doubles;
1965-namespace mc = mir::compositor;
1966-namespace mg = mir::graphics;
1967-namespace mf = mir::frontend;
1968-namespace geom = mir::geometry;
1969-
1970-struct ClientBuffers : public Test
1971-{
1972- std::shared_ptr<mtd::MockEventSink> mock_sink = std::make_shared<testing::NiceMock<mtd::MockEventSink>>();
1973- mg::BufferProperties properties{geom::Size{42,43}, mir_pixel_format_abgr_8888, mg::BufferUsage::hardware};
1974- mtd::StubBuffer stub_buffer{properties};
1975- mc::BufferMap map{mock_sink};
1976-};
1977-
1978-TEST_F(ClientBuffers, sends_full_buffer_on_allocation)
1979-{
1980- EXPECT_CALL(*mock_sink, add_buffer(Ref(stub_buffer)));
1981- mc::BufferMap map{mock_sink};
1982- EXPECT_THAT(map.add_buffer(mt::fake_shared(stub_buffer)), Eq(stub_buffer.id()));
1983-}
1984-
1985-TEST_F(ClientBuffers, access_of_nonexistent_buffer_throws)
1986-{
1987- EXPECT_THROW({
1988- auto buffer = map.get(stub_buffer.id());
1989- }, std::logic_error);
1990-}
1991-
1992-TEST_F(ClientBuffers, removal_of_nonexistent_buffer_throws)
1993-{
1994- EXPECT_THROW({
1995- map.remove_buffer(stub_buffer.id());
1996- }, std::logic_error);
1997-}
1998-
1999-TEST_F(ClientBuffers, can_access_once_added)
2000-{
2001- auto id = map.add_buffer(mt::fake_shared(stub_buffer));
2002- EXPECT_THAT(map.get(id).get(), Eq(&stub_buffer));
2003-}
2004-
2005-TEST_F(ClientBuffers, sends_update_msg_to_send_buffer)
2006-{
2007- auto id = map.add_buffer(mt::fake_shared(stub_buffer));
2008- auto buffer = map.get(id);
2009- EXPECT_CALL(*mock_sink, update_buffer(Ref(*buffer)));
2010- map.send_buffer(id);
2011-}
2012-
2013-TEST_F(ClientBuffers, sends_no_update_msg_if_buffer_is_not_around)
2014-{
2015- auto id = map.add_buffer(mt::fake_shared(stub_buffer));
2016- auto buffer = map.get(id);
2017-
2018- map.remove_buffer(id);
2019- map.send_buffer(id);
2020-}
2021-
2022-TEST_F(ClientBuffers, can_remove_buffer_from_send_callback)
2023-{
2024- auto id = map.add_buffer(mt::fake_shared(stub_buffer));
2025- ON_CALL(*mock_sink, update_buffer(_))
2026- .WillByDefault(Invoke(
2027- [&] (mg::Buffer& buffer)
2028- {
2029- map.remove_buffer(buffer.id());
2030- }));
2031-
2032- map.send_buffer(id);
2033-}
2034-
2035-TEST_F(ClientBuffers, ignores_unknown_receive)
2036-{
2037- EXPECT_CALL(*mock_sink, add_buffer(_))
2038- .Times(1);
2039- auto id = map.add_buffer(mt::fake_shared(stub_buffer));
2040- map.remove_buffer(id);
2041- map.send_buffer(id);
2042-}
2043-
2044-TEST_F(ClientBuffers, sends_error_buffer_when_alloc_fails)
2045-{
2046- std::string error_msg = "a reason";
2047- EXPECT_CALL(*mock_sink, add_buffer(_))
2048- .WillOnce(Throw(std::runtime_error(error_msg)));
2049- EXPECT_CALL(*mock_sink, error_buffer(stub_buffer.size(), stub_buffer.pixel_format(), StrEq(error_msg)));
2050- mc::BufferMap map{mock_sink};
2051- EXPECT_THROW({
2052- map.add_buffer(mt::fake_shared(stub_buffer));
2053- }, std::runtime_error);
2054-}
2055
2056=== modified file 'tests/unit-tests/compositor/test_dropping_schedule.cpp'
2057--- tests/unit-tests/compositor/test_dropping_schedule.cpp 2017-05-08 03:04:26 +0000
2058+++ tests/unit-tests/compositor/test_dropping_schedule.cpp 2017-07-19 05:46:21 +0000
2059@@ -16,7 +16,6 @@
2060 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
2061 */
2062
2063-#include "mir/frontend/client_buffers.h"
2064 #include "src/server/compositor/dropping_schedule.h"
2065 #include "mir/test/doubles/stub_buffer.h"
2066 #include "mir/test/fake_shared.h"
2067@@ -28,20 +27,9 @@
2068 namespace mt = mir::test;
2069 namespace mg = mir::graphics;
2070 namespace mc = mir::compositor;
2071-namespace mf = mir::frontend;
2072 namespace
2073 {
2074
2075-struct MockBufferMap : mf::ClientBuffers
2076-{
2077- MOCK_METHOD1(add_buffer, mg::BufferID(std::shared_ptr<mg::Buffer> const&));
2078- MOCK_METHOD1(remove_buffer, void(mg::BufferID id));
2079- MOCK_METHOD1(send_buffer, void(mg::BufferID id));
2080- MOCK_METHOD1(receive_buffer, void(mg::BufferID id));
2081- MOCK_CONST_METHOD0(client_owned_buffer_count, size_t());
2082- MOCK_CONST_METHOD1(get, std::shared_ptr<mg::Buffer>(mg::BufferID));
2083-};
2084-
2085 struct DroppingSchedule : Test
2086 {
2087 DroppingSchedule()
2088@@ -52,8 +40,7 @@
2089 unsigned int const num_buffers{5};
2090 std::vector<std::shared_ptr<mg::Buffer>> buffers;
2091
2092- MockBufferMap mock_client_buffers;
2093- mc::DroppingSchedule schedule{mt::fake_shared(mock_client_buffers)};
2094+ mc::DroppingSchedule schedule;
2095 std::vector<std::shared_ptr<mg::Buffer>> drain_queue()
2096 {
2097 std::vector<std::shared_ptr<mg::Buffer>> scheduled_buffers;
2098@@ -74,49 +61,23 @@
2099
2100 TEST_F(DroppingSchedule, drops_excess_buffers)
2101 {
2102- InSequence seq;
2103- EXPECT_CALL(mock_client_buffers, send_buffer(buffers[0]->id()));
2104- EXPECT_CALL(mock_client_buffers, send_buffer(buffers[1]->id()));
2105- EXPECT_CALL(mock_client_buffers, send_buffer(buffers[2]->id()));
2106- EXPECT_CALL(mock_client_buffers, send_buffer(buffers[3]->id()));
2107-
2108 for(auto i = 0u; i < num_buffers; i++)
2109 schedule.schedule(buffers[i]);
2110
2111 auto queue = drain_queue();
2112 ASSERT_THAT(queue, SizeIs(1));
2113+
2114+ // The 5th buffer should be scheduled...
2115 EXPECT_THAT(queue[0]->id(), Eq(buffers[4]->id()));
2116-}
2117-
2118-TEST_F(DroppingSchedule, nonblocking_schedule_avoids_socket_io)
2119-{
2120- for (auto i = 0u; i < num_buffers; i++)
2121+ for (int i = 0; i < 4 ; ++i)
2122 {
2123- EXPECT_CALL(mock_client_buffers, send_buffer(_))
2124- .Times(0);
2125-
2126- auto deferred_io = schedule.schedule_nonblocking(buffers[i]);
2127-
2128- testing::Mock::VerifyAndClearExpectations(&mock_client_buffers);
2129- if (i > 0)
2130- {
2131- EXPECT_CALL(mock_client_buffers, send_buffer(buffers[i-1]->id()))
2132- .Times(1);
2133- ASSERT_TRUE(deferred_io.valid());
2134- deferred_io.wait();
2135- testing::Mock::VerifyAndClearExpectations(&mock_client_buffers);
2136- }
2137+ // ...and all the others should have no external references
2138+ EXPECT_TRUE(buffers[i].unique());
2139 }
2140-
2141- auto queue = drain_queue();
2142- ASSERT_THAT(queue, SizeIs(1));
2143- EXPECT_THAT(queue[0]->id(), Eq(buffers[4]->id()));
2144 }
2145
2146 TEST_F(DroppingSchedule, queueing_same_buffer_many_times_doesnt_drop)
2147 {
2148- EXPECT_CALL(mock_client_buffers, send_buffer(_)).Times(0);
2149-
2150 schedule.schedule(buffers[2]);
2151 schedule.schedule(buffers[2]);
2152 schedule.schedule(buffers[2]);
2153
2154=== modified file 'tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp'
2155--- tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp 2017-05-26 12:45:45 +0000
2156+++ tests/unit-tests/compositor/test_multi_monitor_arbiter.cpp 2017-07-19 05:46:21 +0000
2157@@ -21,7 +21,7 @@
2158 #include "mir/test/doubles/stub_buffer_allocator.h"
2159 #include "src/server/compositor/multi_monitor_arbiter.h"
2160 #include "src/server/compositor/schedule.h"
2161-#include "mir/frontend/client_buffers.h"
2162+#include "src/server/compositor/temporary_buffers.h"
2163
2164 #include <gtest/gtest.h>
2165 using namespace testing;
2166@@ -33,16 +33,6 @@
2167
2168 namespace
2169 {
2170-struct MockBufferMap : mf::ClientBuffers
2171-{
2172- MOCK_METHOD1(add_buffer, mg::BufferID(std::shared_ptr<mg::Buffer> const&));
2173- MOCK_METHOD1(remove_buffer, void(mg::BufferID id));
2174- MOCK_METHOD1(receive_buffer, void(mg::BufferID id));
2175- MOCK_METHOD1(send_buffer, void(mg::BufferID id));
2176- MOCK_CONST_METHOD0(client_owned_buffer_count, size_t());
2177- MOCK_CONST_METHOD1(get, std::shared_ptr<mg::Buffer>(mg::BufferID));
2178-};
2179-
2180 struct FixedSchedule : mc::Schedule
2181 {
2182 void schedule(std::shared_ptr<mg::Buffer> const&) override
2183@@ -63,7 +53,9 @@
2184 {
2185 if (sched.empty() || current == sched.size())
2186 throw std::runtime_error("no buffer scheduled");
2187- return sched[current++];
2188+ auto buf = sched.front();
2189+ sched.erase(sched.begin());
2190+ return buf;
2191 }
2192 void set_schedule(std::vector<std::shared_ptr<mg::Buffer>> s)
2193 {
2194@@ -84,10 +76,40 @@
2195 }
2196 unsigned int const num_buffers{6u};
2197 std::vector<std::shared_ptr<mg::Buffer>> buffers;
2198- NiceMock<MockBufferMap> mock_map;
2199 FixedSchedule schedule;
2200- mc::MultiMonitorArbiter arbiter{mt::fake_shared(mock_map), mt::fake_shared(schedule)};
2201+ mc::MultiMonitorArbiter arbiter{mt::fake_shared(schedule)};
2202 };
2203+
2204+MATCHER_P(IsSameBufferAs, buffer, "")
2205+{
2206+ return buffer->id() == arg->id();
2207+}
2208+
2209+std::shared_ptr<mg::Buffer> wrap_with_destruction_notifier(
2210+ std::shared_ptr<mg::Buffer> const& buffer,
2211+ std::shared_ptr<bool> const& destroyed)
2212+{
2213+ class DestructionNotifyingBuffer : public mc::TemporaryBuffer
2214+ {
2215+ public:
2216+ DestructionNotifyingBuffer(
2217+ std::shared_ptr<mg::Buffer> const& buffer,
2218+ std::shared_ptr<bool> const& destroyed)
2219+ : TemporaryBuffer(buffer),
2220+ destroyed{destroyed}
2221+ {
2222+ }
2223+
2224+ ~DestructionNotifyingBuffer()
2225+ {
2226+ *destroyed = true;
2227+ }
2228+ private:
2229+ std::shared_ptr<bool> const destroyed;
2230+ };
2231+
2232+ return std::make_shared<DestructionNotifyingBuffer>(buffer, destroyed);
2233+}
2234 }
2235
2236 TEST_F(MultiMonitorArbiter, compositor_access_before_any_submission_throws)
2237@@ -107,32 +129,30 @@
2238 {
2239 schedule.set_schedule({buffers[0]});
2240 auto cbuffer = arbiter.compositor_acquire(this);
2241- EXPECT_THAT(cbuffer, Eq(buffers[0]));
2242+ EXPECT_THAT(cbuffer, IsSameBufferAs(buffers[0]));
2243 }
2244
2245 TEST_F(MultiMonitorArbiter, compositor_release_sends_buffer_back)
2246 {
2247- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id()));
2248-
2249- schedule.set_schedule({buffers[0]});
2250+ auto buffer_released = std::make_shared<bool>(false);
2251+ schedule.set_schedule({ wrap_with_destruction_notifier(buffers[0], buffer_released) });
2252
2253 auto cbuffer = arbiter.compositor_acquire(this);
2254 schedule.set_schedule({buffers[1]});
2255 arbiter.compositor_release(cbuffer);
2256+ cbuffer.reset();
2257+ // We need to acquire a new buffer - the current one is on-screen, so can't be sent back.
2258+ arbiter.compositor_acquire(this);
2259+ EXPECT_TRUE(*buffer_released);
2260 }
2261
2262 TEST_F(MultiMonitorArbiter, compositor_can_acquire_different_buffers)
2263 {
2264- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id()));
2265-
2266 schedule.set_schedule({buffers[0]});
2267 auto cbuffer1 = arbiter.compositor_acquire(this);
2268 schedule.set_schedule({buffers[1]});
2269 auto cbuffer2 = arbiter.compositor_acquire(this);
2270- EXPECT_THAT(cbuffer1, Ne(cbuffer2));
2271- arbiter.compositor_release(cbuffer2);
2272- arbiter.compositor_release(cbuffer1);
2273- Mock::VerifyAndClearExpectations(&mock_map);
2274+ EXPECT_THAT(cbuffer1, Not(IsSameBufferAs(cbuffer2)));
2275 }
2276
2277 TEST_F(MultiMonitorArbiter, compositor_buffer_syncs_to_fastest_compositor)
2278@@ -155,13 +175,13 @@
2279 auto cbuffer6 = arbiter.compositor_acquire(&comp_id2);
2280 auto cbuffer7 = arbiter.compositor_acquire(&comp_id2);
2281
2282- EXPECT_THAT(cbuffer1, Eq(buffers[0]));
2283- EXPECT_THAT(cbuffer2, Eq(buffers[0]));
2284- EXPECT_THAT(cbuffer3, Eq(buffers[1]));
2285- EXPECT_THAT(cbuffer4, Eq(buffers[0]));
2286- EXPECT_THAT(cbuffer5, Eq(buffers[0]));
2287- EXPECT_THAT(cbuffer6, Eq(buffers[1]));
2288- EXPECT_THAT(cbuffer7, Eq(buffers[1]));
2289+ EXPECT_THAT(cbuffer1, IsSameBufferAs(buffers[0]));
2290+ EXPECT_THAT(cbuffer2, IsSameBufferAs(buffers[0]));
2291+ EXPECT_THAT(cbuffer3, IsSameBufferAs(buffers[1]));
2292+ EXPECT_THAT(cbuffer4, IsSameBufferAs(buffers[0]));
2293+ EXPECT_THAT(cbuffer5, IsSameBufferAs(buffers[0]));
2294+ EXPECT_THAT(cbuffer6, IsSameBufferAs(buffers[1]));
2295+ EXPECT_THAT(cbuffer7, IsSameBufferAs(buffers[1]));
2296 }
2297
2298 TEST_F(MultiMonitorArbiter, compositor_consumes_all_buffers_when_operating_as_a_composited_scene_would)
2299@@ -179,11 +199,11 @@
2300 auto cbuffer5 = arbiter.compositor_acquire(this);
2301 arbiter.compositor_release(cbuffer5);
2302
2303- EXPECT_THAT(cbuffer1, Eq(buffers[0]));
2304- EXPECT_THAT(cbuffer2, Eq(buffers[1]));
2305- EXPECT_THAT(cbuffer3, Eq(buffers[2]));
2306- EXPECT_THAT(cbuffer4, Eq(buffers[3]));
2307- EXPECT_THAT(cbuffer5, Eq(buffers[4]));
2308+ EXPECT_THAT(cbuffer1, IsSameBufferAs(buffers[0]));
2309+ EXPECT_THAT(cbuffer2, IsSameBufferAs(buffers[1]));
2310+ EXPECT_THAT(cbuffer3, IsSameBufferAs(buffers[2]));
2311+ EXPECT_THAT(cbuffer4, IsSameBufferAs(buffers[3]));
2312+ EXPECT_THAT(cbuffer5, IsSameBufferAs(buffers[4]));
2313 }
2314
2315 TEST_F(MultiMonitorArbiter, compositor_consumes_all_buffers_when_operating_as_a_bypassed_buffer_would)
2316@@ -201,11 +221,11 @@
2317 arbiter.compositor_release(cbuffer4);
2318 arbiter.compositor_release(cbuffer5);
2319
2320- EXPECT_THAT(cbuffer1, Eq(buffers[0]));
2321- EXPECT_THAT(cbuffer2, Eq(buffers[1]));
2322- EXPECT_THAT(cbuffer3, Eq(buffers[2]));
2323- EXPECT_THAT(cbuffer4, Eq(buffers[3]));
2324- EXPECT_THAT(cbuffer5, Eq(buffers[4]));
2325+ EXPECT_THAT(cbuffer1, IsSameBufferAs(buffers[0]));
2326+ EXPECT_THAT(cbuffer2, IsSameBufferAs(buffers[1]));
2327+ EXPECT_THAT(cbuffer3, IsSameBufferAs(buffers[2]));
2328+ EXPECT_THAT(cbuffer4, IsSameBufferAs(buffers[3]));
2329+ EXPECT_THAT(cbuffer5, IsSameBufferAs(buffers[4]));
2330 }
2331
2332 TEST_F(MultiMonitorArbiter, multimonitor_compositor_buffer_syncs_to_fastest_with_more_queueing)
2333@@ -228,18 +248,18 @@
2334 auto cbuffer7 = arbiter.compositor_acquire(&comp_id2); //buffer[4]
2335 auto cbuffer8 = arbiter.compositor_acquire(&comp_id1); //buffer[4]
2336
2337- EXPECT_THAT(cbuffer1, Eq(buffers[0]));
2338- EXPECT_THAT(cbuffer2, Eq(buffers[0]));
2339-
2340- EXPECT_THAT(cbuffer3, Eq(buffers[1]));
2341-
2342- EXPECT_THAT(cbuffer4, Eq(buffers[2]));
2343- EXPECT_THAT(cbuffer5, Eq(buffers[2]));
2344-
2345- EXPECT_THAT(cbuffer6, Eq(buffers[3]));
2346-
2347- EXPECT_THAT(cbuffer7, Eq(buffers[4]));
2348- EXPECT_THAT(cbuffer8, Eq(buffers[4]));
2349+ EXPECT_THAT(cbuffer1, IsSameBufferAs(buffers[0]));
2350+ EXPECT_THAT(cbuffer2, IsSameBufferAs(buffers[0]));
2351+
2352+ EXPECT_THAT(cbuffer3, IsSameBufferAs(buffers[1]));
2353+
2354+ EXPECT_THAT(cbuffer4, IsSameBufferAs(buffers[2]));
2355+ EXPECT_THAT(cbuffer5, IsSameBufferAs(buffers[2]));
2356+
2357+ EXPECT_THAT(cbuffer6, IsSameBufferAs(buffers[3]));
2358+
2359+ EXPECT_THAT(cbuffer7, IsSameBufferAs(buffers[4]));
2360+ EXPECT_THAT(cbuffer8, IsSameBufferAs(buffers[4]));
2361 }
2362
2363 TEST_F(MultiMonitorArbiter, can_set_a_new_schedule)
2364@@ -252,8 +272,8 @@
2365 arbiter.set_schedule(mt::fake_shared(another_schedule));
2366 auto cbuffer2 = arbiter.compositor_acquire(this);
2367
2368- EXPECT_THAT(cbuffer1, Eq(buffers[3]));
2369- EXPECT_THAT(cbuffer2, Eq(buffers[0]));
2370+ EXPECT_THAT(cbuffer1, IsSameBufferAs(buffers[3]));
2371+ EXPECT_THAT(cbuffer2, IsSameBufferAs(buffers[0]));
2372 }
2373
2374 TEST_F(MultiMonitorArbiter, basic_snapshot_equals_compositor_buffer)
2375@@ -262,7 +282,7 @@
2376
2377 auto cbuffer1 = arbiter.compositor_acquire(this);
2378 auto sbuffer1 = arbiter.snapshot_acquire();
2379- EXPECT_EQ(cbuffer1, sbuffer1);
2380+ EXPECT_THAT(cbuffer1, IsSameBufferAs(sbuffer1));
2381 }
2382
2383 TEST_F(MultiMonitorArbiter, basic_snapshot_equals_latest_compositor_buffer)
2384@@ -278,8 +298,8 @@
2385 cbuffer2 = arbiter.compositor_acquire(&that);
2386
2387 auto sbuffer2 = arbiter.snapshot_acquire();
2388- EXPECT_EQ(cbuffer1, sbuffer1);
2389- EXPECT_EQ(cbuffer2, sbuffer2);
2390+ EXPECT_THAT(cbuffer1, IsSameBufferAs(sbuffer1));
2391+ EXPECT_THAT(cbuffer2, IsSameBufferAs(sbuffer2));
2392 }
2393
2394 TEST_F(MultiMonitorArbiter, snapshot_cycling_doesnt_advance_buffer_for_compositors)
2395@@ -297,8 +317,8 @@
2396 }
2397 auto cbuffer2 = arbiter.compositor_acquire(&that);
2398
2399- EXPECT_THAT(cbuffer1, Eq(cbuffer2));
2400- EXPECT_THAT(snapshot_buffers, Each(cbuffer1));
2401+ EXPECT_THAT(cbuffer1, IsSameBufferAs(cbuffer2));
2402+ EXPECT_THAT(snapshot_buffers, Each(IsSameBufferAs(cbuffer1)));
2403 }
2404
2405 TEST_F(MultiMonitorArbiter, no_buffers_available_throws_on_snapshot)
2406@@ -311,29 +331,48 @@
2407
2408 TEST_F(MultiMonitorArbiter, snapshotting_will_release_buffer_if_it_was_the_last_owner)
2409 {
2410- EXPECT_CALL(mock_map, send_buffer(_)).Times(0);
2411- schedule.set_schedule({buffers[3],buffers[4]});
2412+ auto buffer_released = std::make_shared<bool>(false);
2413+ schedule.set_schedule(
2414+ {
2415+ wrap_with_destruction_notifier(buffers[3], buffer_released),
2416+ buffers[4]
2417+ });
2418 auto cbuffer1 = arbiter.compositor_acquire(this);
2419 auto sbuffer1 = arbiter.snapshot_acquire();
2420 arbiter.compositor_release(cbuffer1);
2421-
2422- Mock::VerifyAndClearExpectations(&mock_map);
2423- EXPECT_CALL(mock_map, send_buffer(sbuffer1->id()));
2424+ cbuffer1.reset();
2425+
2426+ // Acquire a new buffer so first one is no longer onscreen.
2427+ arbiter.compositor_acquire(this);
2428+
2429+ EXPECT_FALSE(*buffer_released);
2430 arbiter.snapshot_release(sbuffer1);
2431+ sbuffer1.reset();
2432+ EXPECT_TRUE(*buffer_released);
2433 }
2434
2435 TEST_F(MultiMonitorArbiter, compositor_can_acquire_a_few_times_and_only_sends_on_the_last_release)
2436 {
2437 int comp_id1{0};
2438 int comp_id2{0};
2439- schedule.set_schedule({buffers[0], buffers[1]});
2440+
2441+ auto buffer_released = std::make_shared<bool>(false);
2442+ schedule.set_schedule(
2443+ {
2444+ wrap_with_destruction_notifier(buffers[0], buffer_released),
2445+ buffers[1]
2446+ });
2447 auto cbuffer1 = arbiter.compositor_acquire(&comp_id1);
2448 auto cbuffer2 = arbiter.compositor_acquire(&comp_id2);
2449- EXPECT_THAT(cbuffer1, Eq(cbuffer2));
2450- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id())).Times(Exactly(1));
2451+ EXPECT_THAT(cbuffer1, IsSameBufferAs(cbuffer2));
2452+
2453 auto cbuffer3 = arbiter.compositor_acquire(&comp_id1);
2454 arbiter.compositor_release(cbuffer2);
2455+ EXPECT_FALSE(*buffer_released);
2456 arbiter.compositor_release(cbuffer1);
2457+ cbuffer1.reset();
2458+ cbuffer2.reset();
2459+ EXPECT_TRUE(*buffer_released);
2460 }
2461
2462 TEST_F(MultiMonitorArbiter, advance_on_fastest_has_same_buffer)
2463@@ -349,29 +388,29 @@
2464
2465 auto cbuffer3 = arbiter.compositor_acquire(&comp_id1); //buffer[1]
2466
2467- EXPECT_THAT(cbuffer1, Eq(cbuffer2));
2468- EXPECT_THAT(cbuffer1, Eq(buffers[0]));
2469- EXPECT_THAT(cbuffer3, Eq(buffers[1]));
2470-}
2471-
2472-TEST_F(MultiMonitorArbiter, compositor_acquire_sends_buffer_back_with_fastest_guarantee)
2473-{
2474- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id()));
2475-
2476- schedule.set_schedule({buffers[0], buffers[1]});
2477-
2478- auto cbuffer = arbiter.compositor_acquire(this);
2479- schedule.set_schedule({buffers[1]});
2480- arbiter.compositor_release(cbuffer);
2481- cbuffer = arbiter.compositor_acquire(this);
2482+ EXPECT_THAT(cbuffer1, IsSameBufferAs(cbuffer2));
2483+ EXPECT_THAT(cbuffer1, IsSameBufferAs(buffers[0]));
2484+ EXPECT_THAT(cbuffer3, IsSameBufferAs(buffers[1]));
2485 }
2486
2487 TEST_F(MultiMonitorArbiter, buffers_are_sent_back)
2488 {
2489- EXPECT_CALL(mock_map, send_buffer(_)).Times(3);
2490+ std::array<std::shared_ptr<bool>, 3> buffer_released = {
2491+ {
2492+ std::make_shared<bool>(false),
2493+ std::make_shared<bool>(false),
2494+ std::make_shared<bool>(false)
2495+ }};
2496 int comp_id1{0};
2497 int comp_id2{0};
2498- schedule.set_schedule({buffers[0], buffers[1], buffers[2], buffers[3]});
2499+
2500+ schedule.set_schedule(
2501+ {
2502+ wrap_with_destruction_notifier(buffers[0], buffer_released[0]),
2503+ wrap_with_destruction_notifier(buffers[1], buffer_released[1]),
2504+ wrap_with_destruction_notifier(buffers[2], buffer_released[2]),
2505+ buffers[3]
2506+ });
2507
2508 auto b1 = arbiter.compositor_acquire(&comp_id1);
2509 arbiter.compositor_release(b1);
2510@@ -386,7 +425,14 @@
2511 auto b6 = arbiter.compositor_acquire(&comp_id1);
2512 arbiter.compositor_release(b6);
2513
2514- Mock::VerifyAndClearExpectations(&mock_map);
2515+ b1.reset();
2516+ b2.reset();
2517+ b3.reset();
2518+ b4.reset();
2519+ b5.reset();
2520+ b6.reset();
2521+
2522+ EXPECT_THAT(buffer_released, Each(Pointee(true)));
2523 }
2524
2525 TEST_F(MultiMonitorArbiter, can_check_if_buffers_are_ready)
2526@@ -442,17 +488,28 @@
2527 TEST_F(MultiMonitorArbiter, will_release_buffer_in_nbuffers_2_overlay_scenario)
2528 {
2529 int comp_id1{0};
2530- schedule.set_schedule({buffers[0], buffers[1], buffers[0], buffers[1]});
2531+ auto buffer_released = std::make_shared<bool>(false);
2532+ auto notifying_buffer = wrap_with_destruction_notifier(buffers[0], buffer_released);
2533+ schedule.set_schedule(
2534+ {
2535+ notifying_buffer,
2536+ buffers[1],
2537+ buffers[0], // We only want to be notified when the first submission is released
2538+ buffers[1]
2539+ });
2540+ notifying_buffer.reset();
2541
2542- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id()));
2543 auto b1 = arbiter.compositor_acquire(&comp_id1);
2544 auto b2 = arbiter.compositor_acquire(&comp_id1);
2545- EXPECT_THAT(b1, Eq(buffers[0]));
2546- EXPECT_THAT(b2, Eq(buffers[1]));
2547+ EXPECT_THAT(b1, IsSameBufferAs(buffers[0]));
2548+ EXPECT_THAT(b2, IsSameBufferAs(buffers[1]));
2549 arbiter.compositor_release(b1);
2550 arbiter.compositor_release(b2);
2551- Mock::VerifyAndClearExpectations(&mock_map);
2552-}
2553+ b1.reset();
2554+ b2.reset();
2555+
2556+ EXPECT_TRUE(*buffer_released);
2557+}
2558
2559 TEST_F(MultiMonitorArbiter, will_release_buffer_in_nbuffers_2_starvation_scenario)
2560 {
2561@@ -471,10 +528,10 @@
2562 arbiter.compositor_release(b2);
2563 arbiter.compositor_release(b4);
2564
2565- EXPECT_THAT(b1, Eq(buffers[0]));
2566- EXPECT_THAT(b2, Eq(buffers[1]));
2567- EXPECT_THAT(b3, Eq(buffers[1]));
2568- EXPECT_THAT(b4, Eq(buffers[0]));
2569+ EXPECT_THAT(b1, IsSameBufferAs(buffers[0]));
2570+ EXPECT_THAT(b2, IsSameBufferAs(buffers[1]));
2571+ EXPECT_THAT(b3, IsSameBufferAs(buffers[1]));
2572+ EXPECT_THAT(b4, IsSameBufferAs(buffers[0]));
2573
2574 }
2575
2576@@ -482,13 +539,12 @@
2577 {
2578 int comp_id1{0};
2579 int comp_id2{0};
2580+
2581 schedule.set_schedule({
2582 buffers[0], buffers[1], buffers[2],
2583 buffers[0], buffers[1], buffers[2],
2584 buffers[0], buffers[1], buffers[2]});
2585
2586- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id()));
2587-
2588 auto b1 = arbiter.compositor_acquire(&comp_id1);
2589 auto b2 = arbiter.compositor_acquire(&comp_id2);
2590 arbiter.compositor_release(b1); //send nothing
2591@@ -502,13 +558,12 @@
2592 auto b5 = arbiter.compositor_acquire(&comp_id1);
2593 arbiter.compositor_release(b5); //send nothing
2594
2595- EXPECT_THAT(b1, Eq(buffers[0]));
2596- EXPECT_THAT(b2, Eq(buffers[0]));
2597- EXPECT_THAT(b3, Eq(buffers[1]));
2598- EXPECT_THAT(b4, Eq(buffers[1]));
2599- EXPECT_THAT(b5, Eq(buffers[2]));
2600- Mock::VerifyAndClearExpectations(&mock_map);
2601-}
2602+ EXPECT_THAT(b1, IsSameBufferAs(buffers[0]));
2603+ EXPECT_THAT(b2, IsSameBufferAs(buffers[0]));
2604+ EXPECT_THAT(b3, IsSameBufferAs(buffers[1]));
2605+ EXPECT_THAT(b4, IsSameBufferAs(buffers[1]));
2606+ EXPECT_THAT(b5, IsSameBufferAs(buffers[2]));
2607+}
2608
2609 TEST_F(MultiMonitorArbiter, can_advance_buffer_manually)
2610 {
2611@@ -521,11 +576,11 @@
2612
2613 auto b1 = arbiter.compositor_acquire(&comp_id1);
2614 auto b2 = arbiter.compositor_acquire(&comp_id2);
2615- EXPECT_THAT(b1->id(), Eq(buffers[1]->id()));
2616- EXPECT_THAT(b2->id(), Eq(buffers[1]->id()));
2617+ EXPECT_THAT(b1, IsSameBufferAs(buffers[1]));
2618+ EXPECT_THAT(b2, IsSameBufferAs(buffers[1]));
2619
2620 auto b3 = arbiter.compositor_acquire(&comp_id1);
2621- EXPECT_THAT(b3->id(), Eq(buffers[2]->id()));
2622+ EXPECT_THAT(b3, IsSameBufferAs(buffers[2]));
2623 }
2624
2625 TEST_F(MultiMonitorArbiter, checks_if_buffer_is_valid_after_clean_onscreen_buffer)
2626@@ -547,8 +602,12 @@
2627
2628 TEST_F(MultiMonitorArbiter, releases_buffer_on_destruction)
2629 {
2630- mc::MultiMonitorArbiter arbiter{mt::fake_shared(mock_map), mt::fake_shared(schedule)};
2631- EXPECT_CALL(mock_map, send_buffer(buffers[0]->id()));
2632- schedule.set_schedule({buffers[0]});
2633- arbiter.advance_schedule();
2634+ auto buffer_released = std::make_shared<bool>(false);
2635+ schedule.set_schedule({wrap_with_destruction_notifier(buffers[0], buffer_released)});
2636+
2637+ {
2638+ mc::MultiMonitorArbiter arbiter{mt::fake_shared(schedule)};
2639+ arbiter.advance_schedule();
2640+ }
2641+ EXPECT_TRUE(*buffer_released);
2642 }
2643
2644=== modified file 'tests/unit-tests/compositor/test_stream.cpp'
2645--- tests/unit-tests/compositor/test_stream.cpp 2017-05-08 03:04:26 +0000
2646+++ tests/unit-tests/compositor/test_stream.cpp 2017-07-19 05:46:21 +0000
2647@@ -22,7 +22,6 @@
2648 #include "mir/test/fake_shared.h"
2649 #include "src/server/compositor/stream.h"
2650 #include "mir/scene/null_surface_observer.h"
2651-#include "mir/frontend/client_buffers.h"
2652
2653 #include <gmock/gmock.h>
2654 #include <gtest/gtest.h>
2655@@ -41,45 +40,6 @@
2656 MOCK_METHOD2(frame_posted, void(int, geom::Size const&));
2657 };
2658
2659-struct StubBufferMap : mf::ClientBuffers
2660-{
2661- StubBufferMap(mf::EventSink& sink, std::vector<std::shared_ptr<mg::Buffer>>& buffers) :
2662- buffers{buffers},
2663- sink{sink}
2664- {
2665- }
2666- mg::BufferID add_buffer(std::shared_ptr<mg::Buffer> const&)
2667- {
2668- return mg::BufferID{};
2669- }
2670- void remove_buffer(mg::BufferID)
2671- {
2672- }
2673- void with_buffer(mg::BufferID, std::function<void(mg::Buffer&)> const&)
2674- {
2675- }
2676- void receive_buffer(mg::BufferID)
2677- {
2678- }
2679- void send_buffer(mg::BufferID id)
2680- {
2681- sink.send_buffer(mf::BufferStreamId{33}, *get(id), mg::BufferIpcMsgType::update_msg);
2682- }
2683- std::shared_ptr<mg::Buffer> get(mg::BufferID id) const
2684- {
2685- auto it = std::find_if(buffers.begin(), buffers.end(),
2686- [id](std::shared_ptr<mg::Buffer> const& b)
2687- {
2688- return b->id() == id;
2689- });
2690- if (it == buffers.end())
2691- throw std::logic_error("cannot find buffer in map");
2692- return *it;
2693- }
2694- std::vector<std::shared_ptr<mg::Buffer>>& buffers;
2695- mf::EventSink& sink;
2696-};
2697-
2698 struct Stream : Test
2699 {
2700 Stream() :
2701@@ -94,16 +54,14 @@
2702
2703 geom::Size initial_size{44,2};
2704 std::vector<std::shared_ptr<mg::Buffer>> buffers;
2705- NiceMock<mtd::MockEventSink> mock_sink;
2706 MirPixelFormat construction_format{mir_pixel_format_rgb_565};
2707 mc::Stream stream{
2708- std::make_unique<StubBufferMap>(mock_sink, buffers), initial_size, construction_format};
2709+ initial_size, construction_format};
2710 };
2711 }
2712
2713 TEST_F(Stream, transitions_from_queuing_to_framedropping)
2714 {
2715- EXPECT_CALL(mock_sink, send_buffer(_,_,_)).Times(buffers.size() - 1);
2716 for(auto& buffer : buffers)
2717 stream.submit_buffer(buffer);
2718 stream.allow_framedropping(true);
2719@@ -111,25 +69,37 @@
2720 std::vector<std::shared_ptr<mg::Buffer>> cbuffers;
2721 while(stream.buffers_ready_for_compositor(this))
2722 cbuffers.push_back(stream.lock_compositor_buffer(this));
2723+ // Transition to framedropping should have dropped all queued buffers but the last...
2724 ASSERT_THAT(cbuffers, SizeIs(1));
2725 EXPECT_THAT(cbuffers[0]->id(), Eq(buffers.back()->id()));
2726- Mock::VerifyAndClearExpectations(&mock_sink);
2727+
2728+ for (unsigned long i = 0; i < buffers.size() - 1; ++i)
2729+ {
2730+ // ...and so all the previous buffers should no longer have external references
2731+ EXPECT_TRUE(buffers[i].unique());
2732+ }
2733 }
2734
2735 TEST_F(Stream, transitions_from_framedropping_to_queuing)
2736 {
2737 stream.allow_framedropping(true);
2738- Mock::VerifyAndClearExpectations(&mock_sink);
2739
2740- EXPECT_CALL(mock_sink, send_buffer(_,_,_)).Times(buffers.size() - 1);
2741 for(auto& buffer : buffers)
2742 stream.submit_buffer(buffer);
2743
2744+ // Only the last buffer should be owned by the stream...
2745+ EXPECT_THAT(
2746+ std::make_tuple(buffers.data(), buffers.size() - 1),
2747+ Each(Property(&std::shared_ptr<mg::Buffer>::unique, Eq(true))));
2748+
2749 stream.allow_framedropping(false);
2750 for(auto& buffer : buffers)
2751 stream.submit_buffer(buffer);
2752
2753- Mock::VerifyAndClearExpectations(&mock_sink);
2754+ // All buffers should be now owned by the the stream
2755+ EXPECT_THAT(
2756+ buffers,
2757+ Each(Property(&std::shared_ptr<mg::Buffer>::unique, Eq(false))));
2758
2759 std::vector<std::shared_ptr<mg::Buffer>> cbuffers;
2760 while(stream.buffers_ready_for_compositor(this))
2761@@ -180,23 +150,6 @@
2762 stream.submit_buffer(buffers[0]);
2763 }
2764
2765-TEST_F(Stream, wakes_compositor_before_starting_socket_io)
2766-{
2767- auto observer = std::make_shared<MockSurfaceObserver>();
2768-
2769- InSequence seq;
2770- EXPECT_CALL(*observer, frame_posted(_,_)).Times(2);
2771- EXPECT_CALL(mock_sink, send_buffer(_,_,_)).Times(1);
2772-
2773- stream.add_observer(observer);
2774- stream.allow_framedropping(true);
2775- stream.submit_buffer(buffers[0]);
2776- stream.submit_buffer(buffers[1]);
2777- stream.remove_observer(observer);
2778-
2779- Mock::VerifyAndClearExpectations(&mock_sink);
2780-}
2781-
2782 TEST_F(Stream, calls_observers_call_doesnt_hold_lock)
2783 {
2784 auto observer = std::make_shared<MockSurfaceObserver>();
2785@@ -269,9 +222,15 @@
2786 stream.submit_buffer(buffers[1]);
2787 stream.submit_buffer(buffers[2]);
2788
2789- Mock::VerifyAndClearExpectations(&mock_sink);
2790- EXPECT_CALL(mock_sink, send_buffer(_,Ref(*buffers[0]),_));
2791- EXPECT_CALL(mock_sink, send_buffer(_,Ref(*buffers[1]),_));
2792+ // Buffers should be owned by the stream, and our test
2793+ ASSERT_THAT(buffers[0].use_count(), Eq(2));
2794+ ASSERT_THAT(buffers[1].use_count(), Eq(2));
2795+ ASSERT_THAT(buffers[2].use_count(), Eq(2));
2796+
2797 stream.drop_old_buffers();
2798- Mock::VerifyAndClearExpectations(&mock_sink);
2799+
2800+ // Stream should have released ownership of all but the most recent buffer
2801+ EXPECT_THAT(buffers[0].use_count(), Eq(1));
2802+ EXPECT_THAT(buffers[1].use_count(), Eq(1));
2803+ EXPECT_THAT(buffers[2].use_count(), Eq(2));
2804 }
2805
2806=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
2807--- tests/unit-tests/frontend/test_session_mediator.cpp 2017-05-25 08:58:03 +0000
2808+++ tests/unit-tests/frontend/test_session_mediator.cpp 2017-07-19 05:46:21 +0000
2809@@ -32,6 +32,7 @@
2810 #include "mir/graphics/buffer_ipc_message.h"
2811 #include "mir/graphics/platform_operation_message.h"
2812 #include "mir/graphics/buffer_id.h"
2813+#include "mir/graphics/graphic_buffer_allocator.h"
2814 #include "mir/input/cursor_images.h"
2815 #include "mir/graphics/platform_ipc_operations.h"
2816 #include "mir/scene/coordinate_translator.h"
2817@@ -61,6 +62,7 @@
2818 #include "mir/test/doubles/mock_message_sender.h"
2819 #include "mir/test/doubles/mock_input_config_changer.h"
2820 #include "mir/test/doubles/stub_input_device.h"
2821+#include "mir/test/doubles/stub_buffer.h"
2822 #include "mir/test/display_config_matchers.h"
2823 #include "mir/test/input_devices_matcher.h"
2824 #include "mir/test/fake_shared.h"
2825@@ -119,11 +121,6 @@
2826 class StubbedSession : public mtd::StubSession
2827 {
2828 public:
2829- StubbedSession()
2830- {
2831- ON_CALL(*this, destroy_buffer(_))
2832- .WillByDefault(Invoke([this](mg::BufferID){ ++destroy_buffers;}));
2833- }
2834 std::shared_ptr<mf::Surface> get_surface(mf::SurfaceId surface) const override
2835 {
2836 if (mock_surfaces.find(surface) == mock_surfaces.end())
2837@@ -195,27 +192,8 @@
2838 mock_surfaces.erase(surface);
2839 }
2840
2841-
2842- mg::BufferID create_buffer(mg::BufferProperties const&) override
2843- {
2844- buffer_count++;
2845- return mg::BufferID{3};
2846- }
2847-
2848- mg::BufferID create_buffer(geom::Size, MirPixelFormat) override
2849- {
2850- buffer_count++;
2851- return mg::BufferID{3};
2852- }
2853-
2854- mg::BufferID create_buffer(geom::Size, uint32_t, uint32_t) override
2855- {
2856- native_buffer_count++;
2857- return mg::BufferID{3};
2858- }
2859
2860 MOCK_METHOD1(destroy_buffer_stream, void(mf::BufferStreamId));
2861- MOCK_METHOD1(destroy_buffer, void(mg::BufferID));
2862
2863 int num_alloc_requests()
2864 {
2865@@ -258,6 +236,42 @@
2866 }
2867 };
2868
2869+struct RecordingBufferAllocator : public mg::GraphicBufferAllocator
2870+{
2871+ std::shared_ptr<mg::Buffer> alloc_buffer(mg::BufferProperties const& buffer_properties) override
2872+ {
2873+ auto const buf = std::make_shared<mtd::StubBuffer>(buffer_properties);
2874+ allocated_buffers.push_back(buf);
2875+ return buf;
2876+ }
2877+
2878+ std::vector<MirPixelFormat> supported_pixel_formats() override
2879+ {
2880+ return {};
2881+ }
2882+
2883+ std::shared_ptr<mg::Buffer> alloc_buffer(
2884+ geom::Size size, uint32_t /*native_format*/, uint32_t /*native_flags*/) override
2885+ {
2886+ auto const buf = std::make_shared<mtd::StubBuffer>(size);
2887+ allocated_buffers.push_back(buf);
2888+ return buf;
2889+ }
2890+
2891+ std::shared_ptr<mg::Buffer> alloc_software_buffer(
2892+ geom::Size size, MirPixelFormat format) override
2893+ {
2894+ if ((format >= mir_pixel_formats) || format == mir_pixel_format_invalid)
2895+ BOOST_THROW_EXCEPTION((std::runtime_error{"Invalid pixel format"}));
2896+
2897+ auto const buf = std::make_shared<mtd::StubBuffer>(size);
2898+ allocated_buffers.push_back(buf);
2899+ return buf;
2900+ }
2901+
2902+ std::vector<std::weak_ptr<mg::Buffer>> allocated_buffers;
2903+};
2904+
2905 struct SessionMediator : public ::testing::Test
2906 {
2907 SessionMediator()
2908@@ -269,6 +283,7 @@
2909 stub_screencast{std::make_shared<StubScreencast>()},
2910 stubbed_session{std::make_shared<NiceMock<StubbedSession>>()},
2911 null_callback{google::protobuf::NewPermanentCallback(google::protobuf::DoNothing)},
2912+ allocator{std::make_shared<RecordingBufferAllocator>()},
2913 mediator{
2914 shell, mt::fake_shared(mock_ipc_operations), graphics_changer,
2915 surface_pixel_formats, report,
2916@@ -280,7 +295,8 @@
2917 std::make_shared<mtd::NullANRDetector>(),
2918 mir::cookie::Authority::create(),
2919 mt::fake_shared(mock_input_config_changer),
2920- {}}
2921+ {},
2922+ allocator}
2923 {
2924 using namespace ::testing;
2925
2926@@ -310,7 +326,8 @@
2927 std::make_shared<NullCoordinateTranslator>(),
2928 std::make_shared<mtd::NullANRDetector>(),
2929 mir::cookie::Authority::create(),
2930- mt::fake_shared(mock_input_config_changer), std::vector<mir::ExtensionDescription>{});
2931+ mt::fake_shared(mock_input_config_changer), std::vector<mir::ExtensionDescription>{},
2932+ allocator);
2933 }
2934
2935 std::shared_ptr<mf::SessionMediator> create_session_mediator_with_screencast(
2936@@ -325,7 +342,112 @@
2937 std::make_shared<NullCoordinateTranslator>(),
2938 std::make_shared<mtd::NullANRDetector>(),
2939 mir::cookie::Authority::create(),
2940- mt::fake_shared(mock_input_config_changer), std::vector<mir::ExtensionDescription>{});
2941+ mt::fake_shared(mock_input_config_changer), std::vector<mir::ExtensionDescription>{},
2942+ allocator);
2943+ }
2944+
2945+ std::shared_ptr<mf::SessionMediator> create_session_mediator_with_event_sink(
2946+ std::shared_ptr<mf::EventSink> const& sink)
2947+ {
2948+ class WrappingEventSink : public mf::EventSink
2949+ {
2950+ public:
2951+ WrappingEventSink(std::shared_ptr<mf::EventSink> const& wrapped)
2952+ : wrapped{wrapped}
2953+ {
2954+ }
2955+
2956+ void handle_event(MirEvent const &e) override
2957+ {
2958+ wrapped->handle_event(e);
2959+ }
2960+
2961+ void handle_lifecycle_event(MirLifecycleState state) override
2962+ {
2963+ wrapped->handle_lifecycle_event(state);
2964+ }
2965+
2966+ void handle_display_config_change(
2967+ mg::DisplayConfiguration const& config) override
2968+ {
2969+ wrapped->handle_display_config_change(config);
2970+ }
2971+
2972+ void send_ping(int32_t serial) override
2973+ {
2974+ wrapped->send_ping(serial);
2975+ }
2976+
2977+ void handle_input_config_change(MirInputConfig const& config) override
2978+ {
2979+ wrapped->handle_input_config_change(config);
2980+ }
2981+
2982+ void handle_error(mir::ClientVisibleError const& error) override
2983+ {
2984+ wrapped->handle_error(error);
2985+ }
2986+
2987+ void send_buffer(
2988+ mf::BufferStreamId id,
2989+ mg::Buffer& buffer,
2990+ mg::BufferIpcMsgType type) override
2991+ {
2992+ wrapped->send_buffer(id, buffer, type);
2993+ }
2994+
2995+ void add_buffer(mg::Buffer& buffer) override
2996+ {
2997+ wrapped->add_buffer(buffer);
2998+ }
2999+
3000+ void error_buffer(
3001+ geom::Size req_size,
3002+ MirPixelFormat req_format,
3003+ std::string const &error_msg) override
3004+ {
3005+ wrapped->error_buffer(req_size, req_format, error_msg);
3006+ }
3007+
3008+ void update_buffer(mg::Buffer &buffer) override
3009+ {
3010+ wrapped->update_buffer(buffer);
3011+ }
3012+
3013+ private:
3014+ std::shared_ptr<mf::EventSink> const wrapped;
3015+ };
3016+
3017+ class EventSinkFactory : public mf::EventSinkFactory
3018+ {
3019+ public:
3020+ EventSinkFactory(std::shared_ptr<mf::EventSink> const& sink)
3021+ : the_sink{sink}
3022+ {
3023+ }
3024+
3025+ std::unique_ptr<mf::EventSink> create_sink(
3026+ std::shared_ptr<mf::MessageSender> const&) override
3027+ {
3028+ return std::make_unique<WrappingEventSink>(the_sink);
3029+ }
3030+
3031+ private:
3032+ std::shared_ptr<mf::EventSink> const the_sink;
3033+ };
3034+
3035+ return std::make_shared<mf::SessionMediator>(
3036+ shell, mt::fake_shared(mock_ipc_operations), graphics_changer,
3037+ surface_pixel_formats, report,
3038+ std::make_shared<EventSinkFactory>(sink),
3039+ std::make_shared<mtd::NullMessageSender>(),
3040+ resource_cache, stub_screencast, &connector, nullptr,
3041+ std::make_shared<NullCoordinateTranslator>(),
3042+ std::make_shared<mtd::NullANRDetector>(),
3043+ mir::cookie::Authority::create(),
3044+ mt::fake_shared(mock_input_config_changer),
3045+ std::vector<mir::ExtensionDescription>{},
3046+ allocator);
3047 }
3048
3049 MockConnector connector;
3050@@ -339,6 +461,7 @@
3051 std::shared_ptr<StubScreencast> const stub_screencast;
3052 std::shared_ptr<NiceMock<StubbedSession>> const stubbed_session;
3053 std::unique_ptr<google::protobuf::Closure> null_callback;
3054+ std::shared_ptr<RecordingBufferAllocator> const allocator;
3055 mf::SessionMediator mediator;
3056
3057 mp::ConnectParameters connect_parameters;
3058@@ -383,7 +506,8 @@
3059 std::make_shared<NullCoordinateTranslator>(),
3060 std::make_shared<mtd::NullANRDetector>(),
3061 mir::cookie::Authority::create(),
3062- mt::fake_shared(mock_input_config_changer), {}};
3063+ mt::fake_shared(mock_input_config_changer), {},
3064+ allocator};
3065
3066 EXPECT_THAT(connects_handled_count, Eq(0));
3067
3068@@ -413,21 +537,6 @@
3069 }, std::logic_error);
3070 }
3071
3072-TEST_F(SessionMediator, calling_methods_after_connect_works)
3073-{
3074- mediator.connect(&connect_parameters, &connection, null_callback.get());
3075-
3076- EXPECT_NO_THROW({
3077- mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
3078- *buffer_request.mutable_buffer() = surface_response.buffer_stream().buffer();
3079- buffer_request.mutable_id()->set_value(surface_response.id().value());
3080- mediator.submit_buffer(&buffer_request, nullptr, null_callback.get());
3081- mediator.release_surface(&surface_id_request, nullptr, null_callback.get());
3082- });
3083-
3084- mediator.disconnect(nullptr, nullptr, null_callback.get());
3085-}
3086-
3087 TEST_F(SessionMediator, calling_methods_after_disconnect_throws)
3088 {
3089 mediator.connect(&connect_parameters, &connection, null_callback.get());
3090@@ -701,15 +810,20 @@
3091 mediator.modify_surface(&mods, &null, null_callback.get());
3092 }
3093
3094-TEST_F(SessionMediator, allocates_software_buffers_from_the_session)
3095+TEST_F(SessionMediator, allocates_software_buffers)
3096 {
3097 using namespace testing;
3098+
3099+ auto sink = std::make_shared<NiceMock<mtd::MockEventSink>>();
3100+ auto mediator = create_session_mediator_with_event_sink(sink);
3101+
3102+ mediator->connect(&connect_parameters, &connection, null_callback.get());
3103+ mediator->create_surface(&surface_parameters, &surface_response, null_callback.get());
3104+
3105 auto num_requests = 3;
3106 mp::Void null;
3107- mp::BufferStreamId id;
3108- id.set_value(0);
3109 mp::BufferAllocation request;
3110- *request.mutable_id() = id;
3111+ *request.mutable_id() = surface_response.buffer_stream().id();
3112 mg::BufferProperties properties(geom::Size{34, 84}, mir_pixel_format_abgr_8888, mg::BufferUsage::hardware);
3113 for(auto i = 0; i < num_requests; i++)
3114 {
3115@@ -720,58 +834,79 @@
3116 buffer_request->set_buffer_usage((int)properties.usage);
3117 }
3118
3119- mediator.connect(&connect_parameters, &connection, null_callback.get());
3120- mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
3121
3122- mediator.allocate_buffers(&request, &null, null_callback.get());
3123- EXPECT_THAT(stubbed_session->num_alloc_requests(), Eq(num_requests));
3124+ EXPECT_CALL(*sink, add_buffer(_)).Times(num_requests);
3125+ EXPECT_CALL(*sink, error_buffer(_,_,_)).Times(0);
3126+ mediator->allocate_buffers(&request, &null, null_callback.get());
3127+ EXPECT_THAT(allocator->allocated_buffers.size(), Eq(num_requests));
3128 }
3129
3130-TEST_F(SessionMediator, allocates_native_buffers_from_the_session)
3131+TEST_F(SessionMediator, allocates_native_buffers)
3132 {
3133 using namespace testing;
3134+
3135+ auto sink = std::make_shared<NiceMock<mtd::MockEventSink>>();
3136+ auto mediator = create_session_mediator_with_event_sink(sink);
3137+
3138+ mediator->connect(&connect_parameters, &connection, null_callback.get());
3139+ mediator->create_surface(&surface_parameters, &surface_response, null_callback.get());
3140+
3141 geom::Size const size { 1029, 10302 };
3142 auto native_flags = 24u;
3143 auto native_format = 124u;
3144 mp::Void null;
3145- mp::BufferStreamId id;
3146- id.set_value(0);
3147 mp::BufferAllocation request;
3148- *request.mutable_id() = id;
3149+ *request.mutable_id() = surface_response.buffer_stream().id();
3150 auto buffer_request = request.add_buffer_requests();
3151 buffer_request->set_width(size.width.as_int());
3152 buffer_request->set_height(size.height.as_int());
3153 buffer_request->set_native_format(native_format);
3154 buffer_request->set_flags(native_flags);
3155
3156- mediator.connect(&connect_parameters, &connection, null_callback.get());
3157- mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
3158-
3159- mediator.allocate_buffers(&request, &null, null_callback.get());
3160- EXPECT_THAT(stubbed_session->native_buffer_count, Eq(1));
3161+ EXPECT_CALL(*sink, add_buffer(_)).Times(1);
3162+ EXPECT_CALL(*sink, error_buffer(_,_,_)).Times(0);
3163+ mediator->allocate_buffers(&request, &null, null_callback.get());
3164+ EXPECT_THAT(allocator->allocated_buffers.size(), Eq(1));
3165 }
3166
3167-TEST_F(SessionMediator, removes_buffer_from_the_session)
3168+TEST_F(SessionMediator, removes_buffer)
3169 {
3170 using namespace testing;
3171 auto num_requests = 3;
3172 mp::Void null;
3173- mp::BufferStreamId id;
3174- id.set_value(0);
3175 mp::BufferRelease request;
3176- *request.mutable_id() = id;
3177- auto buffer_id = 442u;
3178+
3179+ // Allocate some buffers so we can release them later...
3180+ mp::BufferAllocation allocate_request;
3181 for(auto i = 0; i < num_requests; i++)
3182 {
3183- auto buffer_request = request.add_buffers();
3184- buffer_request->set_buffer_id(buffer_id);
3185+ auto allocate = allocate_request.add_buffer_requests();
3186+ allocate->set_buffer_usage(static_cast<int32_t>(mg::BufferUsage::software));
3187+ allocate->set_pixel_format(mir_pixel_format_abgr_8888);
3188+ allocate->set_width(640);
3189+ allocate->set_height(480);
3190 }
3191
3192 mediator.connect(&connect_parameters, &connection, null_callback.get());
3193- mediator.create_surface(&surface_parameters, &surface_response, null_callback.get());
3194-
3195+ mediator.allocate_buffers(&allocate_request, &null, null_callback.get());
3196+
3197+ ASSERT_THAT(allocator->allocated_buffers.size(), Eq(num_requests));
3198+
3199+ // ...Pull out the BufferIDs of the buffers we've allocated...
3200+ for (auto weak_buffer : allocator->allocated_buffers)
3201+ {
3202+ auto buffer = weak_buffer.lock();
3203+ ASSERT_THAT(buffer, NotNull());
3204+
3205+ auto release_buffer = request.add_buffers();
3206+ release_buffer->set_buffer_id(buffer->id().as_value());
3207+ }
3208+
3209+ // ...and now release all those buffers.
3210 mediator.release_buffers(&request, &null, null_callback.get());
3211- EXPECT_THAT(stubbed_session->num_destroy_requests(), Eq(num_requests));
3212+ EXPECT_THAT(
3213+ allocator->allocated_buffers,
3214+ Each(Property(&std::weak_ptr<mg::Buffer>::expired, Eq(true))));
3215 }
3216
3217 TEST_F(SessionMediator, configures_swap_intervals_on_streams)
3218@@ -861,7 +996,8 @@
3219 std::make_shared<NullCoordinateTranslator>(),
3220 std::make_shared<mtd::NullANRDetector>(),
3221 mir::cookie::Authority::create(),
3222- mt::fake_shared(mock_input_config_changer), {}};
3223+ mt::fake_shared(mock_input_config_changer), {},
3224+ allocator};
3225
3226 ON_CALL(*shell, create_surface( _, _, _))
3227 .WillByDefault(
3228@@ -1022,22 +1158,49 @@
3229 TEST_F(SessionMediator, disassociates_buffers_from_stream_before_destroying)
3230 {
3231 mp::BufferRelease release_buffer;
3232+ mp::BufferAllocation allocate_buffer;
3233 mp::Void null;
3234
3235+ // Add a fake BufferStream...
3236 auto stream_id = mf::BufferStreamId{42};
3237- auto buffer_id = mir::graphics::BufferID{42};
3238 auto stream = stubbed_session->create_mock_stream(stream_id);
3239- auto buffer1 = std::make_shared<mtd::StubBuffer>();
3240+
3241+ // ...and allocate a buffer to it
3242+ allocate_buffer.mutable_id()->set_value(42);
3243+ auto buffer_props = allocate_buffer.add_buffer_requests();
3244+ buffer_props->set_buffer_usage(0);
3245+ buffer_props->set_pixel_format(0);
3246+ buffer_props->set_width(230);
3247+ buffer_props->set_height(230);
3248+
3249+ mediator.connect(&connect_parameters, &connection, null_callback.get());
3250+ mediator.allocate_buffers(&allocate_buffer, &null, null_callback.get());
3251+
3252+ ASSERT_THAT(allocator->allocated_buffers.size(), Eq(1));
3253+ auto allocated_buffer = allocator->allocated_buffers.front().lock();
3254+ ASSERT_THAT(allocated_buffer, NotNull());
3255+
3256+ auto const buffer_id = allocated_buffer->id();
3257+
3258+ // Release our share of the buffer ownership.
3259+ allocated_buffer.reset();
3260
3261 auto buffer_item = release_buffer.add_buffers();
3262 buffer_item->set_buffer_id(buffer_id.as_value());
3263 release_buffer.mutable_id()->set_value(stream_id.as_value());
3264
3265- EXPECT_CALL(*stream, disassociate_buffer(buffer_id));
3266- EXPECT_CALL(*stubbed_session, destroy_buffer(buffer_id));
3267+ EXPECT_CALL(*stream, disassociate_buffer(buffer_id))
3268+ .WillOnce(InvokeWithoutArgs(
3269+ [weak_buffer = allocator->allocated_buffers.front()]()
3270+ {
3271+ // The buffer should be live here!
3272+ EXPECT_THAT(weak_buffer.lock(), NotNull());
3273+ }));
3274
3275- mediator.connect(&connect_parameters, &connection, null_callback.get());
3276 mediator.release_buffers(&release_buffer, &null, null_callback.get());
3277+
3278+ // And now we expect the buffer to have been destroyed.
3279+ EXPECT_THAT(allocator->allocated_buffers.front().lock(), IsNull());
3280 }
3281
3282 TEST_F(SessionMediator, releases_buffers_of_unknown_buffer_stream_does_not_throw)
3283@@ -1046,10 +1209,30 @@
3284 mp::BufferRelease release_buffer;
3285 mp::Void null;
3286
3287+ // Add a fake BufferStream...
3288 auto stream_id = mf::BufferStreamId{42};
3289- auto buffer_id = mir::graphics::BufferID{42};
3290 auto stream = stubbed_session->create_mock_stream(stream_id);
3291- auto buffer1 = std::make_shared<mtd::StubBuffer>();
3292+
3293+ // ...and allocate a buffer to it
3294+ mp::BufferAllocation allocate_buffer;
3295+ allocate_buffer.mutable_id()->set_value(42);
3296+ auto buffer_props = allocate_buffer.add_buffer_requests();
3297+ buffer_props->set_buffer_usage(0);
3298+ buffer_props->set_pixel_format(0);
3299+ buffer_props->set_width(230);
3300+ buffer_props->set_height(230);
3301+
3302+ mediator.connect(&connect_parameters, &connection, null_callback.get());
3303+ mediator.allocate_buffers(&allocate_buffer, &null, null_callback.get());
3304+
3305+ ASSERT_THAT(allocator->allocated_buffers.size(), Eq(1));
3306+ auto allocated_buffer = allocator->allocated_buffers.front().lock();
3307+ ASSERT_THAT(allocated_buffer, NotNull());
3308+
3309+ auto const buffer_id = allocated_buffer->id();
3310+
3311+ // Release our share of the buffer ownership.
3312+ allocated_buffer.reset();
3313
3314 auto buffer_item = release_buffer.add_buffers();
3315 buffer_item->set_buffer_id(buffer_id.as_value());
3316@@ -1058,15 +1241,15 @@
3317 stream_to_release.set_value(stream_id.as_value());
3318
3319 EXPECT_CALL(*stubbed_session, destroy_buffer_stream(stream_id));
3320- EXPECT_CALL(*stubbed_session, destroy_buffer(buffer_id));
3321
3322- mediator.connect(&connect_parameters, &connection, null_callback.get());
3323 mediator.release_buffer_stream(&stream_to_release, &null, null_callback.get());
3324 stream.reset();
3325
3326 EXPECT_NO_THROW(
3327 mediator.release_buffers(&release_buffer, &null, null_callback.get());
3328 );
3329+
3330+ EXPECT_TRUE(allocator->allocated_buffers.front().expired());
3331 }
3332
3333 MATCHER_P3(CursorIs, id_value, x_value, y_value, "cursor configuration match")
3334@@ -1165,7 +1348,6 @@
3335 buffer_request->set_height(129);
3336 buffer_request->set_pixel_format(mir_pixel_format_abgr_8888);
3337 buffer_request->set_buffer_usage(mir_buffer_usage_hardware);
3338- int buffer_id = 3;
3339 mf::ScreencastSessionId screencast_id{7};
3340 auto mock_screencast = std::make_shared<NiceMock<mtd::MockScreencast>>();
3341
3342@@ -1181,7 +1363,180 @@
3343 mp::ScreencastRequest screencast_request;
3344
3345 screencast_request.mutable_id()->set_value(screencast_id.as_value());
3346- screencast_request.set_buffer_id(buffer_id);
3347+ screencast_request.set_buffer_id(allocator->allocated_buffers.front().lock()->id().as_value());
3348
3349 mediator->screencast_to_buffer(&screencast_request, &null, null_callback.get());
3350 }
3351+
3352+namespace
3353+{
3354+void add_software_buffer_request(
3355+ mp::BufferAllocation& request,
3356+ int width,
3357+ int height,
3358+ MirPixelFormat format)
3359+{
3360+ auto buffer_request = request.add_buffer_requests();
3361+ buffer_request->set_width(width);
3362+ buffer_request->set_height(height);
3363+ buffer_request->set_pixel_format(format);
3364+ buffer_request->set_buffer_usage(static_cast<int>(mg::BufferUsage::software));
3365+}
3366+
3367+void add_hardware_request(
3368+ mp::BufferAllocation& request,
3369+ int width,
3370+ int height,
3371+ int native_format,
3372+ int flags)
3373+{
3374+ auto buffer_request = request.add_buffer_requests();
3375+
3376+ buffer_request->set_width(width);
3377+ buffer_request->set_height(height);
3378+ buffer_request->set_native_format(native_format);
3379+ buffer_request->set_flags(flags);
3380+}
3381+}
3382+
3383+TEST_F(SessionMediator, invalid_buffer_stream_in_software_buffer_allocation_sends_only_error_buffer)
3384+{
3385+ using namespace testing;
3386+
3387+ auto sink = std::make_shared<NiceMock<mtd::MockEventSink>>();
3388+ auto mediator = create_session_mediator_with_event_sink(sink);
3389+
3390+ mediator->connect(&connect_parameters, &connection, null_callback.get());
3391+
3392+ auto num_requests = 3;
3393+ mp::Void null;
3394+ mp::BufferAllocation request;
3395+ request.mutable_id()->set_value(-1);
3396+ mg::BufferProperties properties(geom::Size{34, 84}, mir_pixel_format_abgr_8888, mg::BufferUsage::software);
3397+ for(auto i = 0; i < num_requests; i++)
3398+ {
3399+ add_software_buffer_request(
3400+ request,
3401+ properties.size.width.as_int(),
3402+ properties.size.height.as_int(),
3403+ properties.format);
3404+ }
3405+
3406+ EXPECT_CALL(*sink, add_buffer(_)).Times(0);
3407+ EXPECT_CALL(*sink, error_buffer(_,_,_)).Times(num_requests);
3408+ mediator->allocate_buffers(&request, &null, null_callback.get());
3409+ EXPECT_THAT(allocator->allocated_buffers.size(), Eq(num_requests));
3410+}
3411+
3412+TEST_F(SessionMediator, invalid_request_sends_error_buffer)
3413+{
3414+ using namespace testing;
3415+
3416+ auto sink = std::make_shared<NiceMock<mtd::MockEventSink>>();
3417+ auto mediator = create_session_mediator_with_event_sink(sink);
3418+
3419+ mediator->connect(&connect_parameters, &connection, null_callback.get());
3420+ mediator->create_surface(&surface_parameters, &surface_response, null_callback.get());
3421+
3422+ mp::Void null;
3423+ mp::BufferAllocation request;
3424+ *request.mutable_id() = surface_response.buffer_stream().id();
3425+
3426+ decltype(request.add_buffer_requests()) buffer_request;
3427+
3428+ // Loop through all possibilities of has_flags, has_native_format,
3429+ // has_buffer_usage, has_pixel_format
3430+ for (int i = 0 ; i < 1<<4; ++i)
3431+ {
3432+ buffer_request = request.add_buffer_requests();
3433+ buffer_request->set_width(1024);
3434+ buffer_request->set_height(768);
3435+
3436+ if (i & 1<<0)
3437+ buffer_request->set_flags(0xfaac);
3438+ if (i & 1<<1)
3439+ buffer_request->set_native_format(0xdeeb);
3440+ if (i & 1<<2)
3441+ buffer_request->set_pixel_format(mir_pixel_format_abgr_8888);
3442+ if (i & 1<<3)
3443+ buffer_request->set_buffer_usage(static_cast<int>(mg::BufferUsage::software));
3444+ }
3445+
3446+ // There are two valid allocations here - one with flags and native_format set,
3447+ // one with pixel_format and buffer_usage set.
3448+ EXPECT_CALL(*sink, add_buffer(_)).Times(2);
3449+
3450+ EXPECT_CALL(*sink, error_buffer(_,_,_)).Times(16 - 2);
3451+ mediator->allocate_buffers(&request, &null, null_callback.get());
3452+ EXPECT_THAT(allocator->allocated_buffers.size(), Eq(2));
3453+}
3454+
3455+TEST_F(SessionMediator, sends_errors_only_for_invalid_buffer_parameters)
3456+{
3457+ using namespace testing;
3458+
3459+ auto sink = std::make_shared<NiceMock<mtd::MockEventSink>>();
3460+ auto mediator = create_session_mediator_with_event_sink(sink);
3461+
3462+ mediator->connect(&connect_parameters, &connection, null_callback.get());
3463+ mediator->create_surface(&surface_parameters, &surface_response, null_callback.get());
3464+
3465+ auto const num_requests = 3;
3466+ mp::Void null;
3467+ mp::BufferAllocation request;
3468+ *request.mutable_id() = surface_response.buffer_stream().id();
3469+ mg::BufferProperties properties(geom::Size{34, 84}, mir_pixel_format_abgr_8888, mg::BufferUsage::software);
3470+ for(auto i = 0; i < num_requests; i++)
3471+ {
3472+ add_software_buffer_request(
3473+ request,
3474+ properties.size.width.as_int(),
3475+ properties.size.height.as_int(),
3476+ properties.format);
3477+ }
3478+
3479+ // Make the 2nd buffer request invalid, leaving the 1st and 3rd valid
3480+ request.mutable_buffer_requests(1)->set_pixel_format(mir_pixel_format_invalid);
3481+
3482+ EXPECT_CALL(*sink, add_buffer(_)).Times(num_requests - 1);
3483+ EXPECT_CALL(*sink, error_buffer(_,_,_)).Times(1);
3484+ mediator->allocate_buffers(&request, &null, null_callback.get());
3485+ EXPECT_THAT(allocator->allocated_buffers.size(), Eq(num_requests - 1));
3486+}
3487+
3488+TEST_F(SessionMediator, invalid_buffer_stream_in_native_buffer_allocation_sends_only_error_buffer)
3489+{
3490+ using namespace testing;
3491+
3492+ auto const num_requests = 3;
3493+
3494+ auto sink = std::make_shared<NiceMock<mtd::MockEventSink>>();
3495+ auto mediator = create_session_mediator_with_event_sink(sink);
3496+
3497+ mediator->connect(&connect_parameters, &connection, null_callback.get());
3498+
3499+ geom::Size const size { 1029, 10302 };
3500+ auto native_flags = 24u;
3501+ auto native_format = 124u;
3502+ mp::Void null;
3503+ mp::BufferAllocation request;
3504+ request.mutable_id()->set_value(42);
3505+
3506+ for (auto i = 0; i < num_requests; ++i)
3507+ {
3508+ add_hardware_request(
3509+ request,
3510+ size.width.as_int(),
3511+ size.height.as_int(),
3512+ native_format,
3513+ native_flags);
3514+ }
3515+
3516+ EXPECT_CALL(*sink, add_buffer(_)).Times(0);
3517+ EXPECT_CALL(*sink, error_buffer(_,_,_)).Times(num_requests);
3518+ mediator->allocate_buffers(&request, &null, null_callback.get());
3519+ // We don't much care if the buffers were allocated and then freed or never allocated
3520+ EXPECT_THAT(
3521+ allocator->allocated_buffers,
3522+ Each(Property(&std::weak_ptr<mg::Buffer>::expired, Eq(true))));
3523+}
3524
3525=== modified file 'tests/unit-tests/scene/test_application_session.cpp'
3526--- tests/unit-tests/scene/test_application_session.cpp 2017-05-25 04:43:29 +0000
3527+++ tests/unit-tests/scene/test_application_session.cpp 2017-07-19 05:46:21 +0000
3528@@ -63,17 +63,10 @@
3529
3530 struct MockBufferStreamFactory : public ms::BufferStreamFactory
3531 {
3532- MockBufferStreamFactory()
3533- {
3534- ON_CALL(*this, create_buffer_map(testing::_))
3535- .WillByDefault(testing::Return(std::make_shared<mtd::StubClientBuffers>()));
3536- }
3537+ MOCK_METHOD2(create_buffer_stream, std::shared_ptr<mc::BufferStream>(
3538+ mf::BufferStreamId, mg::BufferProperties const&));
3539 MOCK_METHOD3(create_buffer_stream, std::shared_ptr<mc::BufferStream>(
3540- mf::BufferStreamId, std::shared_ptr<mf::ClientBuffers> const&, mg::BufferProperties const&));
3541- MOCK_METHOD4(create_buffer_stream, std::shared_ptr<mc::BufferStream>(
3542- mf::BufferStreamId, std::shared_ptr<mf::ClientBuffers> const&, int, mg::BufferProperties const&));
3543- MOCK_METHOD1(create_buffer_map, std::shared_ptr<mf::ClientBuffers>(
3544- std::shared_ptr<mf::BufferSink> const&));
3545+ mf::BufferStreamId, int, mg::BufferProperties const&));
3546 };
3547
3548
3549@@ -488,7 +481,7 @@
3550 NiceMock<MockSurfaceFactory> surface_factory;
3551 MockBufferStreamFactory mock_buffer_stream_factory;
3552 std::shared_ptr<mc::BufferStream> const mock_stream = std::make_shared<mtd::MockBufferStream>();
3553- ON_CALL(mock_buffer_stream_factory, create_buffer_stream(_,_,_)).WillByDefault(Return(mock_stream));
3554+ ON_CALL(mock_buffer_stream_factory, create_buffer_stream(_,_)).WillByDefault(Return(mock_stream));
3555 ON_CALL(surface_factory, create_surface(_,_)).WillByDefault(Return(mock_surface));
3556 NiceMock<mtd::MockSurfaceStack> surface_stack;
3557
3558@@ -588,7 +581,7 @@
3559 std::make_shared<mtd::StubBufferStream>(),
3560 std::make_shared<mtd::StubBufferStream>()
3561 }};
3562- EXPECT_CALL(mock_bufferstream_factory, create_buffer_stream(_,_,_))
3563+ EXPECT_CALL(mock_bufferstream_factory, create_buffer_stream(_,_))
3564 .WillOnce(Return(streams[0]))
3565 .WillOnce(Return(streams[1]))
3566 .WillOnce(Return(streams[2]));
3567@@ -630,7 +623,7 @@
3568
3569 mg::BufferProperties properties(buffer_size, mir_pixel_format_argb_8888, mg::BufferUsage::software);
3570
3571- EXPECT_CALL(factory, create_buffer_stream(_,_,properties)).Times(1)
3572+ EXPECT_CALL(factory, create_buffer_stream(_,properties)).Times(1)
3573 .WillOnce(Return(mt::fake_shared(stream)));
3574
3575 auto session = make_application_session_with_buffer_stream_factory(mt::fake_shared(factory));
3576@@ -658,7 +651,7 @@
3577
3578 EXPECT_CALL(stream, allow_framedropping(true))
3579 .Times(0);
3580- EXPECT_CALL(factory, create_buffer_stream(_,_,properties)).Times(1)
3581+ EXPECT_CALL(factory, create_buffer_stream(_,properties)).Times(1)
3582 .WillOnce(Return(mt::fake_shared(stream)));
3583
3584 auto session = make_application_session_with_buffer_stream_factory(mt::fake_shared(factory));
3585
3586=== modified file 'tests/unit-tests/scene/test_surface_stack.cpp'
3587--- tests/unit-tests/scene/test_surface_stack.cpp 2017-05-08 03:04:26 +0000
3588+++ tests/unit-tests/scene/test_surface_stack.cpp 2017-07-19 05:46:21 +0000
3589@@ -289,17 +289,7 @@
3590 ms::SurfaceStack stack{report};
3591 stack.register_compositor(this);
3592
3593- struct StubBuffers : mtd::StubClientBuffers
3594- {
3595- std::shared_ptr<mg::Buffer> get(mg::BufferID) const override
3596- {
3597- return buffer;
3598- }
3599- std::shared_ptr<mg::Buffer> buffer {std::make_shared<mtd::StubBuffer>()};
3600- };
3601-
3602- auto buffers = std::make_shared<StubBuffers>();
3603- auto stream = std::make_shared<mc::Stream>(buffers, geom::Size{ 1, 1 }, mir_pixel_format_abgr_8888);
3604+ auto stream = std::make_shared<mc::Stream>(geom::Size{ 1, 1 }, mir_pixel_format_abgr_8888);
3605
3606 auto surface = std::make_shared<ms::BasicSurface>(
3607 std::string("stub"),

Subscribers

People subscribed via source and target branches