Mir

Merge lp:~alan-griffiths/mir/screenshot-to-buffer into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alberto Aguirre
Approved revision: no longer in the source branch.
Merged at revision: 4189
Proposed branch: lp:~alan-griffiths/mir/screenshot-to-buffer
Merge into: lp:mir
Diff against target: 877 lines (+487/-28)
16 files modified
examples/CMakeLists.txt (+4/-0)
examples/screencast.cpp (+149/-0)
include/client/mir_toolkit/mir_screencast.h (+39/-0)
include/test/mir/test/doubles/stub_session_authorizer.h (+6/-0)
src/client/mir_screencast.cpp (+59/-7)
src/client/mir_screencast.h (+25/-1)
src/client/mir_screencast_api.cpp (+37/-0)
src/client/symbols.map (+2/-0)
src/server/compositor/compositing_screencast.cpp (+42/-14)
src/server/compositor/compositing_screencast.h (+1/-2)
src/server/compositor/screencast_display_buffer.cpp (+30/-1)
src/server/compositor/screencast_display_buffer.h (+6/-0)
src/server/frontend/protobuf_message_processor.cpp (+1/-1)
src/server/frontend/session_mediator.cpp (+1/-1)
tests/acceptance-tests/test_client_screencast.cpp (+85/-0)
tests/unit-tests/compositor/test_compositing_screencast.cpp (+0/-1)
To merge this branch: bzr merge lp:~alan-griffiths/mir/screenshot-to-buffer
Reviewer Review Type Date Requested Status
Mir CI Bot continuous-integration Approve
Alberto Aguirre (community) Approve
Daniel van Vugt Pending
Mir development team Pending
Review via email: mp+324943@code.launchpad.net

This proposal supersedes a proposal from 2017-02-21.

Commit message

client: add mir_screencast_to_buffer and mir_screencast_to_buffer_sync. These allow for screencasting to a specific MirBuffer. Also add a small utility that shows these functions in use.

Description of the change

client: add mir_screencast_to_buffer and mir_screencast_to_buffer_sync. These allow for screencasting to a specific MirBuffer. Also add a small utility that shows these functions in use.

The tricky part in screencasting to a buffer is dealing with the differences that might arise because of platforms, pixel formats, etc. The current screencast stream will generate 'hardware buffers' and then send them to the client. On android, these buffers can be accessed directly. On mesa, the hardware buffers might be tiled, and the buffers are ran through a GL context to use glReadPixels.

The new system lets the user submit a buffer to the server to fill.
The function will return one of 3 MirErrors in the screencast domain, failed (something went wrong), unsupported (not supported), and performance_warning (operation completed, but may not have been optimal)

Also, the buffers come out in the correct mirror_mode (the current system flipped them)

The demo works with android 'software' buffers, and fails with mesa ShmBuffers currently. Allocating a mesa gbm buffer would work, but the user would have to do the same sort of thing that mirscreencast does with glReadPixels to make sense of the contents.

The eventual plan is to give more plumbing so that more format conversions and buffer combos will work. So, overtime, more things go from being unsupported to either working, or giving a 'performance_warning' in cases where we have to do a format conversion or buffer conversion.

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

FAILED: Continuous integration, rev:3964
https://mir-jenkins.ubuntu.com/job/mir-ci/3035/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4055/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4142
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4132
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4132
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4132
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4082/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4082/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4082/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4082
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4082/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4082
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4082/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4082/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

+++ include/client/mir_toolkit/mir_buffer.h 2017-02-21 22:04:27 +0000

+ void mir_screencast_capture_to_buffer(
+ MirError const* mir_screencast_capture_to_buffer_sync(MirScreencast* screencast, MirBuffer* buffer);

Shoudn't these be part of the screencast API (mir_screencast.h) rather than the buffer API?

+ if (request->response.has_error())
+ error = std::make_unique<MirError>(mir_error_domain_screencast, mir_screencast_error_failure);
+ else
+ error = nullptr;
+
+ request->available_callback(
+ reinterpret_cast<MirBuffer*>(request->buffer), error.get(), request->available_context);

We apparently support multiple concurrent screencast captures on the same object, but we share the error instance among them, leading to memory errors like:

auto const error1 = mir_screencast_capture_to_buffer(...);
auto const error2 = mir_screencast_capture_to_buffer(...);
// error1 now points to freed memory!

+ class CaptureSync

We can use std::promise<MirError*> instead (or our own no-TLS implementation if needed).

review: Needs Fixing
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote : Posted in a previous version of this proposal

FAILED: Continuous integration, rev:3968
https://mir-jenkins.ubuntu.com/job/mir-ci/3102/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4160/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4247
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=vivid+overlay/4237
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial+overlay/4237
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4237
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4187/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial+overlay/4187/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4187/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4187
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=android,release=vivid+overlay/4187/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4187
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=android,release=vivid+overlay/4187/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial+overlay/4187/console

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> add warning about the limited lifetime of MirError

I don't think a warning is enough. The shared error subtly limits the interface to only one screencast in flight at any time. Another example with async requests:

void callback(buffer, error, context)
{
    // It's not safe to access error here!
}

mir_screencast_capture_to_buffer(buffer1, callback);
mir_screencast_capture_to_buffer(buffer2, callback);

We either need to fix the shared error problem so that concurrent requests can work safely, or, alternatively, explicitly disallow concurrent requests (e.g. abort() if detected).

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I think the long term future of screencasting lays in fixing bug 1660269. Any buffer shared with a screencasting client should be linear and not require any GL code on the client side.

So that's just a reminder. I won't stand in the way of progress...

review: Abstain
Revision history for this message
Alberto Aguirre (albaguirre) wrote : Posted in a previous version of this proposal

MirError const* mir_screencast_capture_to_buffer_sync(MirScreencast* screencast, MirBuffer* buffer);

I think returning a MirError here can lead to the same lifetime issues we had with wait handles.

We need an explicit "mir_error_release" at the very least.

review: Needs Fixing
Revision history for this message
Alexandros Frantzis (afrantzis) : Posted in a previous version of this proposal
review: Abstain
Revision history for this message
Mir CI Bot (mir-ci-bot) wrote :

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

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

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

FAILED: Continuous integration, rev:4184
https://mir-jenkins.ubuntu.com/job/mir-ci/3434/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4678/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4811
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4801
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4801
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4801
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4714/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4714/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4714/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4714/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4714/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4714
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4714/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/4714
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4714/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4714/console

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

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

FAILED: Continuous integration, rev:4187
https://mir-jenkins.ubuntu.com/job/mir-ci/3435/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4679/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4812
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4802
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4802
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4802
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4715/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4715/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4715/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4715/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4715/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4715
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4715/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/4715
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4715/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4715/console

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

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

FAILED: Continuous integration, rev:4188
https://mir-jenkins.ubuntu.com/job/mir-ci/3436/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4680/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4813
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4803
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4803
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4803
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4716/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4716/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4716/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4716/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4716/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/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4716/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/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4716/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4716
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4716/artifact/output/*zip*/output.zip

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

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

FAILED: Continuous integration, rev:4188
https://mir-jenkins.ubuntu.com/job/mir-ci/3437/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4681/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4814
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4804
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4804
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4804
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4717/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4717
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4717/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4717
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4717/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4717/console
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4717/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4717
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4717/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/4717
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4717/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4717/console

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

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

FAILED: Continuous integration, rev:4189
https://mir-jenkins.ubuntu.com/job/mir-ci/3440/
Executed test runs:
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-mir/4684/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4817
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4807
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4807
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4807
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4720/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4720/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4720/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4720/artifact/output/*zip*/output.zip
    FAILURE: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4720/console
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4720/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/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4720/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4720
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4720/artifact/output/*zip*/output.zip

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

review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Four cross process tests failing:

14:34:04 11: [ FAILED ] ServerDisconnect.is_detected_by_client
14:34:04 11: [ FAILED ] ServerDisconnect.doesnt_stop_client_calling_API_functions
14:34:04 11: [ FAILED ] ServerStartup.creates_endpoint_on_filesystem
14:34:04 11: [ FAILED ] ServerStartup.after_server_sigkilled_can_start_new_instance

Typically,

"14:29:22 11: ==3081== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)"

Which looks like a valgrind error "inherited" from an earlier test (presumably Screencast.*) but where is that detailed?

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Oh...

From NestedServerWithTwoDisplays_uses_passthrough_when_surface_size_is_appropriate_Test::TestBody()

14:28:02 11: ==2818== Thread 6 Mir/Input Reade:
14:28:02 11: ==2818== Invalid read of size 8

Looks unrelated to this MP.

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

PASSED: Continuous integration, rev:4189
https://mir-jenkins.ubuntu.com/job/mir-ci/3441/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4685
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4818
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4808
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4808
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4808
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4722/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4722/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4722/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4722/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4722/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/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4722/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/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4722/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4722
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4722/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

Comments inline,

Mainly removing the enum values that are not used as well as the error domain.

And some nitpicks in the example code.

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

PASSED: Continuous integration, rev:4191
https://mir-jenkins.ubuntu.com/job/mir-ci/3445/
Executed test runs:
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-mir/4691
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-0-fetch/4826
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=artful/4816
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=xenial/4816
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-1-sourcepkg/release=zesty/4816
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=artful/4728/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=clang,platform=mesa,release=zesty/4728/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=artful/4728/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=xenial/4728/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=amd64,compiler=gcc,platform=mesa,release=zesty/4728/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/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=artful/4728/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/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=cross-armhf,compiler=gcc,platform=mesa,release=zesty/4728/artifact/output/*zip*/output.zip
    SUCCESS: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4728
        deb: https://mir-jenkins.ubuntu.com/job/build-2-binpkg-mir/arch=i386,compiler=gcc,platform=mesa,release=xenial/4728/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

LGTM

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'examples/CMakeLists.txt'
2--- examples/CMakeLists.txt 2017-06-05 11:06:24 +0000
3+++ examples/CMakeLists.txt 2017-06-06 16:26:39 +0000
4@@ -312,3 +312,7 @@
5 target_link_libraries(mir_demo_client_chain_jumping_buffers
6 mirclient
7 )
8+
9+mir_add_wrapped_executable(mir_demo_client_screencast screencast.cpp)
10+
11+target_link_libraries(mir_demo_client_screencast mirclient)
12
13=== added file 'examples/screencast.cpp'
14--- examples/screencast.cpp 1970-01-01 00:00:00 +0000
15+++ examples/screencast.cpp 2017-06-06 16:26:39 +0000
16@@ -0,0 +1,149 @@
17+/*
18+ * Copyright © 2017 Canonical Ltd.
19+ *
20+ * This program is free software: you can redistribute it and/or modify
21+ * it under the terms of the GNU General Public License version 3 as
22+ * published by the Free Software Foundation.
23+ *
24+ * This program is distributed in the hope that it will be useful,
25+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
26+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27+ * GNU General Public License for more details.
28+ *
29+ * You should have received a copy of the GNU General Public License
30+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
31+ *
32+ * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
33+ */
34+
35+#include "mir_toolkit/mir_client_library.h"
36+#include "mir_toolkit/mir_screencast.h"
37+#include "mir_toolkit/mir_buffer.h"
38+#include <memory>
39+#include <iostream>
40+#include <unistd.h>
41+#include <getopt.h>
42+#include <fstream>
43+
44+int main(int argc, char *argv[])
45+try
46+{
47+ int arg = -1;
48+ static char const* socket_file = NULL;
49+ static char const* output_file = "screencap_output.raw";
50+ unsigned int width = 400;
51+ unsigned int height = 300;
52+
53+ auto disp_id = 0;
54+ while ((arg = getopt (argc, argv, "m:f:d:s:h:")) != -1)
55+ {
56+ switch (arg)
57+ {
58+ case 'm':
59+ socket_file = optarg;
60+ break;
61+ case 'f':
62+ output_file = optarg;
63+ break;
64+ case 'd':
65+ disp_id = atoi(optarg);
66+ break;
67+ case 's':
68+ if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0)
69+ {
70+ std::cerr << "could not parse size " << optarg << '\n';
71+ return -1;
72+ }
73+ break;
74+ case 'h':
75+ default:
76+ std::cout << argv[0] << std::endl;
77+ std::cout << "Usage:\n";
78+ std::cout << " -m <Mir server socket>\n";
79+ std::cout << " -f file to output to\n";
80+ std::cout << " -d output id to capture\n";
81+ std::cout << " -s size of capture buffer (WxH)\n";
82+ std::cout << " -h help dialog\n";
83+ return -1;
84+ }
85+ }
86+
87+ int rc = 0;
88+ auto connection = mir_connect_sync(socket_file, "screencap_to_buffer");
89+ if (!mir_connection_is_valid(connection))
90+ {
91+ std::cerr << "could not connect to server\n";
92+ return -1;
93+ }
94+
95+ auto display_config = mir_connection_create_display_configuration(connection);
96+ if (disp_id < 0 || disp_id > mir_display_config_get_num_outputs(display_config))
97+ {
98+ std::cerr << "invalid display id set\n";
99+ return -1;
100+ }
101+
102+ auto output = mir_display_config_get_output(display_config, disp_id);
103+ auto mode = mir_output_get_current_mode(output);
104+
105+ auto pf = mir_pixel_format_abgr_8888;
106+ MirRectangle rect {
107+ mir_output_get_position_x(output),
108+ mir_output_get_position_y(output),
109+ static_cast<unsigned int>(mir_output_mode_get_width(mode)),
110+ static_cast<unsigned int>(mir_output_mode_get_height(mode)) };
111+ mir_display_config_release(display_config);
112+
113+ auto spec = mir_create_screencast_spec(connection);
114+ mir_screencast_spec_set_capture_region(spec, &rect);
115+ mir_screencast_spec_set_mirror_mode(spec, mir_mirror_mode_horizontal);
116+ //TODO: the default screencast spec will capture a buffer when creating the screencast.
117+ // Set to zero to avoid this, and when the old screencast-bufferstream method is removed,
118+ // the initial capture will be removed.
119+ mir_screencast_spec_set_number_of_buffers(spec, 0);
120+
121+ auto screencast = mir_screencast_create_sync(spec);
122+ mir_screencast_spec_release(spec);
123+
124+ auto buffer = mir_connection_allocate_buffer_sync(connection, width, height, pf);
125+
126+ if (auto status = mir_screencast_capture_to_buffer_sync(screencast, buffer))
127+ {
128+ switch (status)
129+ {
130+ case mir_screencast_error_failure:
131+ std::cerr << "screencast failed" << std::endl;
132+ rc = -1;
133+ break;
134+ default:
135+ break;
136+ }
137+ }
138+
139+ std::ofstream file(output_file);
140+ if (!rc && output)
141+ {
142+ MirBufferLayout layout;
143+ MirGraphicsRegion region;
144+ mir_buffer_map(buffer, &region, &layout);
145+
146+ auto addr = region.vaddr;
147+ for (int i = 0; i < region.height; i++)
148+ {
149+ file.write(addr, region.width * MIR_BYTES_PER_PIXEL(pf));
150+ addr += region.stride;
151+ }
152+
153+ mir_buffer_unmap(buffer);
154+ }
155+
156+ mir_buffer_release(buffer);
157+ mir_screencast_release_sync(screencast);
158+ mir_connection_release(connection);
159+ return EXIT_SUCCESS;
160+}
161+catch(std::exception& e)
162+{
163+ std::cerr << "error : " << e.what() << std::endl;
164+ return EXIT_FAILURE;
165+}
166
167=== modified file 'include/client/mir_toolkit/mir_screencast.h'
168--- include/client/mir_toolkit/mir_screencast.h 2017-05-25 08:58:03 +0000
169+++ include/client/mir_toolkit/mir_screencast.h 2017-06-06 16:26:39 +0000
170@@ -28,6 +28,22 @@
171 extern "C" {
172 #endif
173
174+typedef enum MirScreencastResult
175+{
176+ /**
177+ * Screencasting to the MirBuffer succeeded.
178+ */
179+ mir_screencast_success,
180+
181+ /**
182+ * Screencasting failed.
183+ */
184+ mir_screencast_error_failure,
185+} MirScreencastResult;
186+
187+typedef void (*MirScreencastBufferCallback)(
188+ MirScreencastResult status, MirBuffer* buffer, void* context);
189+
190 /**
191 * Create a screencast specification.
192 *
193@@ -161,6 +177,29 @@
194 */
195 MirBufferStream* mir_screencast_get_buffer_stream(MirScreencast* screencast);
196
197+/** Capture the contents of the screen to a particular buffer.
198+ *
199+ * \param [in] screencast The screencast
200+ * \param [in] buffer The buffer
201+ * \param [in] available_callback Callback triggered when buffer is available again
202+ * \param [in] available_context The context for the above callback
203+ **/
204+void mir_screencast_capture_to_buffer(
205+ MirScreencast* screencast,
206+ MirBuffer* buffer,
207+ MirScreencastBufferCallback available_callback, void* available_context);
208+
209+/** Capture the contents of the screen to a particular buffer and wait for the
210+ * capture to complete.
211+ *
212+ * \warning The returned MirError will be valid until the next call
213+ * to mir_screencast_capture_to_buffer or mir_screencast_capture_to_buffer_sync.
214+ * \param [in] screencast The screencast
215+ * \param [in] buffer The buffer
216+ * \return The error condition
217+ **/
218+MirScreencastResult mir_screencast_capture_to_buffer_sync(MirScreencast* screencast, MirBuffer* buffer);
219+
220 #ifdef __cplusplus
221 }
222 /**@}*/
223
224=== renamed file 'tests/include/mir/test/doubles/mock_gl.h' => 'include/test/mir/test/doubles/mock_gl.h'
225=== modified file 'include/test/mir/test/doubles/stub_session_authorizer.h'
226--- include/test/mir/test/doubles/stub_session_authorizer.h 2017-05-08 03:04:26 +0000
227+++ include/test/mir/test/doubles/stub_session_authorizer.h 2017-06-06 16:26:39 +0000
228@@ -20,6 +20,7 @@
229 #define MIR_TEST_DOUBLES_STUB_SESSION_AUTHORIZER_H_
230
231 #include "mir/frontend/session_authorizer.h"
232+#include <gmock/gmock.h>
233
234 namespace mir
235 {
236@@ -60,6 +61,11 @@
237 }
238 };
239
240+struct MockSessionAuthorizer : StubSessionAuthorizer
241+{
242+ MOCK_METHOD1(screencast_is_allowed, bool(frontend::SessionCredentials const&));
243+};
244+
245 }
246 }
247 } // namespace mir
248
249=== modified file 'src/client/mir_screencast.cpp'
250--- src/client/mir_screencast.cpp 2017-05-08 03:04:26 +0000
251+++ src/client/mir_screencast.cpp 2017-06-06 16:26:39 +0000
252@@ -21,10 +21,12 @@
253 #include "mir_protobuf.pb.h"
254 #include "make_protobuf_object.h"
255 #include "mir/mir_buffer_stream.h"
256+#include "mir/mir_buffer.h"
257 #include "mir/frontend/client_constants.h"
258 #include "mir_toolkit/mir_native_buffer.h"
259
260 #include <boost/throw_exception.hpp>
261+#include <algorithm>
262
263 namespace mcl = mir::client;
264 namespace mp = mir::protobuf;
265@@ -55,6 +57,16 @@
266 message.mutable_region()->set_height(region.height);
267 }
268
269+ if (spec.num_buffers.is_set() && spec.num_buffers.value() == 0)
270+ {
271+ if (!spec.pixel_format.is_set())
272+ message.set_pixel_format(mir_pixel_format_abgr_8888);
273+ if (!spec.width.is_set())
274+ message.set_width(1);
275+ if (!spec.width.is_set())
276+ message.set_height(1);
277+ }
278+
279 return message;
280 }
281
282@@ -72,9 +84,6 @@
283
284 #define THROW_IF_ZERO(option) THROW_IF_EQ(option, 0)
285
286- THROW_IF_ZERO(width);
287- THROW_IF_ZERO(height);
288- THROW_IF_EQ(pixel_format, mir_pixel_format_invalid);
289 THROW_IF_UNSET(capture_region);
290
291 if (spec.capture_region.is_set())
292@@ -85,6 +94,14 @@
293 if (region.height == 0)
294 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid capture region height"));
295 }
296+
297+ //zero nbuffers don't need to set pixel format, width, or height
298+ if (!spec.num_buffers.is_set() || spec.num_buffers.value() > 0)
299+ {
300+ THROW_IF_ZERO(width);
301+ THROW_IF_ZERO(height);
302+ THROW_IF_EQ(pixel_format, mir_pixel_format_invalid);
303+ }
304 }
305 }
306
307@@ -180,13 +197,13 @@
308 void MirScreencast::screencast_created(
309 MirScreencastCallback callback, void* context)
310 {
311- if (!protobuf_screencast->has_error() && connection)
312+ if (connection && !protobuf_screencast->has_error() &&
313+ protobuf_screencast->has_buffer_stream() && protobuf_screencast->buffer_stream().has_buffer())
314 {
315 std::lock_guard<decltype(mutex)> lock(mutex);
316 try
317 {
318- buffer_stream = connection->make_consumer_stream(
319- protobuf_screencast->buffer_stream());
320+ buffer_stream = connection->make_consumer_stream(protobuf_screencast->buffer_stream());
321 }
322 catch (...)
323 {
324@@ -207,7 +224,7 @@
325
326 {
327 std::lock_guard<decltype(mutex)> lock(mutex);
328- if (connection)
329+ if (buffer_stream)
330 connection->release_consumer_stream(buffer_stream.get());
331 buffer_stream.reset();
332 }
333@@ -219,3 +236,38 @@
334 std::lock_guard<decltype(mutex)> lock(mutex);
335 return buffer_stream.get();
336 }
337+
338+void MirScreencast::screencast_done(ScreencastRequest* request)
339+{
340+ auto const status = request->response.has_error() ? mir_screencast_error_failure : mir_screencast_success;
341+
342+ request->available_callback(status, reinterpret_cast<MirBuffer*>(request->buffer), request->available_context);
343+
344+ std::unique_lock<decltype(mutex)> lk(mutex);
345+ auto it = std::find_if(requests.begin(), requests.end(),
346+ [&request] (auto const& it) { return it.get() == request; } );
347+ if (it != requests.end())
348+ requests.erase(it);
349+}
350+
351+void MirScreencast::screencast_to_buffer(
352+ mcl::MirBuffer* buffer,
353+ MirScreencastBufferCallback cb,
354+ void* context)
355+{
356+ if (!server) //construction with nullptr should be invalid
357+ BOOST_THROW_EXCEPTION(std::runtime_error("invalid screencast"));
358+
359+ std::unique_lock<decltype(mutex)> lk(mutex);
360+
361+ requests.emplace_back(std::make_unique<ScreencastRequest>(buffer, cb, context));
362+
363+ mir::protobuf::ScreencastRequest request;
364+ request.set_buffer_id(buffer->rpc_id());
365+ request.mutable_id()->set_value(protobuf_screencast->screencast_id().value());
366+
367+ server->screencast_to_buffer(
368+ &request,
369+ &(requests.back()->response),
370+ google::protobuf::NewCallback(this, &MirScreencast::screencast_done, requests.back().get()));
371+}
372
373=== modified file 'src/client/mir_screencast.h'
374--- src/client/mir_screencast.h 2017-05-08 03:04:26 +0000
375+++ src/client/mir_screencast.h 2017-06-06 16:26:39 +0000
376@@ -20,10 +20,11 @@
377 #define MIR_CLIENT_MIR_SCREENCAST_H_
378
379 #include "mir_wait_handle.h"
380-#include "mir_toolkit/client_types.h"
381+#include "mir_toolkit/mir_screencast.h"
382 #include "mir/optional_value.h"
383 #include "mir/geometry/size.h"
384 #include "mir/geometry/rectangle.h"
385+#include "mir_protobuf.pb.h"
386
387 #include <EGL/eglplatform.h>
388
389@@ -38,6 +39,7 @@
390 }
391 namespace client
392 {
393+class MirBuffer;
394 namespace rpc
395 {
396 class DisplayServer;
397@@ -85,6 +87,11 @@
398
399 MirBufferStream* get_buffer_stream();
400
401+ void screencast_to_buffer(
402+ mir::client::MirBuffer* buffer,
403+ MirScreencastBufferCallback available_callback,
404+ void* available_context);
405+
406 private:
407 void screencast_created(
408 MirScreencastCallback callback, void* context);
409@@ -103,6 +110,23 @@
410 MirWaitHandle release_wait_handle;
411
412 std::string const empty_error_message;
413+
414+ struct ScreencastRequest
415+ {
416+ ScreencastRequest(mir::client::MirBuffer* b, MirScreencastBufferCallback cb, void* context) :
417+ buffer(b),
418+ available_callback(cb),
419+ available_context(context)
420+ {
421+ }
422+
423+ mir::client::MirBuffer* buffer;
424+ MirScreencastBufferCallback available_callback;
425+ void* available_context;
426+ mir::protobuf::Void response;
427+ };
428+ std::vector<std::unique_ptr<ScreencastRequest>> requests;
429+ void screencast_done(ScreencastRequest* request);
430 };
431
432 #endif /* MIR_CLIENT_MIR_SCREENCAST_H_ */
433
434=== modified file 'src/client/mir_screencast_api.cpp'
435--- src/client/mir_screencast_api.cpp 2017-05-08 03:04:26 +0000
436+++ src/client/mir_screencast_api.cpp 2017-06-06 16:26:39 +0000
437@@ -19,11 +19,13 @@
438 #define MIR_LOG_COMPONENT "MirScreencastAPI"
439
440 #include "mir_toolkit/mir_screencast.h"
441+#include "mir_toolkit/mir_buffer.h"
442 #include "mir_screencast.h"
443 #include "mir_connection.h"
444 #include "mir/raii.h"
445 #include "mir/require.h"
446 #include "mir/uncaught.h"
447+#include "no_tls_future-inl.h"
448
449 #include <stdexcept>
450 #include <boost/throw_exception.hpp>
451@@ -131,3 +133,38 @@
452 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
453 return nullptr;
454 }
455+
456+void mir_screencast_capture_to_buffer(
457+ MirScreencast* screencast,
458+ MirBuffer* b,
459+ MirScreencastBufferCallback available_callback, void* available_context)
460+try
461+{
462+ mir::require(b);
463+ mir::require(screencast);
464+
465+ auto buffer = reinterpret_cast<mir::client::MirBuffer*>(b);
466+ screencast->screencast_to_buffer(buffer, available_callback, available_context);
467+}
468+catch (std::exception const& ex)
469+{
470+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
471+ available_callback(mir_screencast_error_failure, nullptr, available_context);
472+}
473+
474+MirScreencastResult mir_screencast_capture_to_buffer_sync(MirScreencast* screencast, MirBuffer* buffer)
475+try
476+{
477+ mir::client::NoTLSPromise<MirScreencastResult> promise;
478+ mir_screencast_capture_to_buffer(screencast, buffer,
479+ [](MirScreencastResult status, MirBuffer* /*buffer*/, void* context)
480+ {
481+ reinterpret_cast<mir::client::NoTLSPromise<MirScreencastResult>*>(context)->set_value(status);
482+ }, &promise);
483+ return promise.get_future().get();
484+}
485+catch (std::exception const& ex)
486+{
487+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
488+ return mir_screencast_error_failure;
489+}
490
491=== modified file 'src/client/symbols.map'
492--- src/client/symbols.map 2017-05-25 08:58:03 +0000
493+++ src/client/symbols.map 2017-06-06 16:26:39 +0000
494@@ -584,6 +584,8 @@
495 mir_buffer_stream_get_microseconds_till_vblank;
496 mir_connection_apply_session_input_config;
497 mir_connection_set_base_input_config;
498+ mir_screencast_capture_to_buffer;
499+ mir_screencast_capture_to_buffer_sync;
500 mir_create_freestyle_window_spec;
501 mir_create_gloss_window_spec;
502 mir_create_satellite_window_spec;
503
504=== modified file 'src/server/compositor/compositing_screencast.cpp'
505--- src/server/compositor/compositing_screencast.cpp 2017-05-08 03:04:26 +0000
506+++ src/server/compositor/compositing_screencast.cpp 2017-06-06 16:26:39 +0000
507@@ -26,6 +26,7 @@
508 #include "mir/graphics/display_buffer.h"
509 #include "mir/graphics/graphic_buffer_allocator.h"
510 #include "mir/compositor/display_buffer_compositor_factory.h"
511+#include "mir/graphics/transformation.h"
512 #include "mir/compositor/display_buffer_compositor.h"
513 #include "mir/geometry/rectangles.h"
514 #include "mir/raii.h"
515@@ -71,21 +72,20 @@
516 ScreencastSessionContext(
517 std::shared_ptr<Scene> const& scene,
518 mg::Display& display,
519- mg::GraphicBufferAllocator& buffer_allocator,
520 DisplayBufferCompositorFactory& db_compositor_factory,
521+ std::vector<std::shared_ptr<mg::Buffer>> const& buffers,
522 geom::Rectangle const& capture_region,
523 geom::Size const& capture_size,
524- MirPixelFormat pixel_format,
525- int nbuffers,
526 MirMirrorMode mirror_mode)
527 : scene{scene},
528 display_buffer{std::make_unique<ScreencastDisplayBuffer>(capture_region, capture_size, mirror_mode, free_queue, ready_queue, display)},
529 display_buffer_compositor{db_compositor_factory.create_compositor_for(*display_buffer)},
530- virtual_output{make_virtual_output(display, capture_region)}
531+ virtual_output{make_virtual_output(display, capture_region)},
532+ queue_size(capture_size),
533+ mirror_mode(mirror_mode)
534 {
535- mg::BufferProperties const buffer_properties{capture_size, pixel_format, mg::BufferUsage::hardware};
536- for (int i = 0; i < nbuffers; i++)
537- free_queue.schedule(buffer_allocator.alloc_buffer(buffer_properties));
538+ for (auto buffer : buffers)
539+ free_queue.schedule(buffer);
540
541 scene->register_compositor(this);
542 if (virtual_output)
543@@ -99,6 +99,9 @@
544 std::shared_ptr<mg::Buffer> capture()
545 {
546 std::lock_guard<decltype(mutex)> lk(mutex);
547+ if (queue_size != display_buffer->renderbuffer_size())
548+ display_buffer->set_renderbuffer_size(queue_size);
549+
550 //FIXME:: the client needs a better way to express it is no longer
551 //using the last captured buffer
552 if (last_captured_buffer)
553@@ -113,6 +116,23 @@
554 void capture(std::shared_ptr<mg::Buffer> const& buffer)
555 {
556 std::lock_guard<decltype(mutex)> lk(mutex);
557+ if (buffer->size() != display_buffer->renderbuffer_size())
558+ display_buffer->set_renderbuffer_size(buffer->size());
559+
560+ //a bit confusingly, the old way of screencasting had the mirror_mode_none
561+ //produce upside down buffers.
562+ if (mirror_mode == mir_mirror_mode_none)
563+ display_buffer->set_transformation(mg::transformation(mir_mirror_mode_vertical));
564+ if (mirror_mode == mir_mirror_mode_vertical)
565+ display_buffer->set_transformation(mg::transformation(mir_mirror_mode_none));
566+ if (mirror_mode == mir_mirror_mode_horizontal)
567+ {
568+ glm::mat2 mat;
569+ mat[0][0] = -1;
570+ mat[1][1] = -1;
571+ display_buffer->set_transformation(mat);
572+ }
573+
574 auto scheduled = free_queue.num_scheduled();
575 free_queue.schedule(buffer);
576 for(auto i = 0u; i < scheduled; i++)
577@@ -121,6 +141,8 @@
578 display_buffer_compositor->composite(scene->scene_elements_for(this));
579 if (buffer != ready_queue.next_buffer())
580 throw std::runtime_error("unable to capture to buffer");
581+
582+ display_buffer->set_transformation(mg::transformation(mirror_mode));
583 }
584
585 private:
586@@ -133,6 +155,8 @@
587 std::unique_ptr<compositor::DisplayBufferCompositor> display_buffer_compositor;
588 std::unique_ptr<graphics::VirtualOutput> virtual_output;
589 std::shared_ptr<mg::Buffer> last_captured_buffer;
590+ geom::Size queue_size;
591+ MirMirrorMode mirror_mode;
592 };
593
594
595@@ -159,14 +183,20 @@
596 size.height.as_int() == 0 ||
597 region.size.width.as_int() == 0 ||
598 region.size.height.as_int() == 0 ||
599- pixel_format == mir_pixel_format_invalid ||
600- nbuffers < 0)
601+ ((nbuffers > 1) && (pixel_format == mir_pixel_format_invalid)))
602 {
603 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid parameters"));
604 }
605 std::lock_guard<decltype(session_mutex)> lock{session_mutex};
606 auto const id = next_available_session_id();
607- session_contexts[id] = create_session_context(region, size, pixel_format, nbuffers, mirror_mode);
608+
609+ std::vector<std::shared_ptr<mg::Buffer>> buffers(nbuffers);
610+ for (auto& buffer : buffers)
611+ {
612+ buffer = buffer_allocator->alloc_buffer(
613+ mg::BufferProperties{size, pixel_format, mg::BufferUsage::hardware});
614+ }
615+ session_contexts[id] = create_session_context(region, size, buffers, mirror_mode);
616
617 return id;
618 }
619@@ -204,13 +234,11 @@
620 mc::CompositingScreencast::create_session_context(
621 geometry::Rectangle const& rect,
622 geometry::Size const& size,
623- MirPixelFormat pixel_format,
624- int nbuffers,
625+ std::vector<std::shared_ptr<mg::Buffer>> const& buffers,
626 MirMirrorMode mirror_mode)
627 {
628 return std::make_shared<detail::ScreencastSessionContext>(
629- scene, *display, *buffer_allocator, *db_compositor_factory,
630- rect, size, pixel_format, nbuffers, mirror_mode);
631+ scene, *display, *db_compositor_factory, buffers, rect, size, mirror_mode);
632 }
633
634 void mc::CompositingScreencast::capture(
635
636=== modified file 'src/server/compositor/compositing_screencast.h'
637--- src/server/compositor/compositing_screencast.h 2017-05-08 03:04:26 +0000
638+++ src/server/compositor/compositing_screencast.h 2017-06-06 16:26:39 +0000
639@@ -64,8 +64,7 @@
640 std::shared_ptr<detail::ScreencastSessionContext>
641 create_session_context(geometry::Rectangle const& rect,
642 geometry::Size const& size,
643- MirPixelFormat pixel_format,
644- int nbuffers,
645+ std::vector<std::shared_ptr<graphics::Buffer>> const& buffers,
646 MirMirrorMode mirror_mode);
647 std::shared_ptr<detail::ScreencastSessionContext> session(frontend::ScreencastSessionId id);
648
649
650=== modified file 'src/server/compositor/screencast_display_buffer.cpp'
651--- src/server/compositor/screencast_display_buffer.cpp 2017-05-08 03:04:26 +0000
652+++ src/server/compositor/screencast_display_buffer.cpp 2017-06-06 16:26:39 +0000
653@@ -72,7 +72,8 @@
654 rect(rect),
655 transform(mg::transformation(mirror_mode)),
656 free_queue(free_queue), ready_queue(ready_queue),
657- old_fbo(), old_viewport()
658+ old_fbo(), old_viewport(),
659+ current_size(size)
660 {
661 auto const gl_context_raii = mir::raii::paired_calls(
662 [this] { gl_context->make_current(); },
663@@ -182,3 +183,31 @@
664 {
665 return this;
666 }
667+
668+geom::Size mc::ScreencastDisplayBuffer::renderbuffer_size()
669+{
670+ return current_size;
671+}
672+
673+void mc::ScreencastDisplayBuffer::set_renderbuffer_size(geom::Size size)
674+{
675+ if (size == current_size)
676+ return;
677+
678+ auto depth_buffer = allocate_gl_resource<glGenRenderbuffers, glDeleteRenderbuffers>();
679+ glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
680+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
681+ size.width.as_uint32_t(),
682+ size.height.as_uint32_t());
683+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
684+ GL_RENDERBUFFER, depth_buffer);
685+
686+ if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
687+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create FBO for buffer"));
688+ depth_rbo = std::move(depth_buffer);
689+}
690+
691+void mc::ScreencastDisplayBuffer::set_transformation(glm::mat2 const& t)
692+{
693+ transform = t;
694+}
695
696=== modified file 'src/server/compositor/screencast_display_buffer.h'
697--- src/server/compositor/screencast_display_buffer.h 2017-05-08 03:04:26 +0000
698+++ src/server/compositor/screencast_display_buffer.h 2017-06-06 16:26:39 +0000
699@@ -116,6 +116,10 @@
700
701 NativeDisplayBuffer* native_display_buffer() override;
702
703+ geometry::Size renderbuffer_size();
704+ void set_renderbuffer_size(geometry::Size);
705+ void set_transformation(glm::mat2 const& transform);
706+
707 private:
708 std::unique_ptr<renderer::gl::Context> gl_context;
709 geometry::Rectangle const rect;
710@@ -131,6 +135,8 @@
711 detail::GLResource<glDeleteTextures> color_tex;
712 detail::GLResource<glDeleteRenderbuffers> depth_rbo;
713 detail::GLResource<glDeleteFramebuffers> fbo;
714+
715+ geometry::Size current_size;
716 };
717
718 }
719
720=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
721--- src/server/frontend/protobuf_message_processor.cpp 2017-05-08 03:04:26 +0000
722+++ src/server/frontend/protobuf_message_processor.cpp 2017-06-06 16:26:39 +0000
723@@ -425,7 +425,7 @@
724 void mfd::ProtobufMessageProcessor::send_response(
725 ::google::protobuf::uint32 id, mir::protobuf::Screencast* response)
726 {
727- if (response->has_buffer_stream())
728+ if (response->has_buffer_stream() && response->buffer_stream().has_buffer())
729 sender->send_response(id, response,
730 {extract_fds_from(response->mutable_buffer_stream()->mutable_buffer())});
731 else
732
733=== modified file 'src/server/frontend/session_mediator.cpp'
734--- src/server/frontend/session_mediator.cpp 2017-05-25 08:58:03 +0000
735+++ src/server/frontend/session_mediator.cpp 2017-06-06 16:26:39 +0000
736@@ -826,6 +826,7 @@
737 protobuf_screencast->mutable_buffer_stream()->set_pixel_format(pixel_format);
738 protobuf_screencast->mutable_buffer_stream()->mutable_id()->set_value(
739 screencast_session_id.as_value());
740+ protobuf_screencast->mutable_buffer_stream()->set_pixel_format(pixel_format);
741
742 done->Run();
743 }
744@@ -869,7 +870,6 @@
745 auto session = weak_session.lock();
746 ScreencastSessionId const screencast_session_id{request->id().value()};
747 auto buffer = session->get_buffer(mg::BufferID{request->buffer_id()});
748- mf::ScreencastSessionId const screencast_id{request->id().value()};
749 screencast->capture(screencast_session_id, buffer);
750 done->Run();
751 }
752
753=== modified file 'tests/acceptance-tests/test_client_screencast.cpp'
754--- tests/acceptance-tests/test_client_screencast.cpp 2017-05-08 03:04:26 +0000
755+++ tests/acceptance-tests/test_client_screencast.cpp 2017-06-06 16:26:39 +0000
756@@ -24,6 +24,7 @@
757 #include "mir_test_framework/connected_client_headless_server.h"
758 #include "mir/test/doubles/stub_session_authorizer.h"
759 #include "mir/test/fake_shared.h"
760+#include "mir/test/doubles/mock_gl.h"
761
762 #include <gtest/gtest.h>
763 #include <gmock/gmock.h>
764@@ -32,6 +33,8 @@
765 namespace mtd = mir::test::doubles;
766 namespace mf = mir::frontend;
767 namespace mt = mir::test;
768+using namespace testing;
769+using namespace std::literals::chrono_literals;
770
771 namespace
772 {
773@@ -48,6 +51,7 @@
774 struct Screencast : mtf::HeadlessInProcessServer
775 {
776 MockSessionAuthorizer mock_authorizer;
777+ NiceMock<mtd::MockGL> mockgl;
778
779 void SetUp() override
780 {
781@@ -126,3 +130,84 @@
782 mir_screencast_release_sync(screencast);
783 mir_connection_release(connection);
784 }
785+
786+TEST_F(Screencast, can_cast_to_buffer)
787+{
788+ EXPECT_CALL(mock_authorizer, screencast_is_allowed(_))
789+ .WillOnce(Return(true));
790+ auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
791+
792+ auto const buffer = mir_connection_allocate_buffer_sync(
793+ connection, default_width, default_height, default_pixel_format);
794+
795+ ASSERT_TRUE(buffer);
796+
797+ MirScreencastSpec* spec = mir_create_screencast_spec(connection);
798+ //We have to set nbuffers == 0 now to avoid capturing at startup. Current default is 1.
799+ mir_screencast_spec_set_number_of_buffers(spec, 0);
800+
801+ mir_screencast_spec_set_capture_region(spec, &default_capture_region);
802+ auto screencast = mir_screencast_create_sync(spec);
803+ mir_screencast_spec_release(spec);
804+
805+ struct Capture
806+ {
807+ std::mutex mutex;
808+ std::condition_variable cv;
809+ bool capture = false;
810+ } capture;
811+
812+ mir_screencast_capture_to_buffer(screencast, buffer,
813+ [] (MirScreencastResult /*status*/, MirBuffer* /*buffer*/, void* context) {
814+ auto c = reinterpret_cast<Capture*>(context);
815+ std::unique_lock<decltype(c->mutex)> lk(c->mutex);
816+ c->capture = true;
817+ c->cv.notify_all();
818+ }, &capture );
819+
820+ std::unique_lock<decltype(capture.mutex)> lk2(capture.mutex);
821+ ASSERT_TRUE(capture.cv.wait_for(lk2, 5s, [&] { return capture.capture; }));
822+ EXPECT_THAT(mir_buffer_get_error_message(buffer), StrEq(""));
823+
824+ mir_screencast_release_sync(screencast);
825+ mir_connection_release(connection);
826+}
827+
828+TEST_F(Screencast, can_cast_to_buffer_sync)
829+{
830+ EXPECT_CALL(mock_authorizer, screencast_is_allowed(_))
831+ .WillOnce(Return(true));
832+ auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
833+
834+ struct BufferSync
835+ {
836+ MirBuffer* buffer = nullptr;
837+ std::mutex mutex;
838+ std::condition_variable cv;
839+ } buffer_info;
840+
841+ mir_connection_allocate_buffer(
842+ connection,
843+ default_width, default_height, default_pixel_format,
844+ [](MirBuffer* b, void* ctxt) {
845+ auto info = reinterpret_cast<BufferSync*>(ctxt);
846+ std::unique_lock<decltype(info->mutex)> lk(info->mutex);
847+ info->buffer = b;
848+ info->cv.notify_all();
849+ }, &buffer_info);
850+ std::unique_lock<decltype(buffer_info.mutex)> lk(buffer_info.mutex);
851+ ASSERT_TRUE(buffer_info.cv.wait_for(lk, 5s, [&] { return buffer_info.buffer; }));
852+
853+ MirScreencastSpec* spec = mir_create_screencast_spec(connection);
854+ //We have to set nbuffers == 0 now to avoid capturing at startup. Current default is 1.
855+ mir_screencast_spec_set_number_of_buffers(spec, 0);
856+
857+ mir_screencast_spec_set_capture_region(spec, &default_capture_region);
858+ auto screencast = mir_screencast_create_sync(spec);
859+
860+ mir_screencast_spec_release(spec);
861+ mir_screencast_capture_to_buffer_sync(screencast, buffer_info.buffer);
862+
863+ mir_screencast_release_sync(screencast);
864+ mir_connection_release(connection);
865+}
866
867=== modified file 'tests/unit-tests/compositor/test_compositing_screencast.cpp'
868--- tests/unit-tests/compositor/test_compositing_screencast.cpp 2017-05-08 03:04:26 +0000
869+++ tests/unit-tests/compositor/test_compositing_screencast.cpp 2017-06-06 16:26:39 +0000
870@@ -251,7 +251,6 @@
871 EXPECT_THROW(screencast.create_session(invalid_region, default_size, default_pixel_format, default_num_buffers, default_mirror_mode), std::runtime_error);
872 EXPECT_THROW(screencast.create_session(default_region, invalid_size, default_pixel_format, default_num_buffers, default_mirror_mode), std::runtime_error);
873 EXPECT_THROW(screencast.create_session(default_region, default_size, mir_pixel_format_invalid, default_num_buffers, default_mirror_mode), std::runtime_error);
874- EXPECT_THROW(screencast.create_session(default_region, default_size, mir_pixel_format_invalid, 0, default_mirror_mode), std::runtime_error);
875 }
876
877 TEST_F(CompositingScreencastTest, throws_on_capture_with_invalid_session_id)

Subscribers

People subscribed via source and target branches