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
=== modified file 'examples/CMakeLists.txt'
--- examples/CMakeLists.txt 2017-06-05 11:06:24 +0000
+++ examples/CMakeLists.txt 2017-06-06 16:26:39 +0000
@@ -312,3 +312,7 @@
312target_link_libraries(mir_demo_client_chain_jumping_buffers312target_link_libraries(mir_demo_client_chain_jumping_buffers
313 mirclient313 mirclient
314)314)
315
316mir_add_wrapped_executable(mir_demo_client_screencast screencast.cpp)
317
318target_link_libraries(mir_demo_client_screencast mirclient)
315319
=== added file 'examples/screencast.cpp'
--- examples/screencast.cpp 1970-01-01 00:00:00 +0000
+++ examples/screencast.cpp 2017-06-06 16:26:39 +0000
@@ -0,0 +1,149 @@
1/*
2 * Copyright © 2017 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Kevin DuBois <kevin.dubois@canonical.com>
17 */
18
19#include "mir_toolkit/mir_client_library.h"
20#include "mir_toolkit/mir_screencast.h"
21#include "mir_toolkit/mir_buffer.h"
22#include <memory>
23#include <iostream>
24#include <unistd.h>
25#include <getopt.h>
26#include <fstream>
27
28int main(int argc, char *argv[])
29try
30{
31 int arg = -1;
32 static char const* socket_file = NULL;
33 static char const* output_file = "screencap_output.raw";
34 unsigned int width = 400;
35 unsigned int height = 300;
36
37 auto disp_id = 0;
38 while ((arg = getopt (argc, argv, "m:f:d:s:h:")) != -1)
39 {
40 switch (arg)
41 {
42 case 'm':
43 socket_file = optarg;
44 break;
45 case 'f':
46 output_file = optarg;
47 break;
48 case 'd':
49 disp_id = atoi(optarg);
50 break;
51 case 's':
52 if (sscanf(optarg, "%ux%u", &width, &height) != 2 || width == 0 || height == 0)
53 {
54 std::cerr << "could not parse size " << optarg << '\n';
55 return -1;
56 }
57 break;
58 case 'h':
59 default:
60 std::cout << argv[0] << std::endl;
61 std::cout << "Usage:\n";
62 std::cout << " -m <Mir server socket>\n";
63 std::cout << " -f file to output to\n";
64 std::cout << " -d output id to capture\n";
65 std::cout << " -s size of capture buffer (WxH)\n";
66 std::cout << " -h help dialog\n";
67 return -1;
68 }
69 }
70
71 int rc = 0;
72 auto connection = mir_connect_sync(socket_file, "screencap_to_buffer");
73 if (!mir_connection_is_valid(connection))
74 {
75 std::cerr << "could not connect to server\n";
76 return -1;
77 }
78
79 auto display_config = mir_connection_create_display_configuration(connection);
80 if (disp_id < 0 || disp_id > mir_display_config_get_num_outputs(display_config))
81 {
82 std::cerr << "invalid display id set\n";
83 return -1;
84 }
85
86 auto output = mir_display_config_get_output(display_config, disp_id);
87 auto mode = mir_output_get_current_mode(output);
88
89 auto pf = mir_pixel_format_abgr_8888;
90 MirRectangle rect {
91 mir_output_get_position_x(output),
92 mir_output_get_position_y(output),
93 static_cast<unsigned int>(mir_output_mode_get_width(mode)),
94 static_cast<unsigned int>(mir_output_mode_get_height(mode)) };
95 mir_display_config_release(display_config);
96
97 auto spec = mir_create_screencast_spec(connection);
98 mir_screencast_spec_set_capture_region(spec, &rect);
99 mir_screencast_spec_set_mirror_mode(spec, mir_mirror_mode_horizontal);
100 //TODO: the default screencast spec will capture a buffer when creating the screencast.
101 // Set to zero to avoid this, and when the old screencast-bufferstream method is removed,
102 // the initial capture will be removed.
103 mir_screencast_spec_set_number_of_buffers(spec, 0);
104
105 auto screencast = mir_screencast_create_sync(spec);
106 mir_screencast_spec_release(spec);
107
108 auto buffer = mir_connection_allocate_buffer_sync(connection, width, height, pf);
109
110 if (auto status = mir_screencast_capture_to_buffer_sync(screencast, buffer))
111 {
112 switch (status)
113 {
114 case mir_screencast_error_failure:
115 std::cerr << "screencast failed" << std::endl;
116 rc = -1;
117 break;
118 default:
119 break;
120 }
121 }
122
123 std::ofstream file(output_file);
124 if (!rc && output)
125 {
126 MirBufferLayout layout;
127 MirGraphicsRegion region;
128 mir_buffer_map(buffer, &region, &layout);
129
130 auto addr = region.vaddr;
131 for (int i = 0; i < region.height; i++)
132 {
133 file.write(addr, region.width * MIR_BYTES_PER_PIXEL(pf));
134 addr += region.stride;
135 }
136
137 mir_buffer_unmap(buffer);
138 }
139
140 mir_buffer_release(buffer);
141 mir_screencast_release_sync(screencast);
142 mir_connection_release(connection);
143 return EXIT_SUCCESS;
144}
145catch(std::exception& e)
146{
147 std::cerr << "error : " << e.what() << std::endl;
148 return EXIT_FAILURE;
149}
0150
=== modified file 'include/client/mir_toolkit/mir_screencast.h'
--- include/client/mir_toolkit/mir_screencast.h 2017-05-25 08:58:03 +0000
+++ include/client/mir_toolkit/mir_screencast.h 2017-06-06 16:26:39 +0000
@@ -28,6 +28,22 @@
28extern "C" {28extern "C" {
29#endif29#endif
3030
31typedef enum MirScreencastResult
32{
33 /**
34 * Screencasting to the MirBuffer succeeded.
35 */
36 mir_screencast_success,
37
38 /**
39 * Screencasting failed.
40 */
41 mir_screencast_error_failure,
42} MirScreencastResult;
43
44typedef void (*MirScreencastBufferCallback)(
45 MirScreencastResult status, MirBuffer* buffer, void* context);
46
31/**47/**
32 * Create a screencast specification.48 * Create a screencast specification.
33 *49 *
@@ -161,6 +177,29 @@
161 */177 */
162MirBufferStream* mir_screencast_get_buffer_stream(MirScreencast* screencast);178MirBufferStream* mir_screencast_get_buffer_stream(MirScreencast* screencast);
163179
180/** Capture the contents of the screen to a particular buffer.
181 *
182 * \param [in] screencast The screencast
183 * \param [in] buffer The buffer
184 * \param [in] available_callback Callback triggered when buffer is available again
185 * \param [in] available_context The context for the above callback
186 **/
187void mir_screencast_capture_to_buffer(
188 MirScreencast* screencast,
189 MirBuffer* buffer,
190 MirScreencastBufferCallback available_callback, void* available_context);
191
192/** Capture the contents of the screen to a particular buffer and wait for the
193 * capture to complete.
194 *
195 * \warning The returned MirError will be valid until the next call
196 * to mir_screencast_capture_to_buffer or mir_screencast_capture_to_buffer_sync.
197 * \param [in] screencast The screencast
198 * \param [in] buffer The buffer
199 * \return The error condition
200 **/
201MirScreencastResult mir_screencast_capture_to_buffer_sync(MirScreencast* screencast, MirBuffer* buffer);
202
164#ifdef __cplusplus203#ifdef __cplusplus
165}204}
166/**@}*/205/**@}*/
167206
=== renamed file 'tests/include/mir/test/doubles/mock_gl.h' => 'include/test/mir/test/doubles/mock_gl.h'
=== modified file 'include/test/mir/test/doubles/stub_session_authorizer.h'
--- include/test/mir/test/doubles/stub_session_authorizer.h 2017-05-08 03:04:26 +0000
+++ include/test/mir/test/doubles/stub_session_authorizer.h 2017-06-06 16:26:39 +0000
@@ -20,6 +20,7 @@
20#define MIR_TEST_DOUBLES_STUB_SESSION_AUTHORIZER_H_20#define MIR_TEST_DOUBLES_STUB_SESSION_AUTHORIZER_H_
2121
22#include "mir/frontend/session_authorizer.h"22#include "mir/frontend/session_authorizer.h"
23#include <gmock/gmock.h>
2324
24namespace mir25namespace mir
25{26{
@@ -60,6 +61,11 @@
60 }61 }
61};62};
6263
64struct MockSessionAuthorizer : StubSessionAuthorizer
65{
66 MOCK_METHOD1(screencast_is_allowed, bool(frontend::SessionCredentials const&));
67};
68
63}69}
64}70}
65} // namespace mir71} // namespace mir
6672
=== modified file 'src/client/mir_screencast.cpp'
--- src/client/mir_screencast.cpp 2017-05-08 03:04:26 +0000
+++ src/client/mir_screencast.cpp 2017-06-06 16:26:39 +0000
@@ -21,10 +21,12 @@
21#include "mir_protobuf.pb.h"21#include "mir_protobuf.pb.h"
22#include "make_protobuf_object.h"22#include "make_protobuf_object.h"
23#include "mir/mir_buffer_stream.h"23#include "mir/mir_buffer_stream.h"
24#include "mir/mir_buffer.h"
24#include "mir/frontend/client_constants.h"25#include "mir/frontend/client_constants.h"
25#include "mir_toolkit/mir_native_buffer.h"26#include "mir_toolkit/mir_native_buffer.h"
2627
27#include <boost/throw_exception.hpp>28#include <boost/throw_exception.hpp>
29#include <algorithm>
2830
29namespace mcl = mir::client;31namespace mcl = mir::client;
30namespace mp = mir::protobuf;32namespace mp = mir::protobuf;
@@ -55,6 +57,16 @@
55 message.mutable_region()->set_height(region.height);57 message.mutable_region()->set_height(region.height);
56 }58 }
5759
60 if (spec.num_buffers.is_set() && spec.num_buffers.value() == 0)
61 {
62 if (!spec.pixel_format.is_set())
63 message.set_pixel_format(mir_pixel_format_abgr_8888);
64 if (!spec.width.is_set())
65 message.set_width(1);
66 if (!spec.width.is_set())
67 message.set_height(1);
68 }
69
58 return message;70 return message;
59}71}
6072
@@ -72,9 +84,6 @@
7284
73#define THROW_IF_ZERO(option) THROW_IF_EQ(option, 0)85#define THROW_IF_ZERO(option) THROW_IF_EQ(option, 0)
7486
75 THROW_IF_ZERO(width);
76 THROW_IF_ZERO(height);
77 THROW_IF_EQ(pixel_format, mir_pixel_format_invalid);
78 THROW_IF_UNSET(capture_region);87 THROW_IF_UNSET(capture_region);
7988
80 if (spec.capture_region.is_set())89 if (spec.capture_region.is_set())
@@ -85,6 +94,14 @@
85 if (region.height == 0)94 if (region.height == 0)
86 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid capture region height"));95 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid capture region height"));
87 }96 }
97
98 //zero nbuffers don't need to set pixel format, width, or height
99 if (!spec.num_buffers.is_set() || spec.num_buffers.value() > 0)
100 {
101 THROW_IF_ZERO(width);
102 THROW_IF_ZERO(height);
103 THROW_IF_EQ(pixel_format, mir_pixel_format_invalid);
104 }
88}105}
89}106}
90107
@@ -180,13 +197,13 @@
180void MirScreencast::screencast_created(197void MirScreencast::screencast_created(
181 MirScreencastCallback callback, void* context)198 MirScreencastCallback callback, void* context)
182{199{
183 if (!protobuf_screencast->has_error() && connection)200 if (connection && !protobuf_screencast->has_error() &&
201 protobuf_screencast->has_buffer_stream() && protobuf_screencast->buffer_stream().has_buffer())
184 {202 {
185 std::lock_guard<decltype(mutex)> lock(mutex);203 std::lock_guard<decltype(mutex)> lock(mutex);
186 try204 try
187 {205 {
188 buffer_stream = connection->make_consumer_stream(206 buffer_stream = connection->make_consumer_stream(protobuf_screencast->buffer_stream());
189 protobuf_screencast->buffer_stream());
190 }207 }
191 catch (...)208 catch (...)
192 {209 {
@@ -207,7 +224,7 @@
207224
208 {225 {
209 std::lock_guard<decltype(mutex)> lock(mutex);226 std::lock_guard<decltype(mutex)> lock(mutex);
210 if (connection)227 if (buffer_stream)
211 connection->release_consumer_stream(buffer_stream.get());228 connection->release_consumer_stream(buffer_stream.get());
212 buffer_stream.reset();229 buffer_stream.reset();
213 }230 }
@@ -219,3 +236,38 @@
219 std::lock_guard<decltype(mutex)> lock(mutex);236 std::lock_guard<decltype(mutex)> lock(mutex);
220 return buffer_stream.get();237 return buffer_stream.get();
221}238}
239
240void MirScreencast::screencast_done(ScreencastRequest* request)
241{
242 auto const status = request->response.has_error() ? mir_screencast_error_failure : mir_screencast_success;
243
244 request->available_callback(status, reinterpret_cast<MirBuffer*>(request->buffer), request->available_context);
245
246 std::unique_lock<decltype(mutex)> lk(mutex);
247 auto it = std::find_if(requests.begin(), requests.end(),
248 [&request] (auto const& it) { return it.get() == request; } );
249 if (it != requests.end())
250 requests.erase(it);
251}
252
253void MirScreencast::screencast_to_buffer(
254 mcl::MirBuffer* buffer,
255 MirScreencastBufferCallback cb,
256 void* context)
257{
258 if (!server) //construction with nullptr should be invalid
259 BOOST_THROW_EXCEPTION(std::runtime_error("invalid screencast"));
260
261 std::unique_lock<decltype(mutex)> lk(mutex);
262
263 requests.emplace_back(std::make_unique<ScreencastRequest>(buffer, cb, context));
264
265 mir::protobuf::ScreencastRequest request;
266 request.set_buffer_id(buffer->rpc_id());
267 request.mutable_id()->set_value(protobuf_screencast->screencast_id().value());
268
269 server->screencast_to_buffer(
270 &request,
271 &(requests.back()->response),
272 google::protobuf::NewCallback(this, &MirScreencast::screencast_done, requests.back().get()));
273}
222274
=== modified file 'src/client/mir_screencast.h'
--- src/client/mir_screencast.h 2017-05-08 03:04:26 +0000
+++ src/client/mir_screencast.h 2017-06-06 16:26:39 +0000
@@ -20,10 +20,11 @@
20#define MIR_CLIENT_MIR_SCREENCAST_H_20#define MIR_CLIENT_MIR_SCREENCAST_H_
2121
22#include "mir_wait_handle.h"22#include "mir_wait_handle.h"
23#include "mir_toolkit/client_types.h"23#include "mir_toolkit/mir_screencast.h"
24#include "mir/optional_value.h"24#include "mir/optional_value.h"
25#include "mir/geometry/size.h"25#include "mir/geometry/size.h"
26#include "mir/geometry/rectangle.h"26#include "mir/geometry/rectangle.h"
27#include "mir_protobuf.pb.h"
2728
28#include <EGL/eglplatform.h>29#include <EGL/eglplatform.h>
2930
@@ -38,6 +39,7 @@
38}39}
39namespace client40namespace client
40{41{
42class MirBuffer;
41namespace rpc43namespace rpc
42{44{
43class DisplayServer;45class DisplayServer;
@@ -85,6 +87,11 @@
8587
86 MirBufferStream* get_buffer_stream();88 MirBufferStream* get_buffer_stream();
8789
90 void screencast_to_buffer(
91 mir::client::MirBuffer* buffer,
92 MirScreencastBufferCallback available_callback,
93 void* available_context);
94
88private:95private:
89 void screencast_created(96 void screencast_created(
90 MirScreencastCallback callback, void* context);97 MirScreencastCallback callback, void* context);
@@ -103,6 +110,23 @@
103 MirWaitHandle release_wait_handle;110 MirWaitHandle release_wait_handle;
104111
105 std::string const empty_error_message;112 std::string const empty_error_message;
113
114 struct ScreencastRequest
115 {
116 ScreencastRequest(mir::client::MirBuffer* b, MirScreencastBufferCallback cb, void* context) :
117 buffer(b),
118 available_callback(cb),
119 available_context(context)
120 {
121 }
122
123 mir::client::MirBuffer* buffer;
124 MirScreencastBufferCallback available_callback;
125 void* available_context;
126 mir::protobuf::Void response;
127 };
128 std::vector<std::unique_ptr<ScreencastRequest>> requests;
129 void screencast_done(ScreencastRequest* request);
106};130};
107131
108#endif /* MIR_CLIENT_MIR_SCREENCAST_H_ */132#endif /* MIR_CLIENT_MIR_SCREENCAST_H_ */
109133
=== modified file 'src/client/mir_screencast_api.cpp'
--- src/client/mir_screencast_api.cpp 2017-05-08 03:04:26 +0000
+++ src/client/mir_screencast_api.cpp 2017-06-06 16:26:39 +0000
@@ -19,11 +19,13 @@
19#define MIR_LOG_COMPONENT "MirScreencastAPI"19#define MIR_LOG_COMPONENT "MirScreencastAPI"
2020
21#include "mir_toolkit/mir_screencast.h"21#include "mir_toolkit/mir_screencast.h"
22#include "mir_toolkit/mir_buffer.h"
22#include "mir_screencast.h"23#include "mir_screencast.h"
23#include "mir_connection.h"24#include "mir_connection.h"
24#include "mir/raii.h"25#include "mir/raii.h"
25#include "mir/require.h"26#include "mir/require.h"
26#include "mir/uncaught.h"27#include "mir/uncaught.h"
28#include "no_tls_future-inl.h"
2729
28#include <stdexcept>30#include <stdexcept>
29#include <boost/throw_exception.hpp>31#include <boost/throw_exception.hpp>
@@ -131,3 +133,38 @@
131 MIR_LOG_UNCAUGHT_EXCEPTION(ex);133 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
132 return nullptr;134 return nullptr;
133}135}
136
137void mir_screencast_capture_to_buffer(
138 MirScreencast* screencast,
139 MirBuffer* b,
140 MirScreencastBufferCallback available_callback, void* available_context)
141try
142{
143 mir::require(b);
144 mir::require(screencast);
145
146 auto buffer = reinterpret_cast<mir::client::MirBuffer*>(b);
147 screencast->screencast_to_buffer(buffer, available_callback, available_context);
148}
149catch (std::exception const& ex)
150{
151 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
152 available_callback(mir_screencast_error_failure, nullptr, available_context);
153}
154
155MirScreencastResult mir_screencast_capture_to_buffer_sync(MirScreencast* screencast, MirBuffer* buffer)
156try
157{
158 mir::client::NoTLSPromise<MirScreencastResult> promise;
159 mir_screencast_capture_to_buffer(screencast, buffer,
160 [](MirScreencastResult status, MirBuffer* /*buffer*/, void* context)
161 {
162 reinterpret_cast<mir::client::NoTLSPromise<MirScreencastResult>*>(context)->set_value(status);
163 }, &promise);
164 return promise.get_future().get();
165}
166catch (std::exception const& ex)
167{
168 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
169 return mir_screencast_error_failure;
170}
134171
=== modified file 'src/client/symbols.map'
--- src/client/symbols.map 2017-05-25 08:58:03 +0000
+++ src/client/symbols.map 2017-06-06 16:26:39 +0000
@@ -584,6 +584,8 @@
584 mir_buffer_stream_get_microseconds_till_vblank;584 mir_buffer_stream_get_microseconds_till_vblank;
585 mir_connection_apply_session_input_config;585 mir_connection_apply_session_input_config;
586 mir_connection_set_base_input_config;586 mir_connection_set_base_input_config;
587 mir_screencast_capture_to_buffer;
588 mir_screencast_capture_to_buffer_sync;
587 mir_create_freestyle_window_spec;589 mir_create_freestyle_window_spec;
588 mir_create_gloss_window_spec;590 mir_create_gloss_window_spec;
589 mir_create_satellite_window_spec;591 mir_create_satellite_window_spec;
590592
=== modified file 'src/server/compositor/compositing_screencast.cpp'
--- src/server/compositor/compositing_screencast.cpp 2017-05-08 03:04:26 +0000
+++ src/server/compositor/compositing_screencast.cpp 2017-06-06 16:26:39 +0000
@@ -26,6 +26,7 @@
26#include "mir/graphics/display_buffer.h"26#include "mir/graphics/display_buffer.h"
27#include "mir/graphics/graphic_buffer_allocator.h"27#include "mir/graphics/graphic_buffer_allocator.h"
28#include "mir/compositor/display_buffer_compositor_factory.h"28#include "mir/compositor/display_buffer_compositor_factory.h"
29#include "mir/graphics/transformation.h"
29#include "mir/compositor/display_buffer_compositor.h"30#include "mir/compositor/display_buffer_compositor.h"
30#include "mir/geometry/rectangles.h"31#include "mir/geometry/rectangles.h"
31#include "mir/raii.h"32#include "mir/raii.h"
@@ -71,21 +72,20 @@
71 ScreencastSessionContext(72 ScreencastSessionContext(
72 std::shared_ptr<Scene> const& scene,73 std::shared_ptr<Scene> const& scene,
73 mg::Display& display,74 mg::Display& display,
74 mg::GraphicBufferAllocator& buffer_allocator,
75 DisplayBufferCompositorFactory& db_compositor_factory,75 DisplayBufferCompositorFactory& db_compositor_factory,
76 std::vector<std::shared_ptr<mg::Buffer>> const& buffers,
76 geom::Rectangle const& capture_region,77 geom::Rectangle const& capture_region,
77 geom::Size const& capture_size,78 geom::Size const& capture_size,
78 MirPixelFormat pixel_format,
79 int nbuffers,
80 MirMirrorMode mirror_mode)79 MirMirrorMode mirror_mode)
81 : scene{scene},80 : scene{scene},
82 display_buffer{std::make_unique<ScreencastDisplayBuffer>(capture_region, capture_size, mirror_mode, free_queue, ready_queue, display)},81 display_buffer{std::make_unique<ScreencastDisplayBuffer>(capture_region, capture_size, mirror_mode, free_queue, ready_queue, display)},
83 display_buffer_compositor{db_compositor_factory.create_compositor_for(*display_buffer)},82 display_buffer_compositor{db_compositor_factory.create_compositor_for(*display_buffer)},
84 virtual_output{make_virtual_output(display, capture_region)}83 virtual_output{make_virtual_output(display, capture_region)},
84 queue_size(capture_size),
85 mirror_mode(mirror_mode)
85 {86 {
86 mg::BufferProperties const buffer_properties{capture_size, pixel_format, mg::BufferUsage::hardware};87 for (auto buffer : buffers)
87 for (int i = 0; i < nbuffers; i++)88 free_queue.schedule(buffer);
88 free_queue.schedule(buffer_allocator.alloc_buffer(buffer_properties));
8989
90 scene->register_compositor(this);90 scene->register_compositor(this);
91 if (virtual_output)91 if (virtual_output)
@@ -99,6 +99,9 @@
99 std::shared_ptr<mg::Buffer> capture()99 std::shared_ptr<mg::Buffer> capture()
100 {100 {
101 std::lock_guard<decltype(mutex)> lk(mutex);101 std::lock_guard<decltype(mutex)> lk(mutex);
102 if (queue_size != display_buffer->renderbuffer_size())
103 display_buffer->set_renderbuffer_size(queue_size);
104
102 //FIXME:: the client needs a better way to express it is no longer105 //FIXME:: the client needs a better way to express it is no longer
103 //using the last captured buffer106 //using the last captured buffer
104 if (last_captured_buffer)107 if (last_captured_buffer)
@@ -113,6 +116,23 @@
113 void capture(std::shared_ptr<mg::Buffer> const& buffer)116 void capture(std::shared_ptr<mg::Buffer> const& buffer)
114 {117 {
115 std::lock_guard<decltype(mutex)> lk(mutex);118 std::lock_guard<decltype(mutex)> lk(mutex);
119 if (buffer->size() != display_buffer->renderbuffer_size())
120 display_buffer->set_renderbuffer_size(buffer->size());
121
122 //a bit confusingly, the old way of screencasting had the mirror_mode_none
123 //produce upside down buffers.
124 if (mirror_mode == mir_mirror_mode_none)
125 display_buffer->set_transformation(mg::transformation(mir_mirror_mode_vertical));
126 if (mirror_mode == mir_mirror_mode_vertical)
127 display_buffer->set_transformation(mg::transformation(mir_mirror_mode_none));
128 if (mirror_mode == mir_mirror_mode_horizontal)
129 {
130 glm::mat2 mat;
131 mat[0][0] = -1;
132 mat[1][1] = -1;
133 display_buffer->set_transformation(mat);
134 }
135
116 auto scheduled = free_queue.num_scheduled();136 auto scheduled = free_queue.num_scheduled();
117 free_queue.schedule(buffer);137 free_queue.schedule(buffer);
118 for(auto i = 0u; i < scheduled; i++)138 for(auto i = 0u; i < scheduled; i++)
@@ -121,6 +141,8 @@
121 display_buffer_compositor->composite(scene->scene_elements_for(this));141 display_buffer_compositor->composite(scene->scene_elements_for(this));
122 if (buffer != ready_queue.next_buffer())142 if (buffer != ready_queue.next_buffer())
123 throw std::runtime_error("unable to capture to buffer");143 throw std::runtime_error("unable to capture to buffer");
144
145 display_buffer->set_transformation(mg::transformation(mirror_mode));
124 }146 }
125147
126private:148private:
@@ -133,6 +155,8 @@
133 std::unique_ptr<compositor::DisplayBufferCompositor> display_buffer_compositor;155 std::unique_ptr<compositor::DisplayBufferCompositor> display_buffer_compositor;
134 std::unique_ptr<graphics::VirtualOutput> virtual_output;156 std::unique_ptr<graphics::VirtualOutput> virtual_output;
135 std::shared_ptr<mg::Buffer> last_captured_buffer;157 std::shared_ptr<mg::Buffer> last_captured_buffer;
158 geom::Size queue_size;
159 MirMirrorMode mirror_mode;
136};160};
137161
138162
@@ -159,14 +183,20 @@
159 size.height.as_int() == 0 ||183 size.height.as_int() == 0 ||
160 region.size.width.as_int() == 0 ||184 region.size.width.as_int() == 0 ||
161 region.size.height.as_int() == 0 ||185 region.size.height.as_int() == 0 ||
162 pixel_format == mir_pixel_format_invalid ||186 ((nbuffers > 1) && (pixel_format == mir_pixel_format_invalid)))
163 nbuffers < 0)
164 {187 {
165 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid parameters"));188 BOOST_THROW_EXCEPTION(std::runtime_error("Invalid parameters"));
166 }189 }
167 std::lock_guard<decltype(session_mutex)> lock{session_mutex};190 std::lock_guard<decltype(session_mutex)> lock{session_mutex};
168 auto const id = next_available_session_id();191 auto const id = next_available_session_id();
169 session_contexts[id] = create_session_context(region, size, pixel_format, nbuffers, mirror_mode);192
193 std::vector<std::shared_ptr<mg::Buffer>> buffers(nbuffers);
194 for (auto& buffer : buffers)
195 {
196 buffer = buffer_allocator->alloc_buffer(
197 mg::BufferProperties{size, pixel_format, mg::BufferUsage::hardware});
198 }
199 session_contexts[id] = create_session_context(region, size, buffers, mirror_mode);
170200
171 return id;201 return id;
172}202}
@@ -204,13 +234,11 @@
204mc::CompositingScreencast::create_session_context(234mc::CompositingScreencast::create_session_context(
205 geometry::Rectangle const& rect,235 geometry::Rectangle const& rect,
206 geometry::Size const& size,236 geometry::Size const& size,
207 MirPixelFormat pixel_format,237 std::vector<std::shared_ptr<mg::Buffer>> const& buffers,
208 int nbuffers,
209 MirMirrorMode mirror_mode)238 MirMirrorMode mirror_mode)
210{239{
211 return std::make_shared<detail::ScreencastSessionContext>(240 return std::make_shared<detail::ScreencastSessionContext>(
212 scene, *display, *buffer_allocator, *db_compositor_factory,241 scene, *display, *db_compositor_factory, buffers, rect, size, mirror_mode);
213 rect, size, pixel_format, nbuffers, mirror_mode);
214}242}
215243
216void mc::CompositingScreencast::capture(244void mc::CompositingScreencast::capture(
217245
=== modified file 'src/server/compositor/compositing_screencast.h'
--- src/server/compositor/compositing_screencast.h 2017-05-08 03:04:26 +0000
+++ src/server/compositor/compositing_screencast.h 2017-06-06 16:26:39 +0000
@@ -64,8 +64,7 @@
64 std::shared_ptr<detail::ScreencastSessionContext>64 std::shared_ptr<detail::ScreencastSessionContext>
65 create_session_context(geometry::Rectangle const& rect,65 create_session_context(geometry::Rectangle const& rect,
66 geometry::Size const& size,66 geometry::Size const& size,
67 MirPixelFormat pixel_format,67 std::vector<std::shared_ptr<graphics::Buffer>> const& buffers,
68 int nbuffers,
69 MirMirrorMode mirror_mode);68 MirMirrorMode mirror_mode);
70 std::shared_ptr<detail::ScreencastSessionContext> session(frontend::ScreencastSessionId id);69 std::shared_ptr<detail::ScreencastSessionContext> session(frontend::ScreencastSessionId id);
7170
7271
=== modified file 'src/server/compositor/screencast_display_buffer.cpp'
--- src/server/compositor/screencast_display_buffer.cpp 2017-05-08 03:04:26 +0000
+++ src/server/compositor/screencast_display_buffer.cpp 2017-06-06 16:26:39 +0000
@@ -72,7 +72,8 @@
72 rect(rect),72 rect(rect),
73 transform(mg::transformation(mirror_mode)),73 transform(mg::transformation(mirror_mode)),
74 free_queue(free_queue), ready_queue(ready_queue),74 free_queue(free_queue), ready_queue(ready_queue),
75 old_fbo(), old_viewport()75 old_fbo(), old_viewport(),
76 current_size(size)
76{77{
77 auto const gl_context_raii = mir::raii::paired_calls(78 auto const gl_context_raii = mir::raii::paired_calls(
78 [this] { gl_context->make_current(); },79 [this] { gl_context->make_current(); },
@@ -182,3 +183,31 @@
182{183{
183 return this;184 return this;
184}185}
186
187geom::Size mc::ScreencastDisplayBuffer::renderbuffer_size()
188{
189 return current_size;
190}
191
192void mc::ScreencastDisplayBuffer::set_renderbuffer_size(geom::Size size)
193{
194 if (size == current_size)
195 return;
196
197 auto depth_buffer = allocate_gl_resource<glGenRenderbuffers, glDeleteRenderbuffers>();
198 glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
199 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
200 size.width.as_uint32_t(),
201 size.height.as_uint32_t());
202 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
203 GL_RENDERBUFFER, depth_buffer);
204
205 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
206 BOOST_THROW_EXCEPTION(std::runtime_error("Failed to create FBO for buffer"));
207 depth_rbo = std::move(depth_buffer);
208}
209
210void mc::ScreencastDisplayBuffer::set_transformation(glm::mat2 const& t)
211{
212 transform = t;
213}
185214
=== modified file 'src/server/compositor/screencast_display_buffer.h'
--- src/server/compositor/screencast_display_buffer.h 2017-05-08 03:04:26 +0000
+++ src/server/compositor/screencast_display_buffer.h 2017-06-06 16:26:39 +0000
@@ -116,6 +116,10 @@
116116
117 NativeDisplayBuffer* native_display_buffer() override;117 NativeDisplayBuffer* native_display_buffer() override;
118118
119 geometry::Size renderbuffer_size();
120 void set_renderbuffer_size(geometry::Size);
121 void set_transformation(glm::mat2 const& transform);
122
119private:123private:
120 std::unique_ptr<renderer::gl::Context> gl_context;124 std::unique_ptr<renderer::gl::Context> gl_context;
121 geometry::Rectangle const rect;125 geometry::Rectangle const rect;
@@ -131,6 +135,8 @@
131 detail::GLResource<glDeleteTextures> color_tex;135 detail::GLResource<glDeleteTextures> color_tex;
132 detail::GLResource<glDeleteRenderbuffers> depth_rbo;136 detail::GLResource<glDeleteRenderbuffers> depth_rbo;
133 detail::GLResource<glDeleteFramebuffers> fbo;137 detail::GLResource<glDeleteFramebuffers> fbo;
138
139 geometry::Size current_size;
134};140};
135141
136}142}
137143
=== modified file 'src/server/frontend/protobuf_message_processor.cpp'
--- src/server/frontend/protobuf_message_processor.cpp 2017-05-08 03:04:26 +0000
+++ src/server/frontend/protobuf_message_processor.cpp 2017-06-06 16:26:39 +0000
@@ -425,7 +425,7 @@
425void mfd::ProtobufMessageProcessor::send_response(425void mfd::ProtobufMessageProcessor::send_response(
426 ::google::protobuf::uint32 id, mir::protobuf::Screencast* response)426 ::google::protobuf::uint32 id, mir::protobuf::Screencast* response)
427{427{
428 if (response->has_buffer_stream())428 if (response->has_buffer_stream() && response->buffer_stream().has_buffer())
429 sender->send_response(id, response,429 sender->send_response(id, response,
430 {extract_fds_from(response->mutable_buffer_stream()->mutable_buffer())});430 {extract_fds_from(response->mutable_buffer_stream()->mutable_buffer())});
431 else431 else
432432
=== modified file 'src/server/frontend/session_mediator.cpp'
--- src/server/frontend/session_mediator.cpp 2017-05-25 08:58:03 +0000
+++ src/server/frontend/session_mediator.cpp 2017-06-06 16:26:39 +0000
@@ -826,6 +826,7 @@
826 protobuf_screencast->mutable_buffer_stream()->set_pixel_format(pixel_format);826 protobuf_screencast->mutable_buffer_stream()->set_pixel_format(pixel_format);
827 protobuf_screencast->mutable_buffer_stream()->mutable_id()->set_value(827 protobuf_screencast->mutable_buffer_stream()->mutable_id()->set_value(
828 screencast_session_id.as_value());828 screencast_session_id.as_value());
829 protobuf_screencast->mutable_buffer_stream()->set_pixel_format(pixel_format);
829830
830 done->Run();831 done->Run();
831}832}
@@ -869,7 +870,6 @@
869 auto session = weak_session.lock();870 auto session = weak_session.lock();
870 ScreencastSessionId const screencast_session_id{request->id().value()};871 ScreencastSessionId const screencast_session_id{request->id().value()};
871 auto buffer = session->get_buffer(mg::BufferID{request->buffer_id()});872 auto buffer = session->get_buffer(mg::BufferID{request->buffer_id()});
872 mf::ScreencastSessionId const screencast_id{request->id().value()};
873 screencast->capture(screencast_session_id, buffer);873 screencast->capture(screencast_session_id, buffer);
874 done->Run();874 done->Run();
875}875}
876876
=== modified file 'tests/acceptance-tests/test_client_screencast.cpp'
--- tests/acceptance-tests/test_client_screencast.cpp 2017-05-08 03:04:26 +0000
+++ tests/acceptance-tests/test_client_screencast.cpp 2017-06-06 16:26:39 +0000
@@ -24,6 +24,7 @@
24#include "mir_test_framework/connected_client_headless_server.h"24#include "mir_test_framework/connected_client_headless_server.h"
25#include "mir/test/doubles/stub_session_authorizer.h"25#include "mir/test/doubles/stub_session_authorizer.h"
26#include "mir/test/fake_shared.h"26#include "mir/test/fake_shared.h"
27#include "mir/test/doubles/mock_gl.h"
2728
28#include <gtest/gtest.h>29#include <gtest/gtest.h>
29#include <gmock/gmock.h>30#include <gmock/gmock.h>
@@ -32,6 +33,8 @@
32namespace mtd = mir::test::doubles;33namespace mtd = mir::test::doubles;
33namespace mf = mir::frontend;34namespace mf = mir::frontend;
34namespace mt = mir::test;35namespace mt = mir::test;
36using namespace testing;
37using namespace std::literals::chrono_literals;
3538
36namespace39namespace
37{40{
@@ -48,6 +51,7 @@
48struct Screencast : mtf::HeadlessInProcessServer51struct Screencast : mtf::HeadlessInProcessServer
49{52{
50 MockSessionAuthorizer mock_authorizer;53 MockSessionAuthorizer mock_authorizer;
54 NiceMock<mtd::MockGL> mockgl;
5155
52 void SetUp() override56 void SetUp() override
53 {57 {
@@ -126,3 +130,84 @@
126 mir_screencast_release_sync(screencast);130 mir_screencast_release_sync(screencast);
127 mir_connection_release(connection);131 mir_connection_release(connection);
128}132}
133
134TEST_F(Screencast, can_cast_to_buffer)
135{
136 EXPECT_CALL(mock_authorizer, screencast_is_allowed(_))
137 .WillOnce(Return(true));
138 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
139
140 auto const buffer = mir_connection_allocate_buffer_sync(
141 connection, default_width, default_height, default_pixel_format);
142
143 ASSERT_TRUE(buffer);
144
145 MirScreencastSpec* spec = mir_create_screencast_spec(connection);
146 //We have to set nbuffers == 0 now to avoid capturing at startup. Current default is 1.
147 mir_screencast_spec_set_number_of_buffers(spec, 0);
148
149 mir_screencast_spec_set_capture_region(spec, &default_capture_region);
150 auto screencast = mir_screencast_create_sync(spec);
151 mir_screencast_spec_release(spec);
152
153 struct Capture
154 {
155 std::mutex mutex;
156 std::condition_variable cv;
157 bool capture = false;
158 } capture;
159
160 mir_screencast_capture_to_buffer(screencast, buffer,
161 [] (MirScreencastResult /*status*/, MirBuffer* /*buffer*/, void* context) {
162 auto c = reinterpret_cast<Capture*>(context);
163 std::unique_lock<decltype(c->mutex)> lk(c->mutex);
164 c->capture = true;
165 c->cv.notify_all();
166 }, &capture );
167
168 std::unique_lock<decltype(capture.mutex)> lk2(capture.mutex);
169 ASSERT_TRUE(capture.cv.wait_for(lk2, 5s, [&] { return capture.capture; }));
170 EXPECT_THAT(mir_buffer_get_error_message(buffer), StrEq(""));
171
172 mir_screencast_release_sync(screencast);
173 mir_connection_release(connection);
174}
175
176TEST_F(Screencast, can_cast_to_buffer_sync)
177{
178 EXPECT_CALL(mock_authorizer, screencast_is_allowed(_))
179 .WillOnce(Return(true));
180 auto const connection = mir_connect_sync(new_connection().c_str(), __PRETTY_FUNCTION__);
181
182 struct BufferSync
183 {
184 MirBuffer* buffer = nullptr;
185 std::mutex mutex;
186 std::condition_variable cv;
187 } buffer_info;
188
189 mir_connection_allocate_buffer(
190 connection,
191 default_width, default_height, default_pixel_format,
192 [](MirBuffer* b, void* ctxt) {
193 auto info = reinterpret_cast<BufferSync*>(ctxt);
194 std::unique_lock<decltype(info->mutex)> lk(info->mutex);
195 info->buffer = b;
196 info->cv.notify_all();
197 }, &buffer_info);
198 std::unique_lock<decltype(buffer_info.mutex)> lk(buffer_info.mutex);
199 ASSERT_TRUE(buffer_info.cv.wait_for(lk, 5s, [&] { return buffer_info.buffer; }));
200
201 MirScreencastSpec* spec = mir_create_screencast_spec(connection);
202 //We have to set nbuffers == 0 now to avoid capturing at startup. Current default is 1.
203 mir_screencast_spec_set_number_of_buffers(spec, 0);
204
205 mir_screencast_spec_set_capture_region(spec, &default_capture_region);
206 auto screencast = mir_screencast_create_sync(spec);
207
208 mir_screencast_spec_release(spec);
209 mir_screencast_capture_to_buffer_sync(screencast, buffer_info.buffer);
210
211 mir_screencast_release_sync(screencast);
212 mir_connection_release(connection);
213}
129214
=== modified file 'tests/unit-tests/compositor/test_compositing_screencast.cpp'
--- tests/unit-tests/compositor/test_compositing_screencast.cpp 2017-05-08 03:04:26 +0000
+++ tests/unit-tests/compositor/test_compositing_screencast.cpp 2017-06-06 16:26:39 +0000
@@ -251,7 +251,6 @@
251 EXPECT_THROW(screencast.create_session(invalid_region, default_size, default_pixel_format, default_num_buffers, default_mirror_mode), std::runtime_error);251 EXPECT_THROW(screencast.create_session(invalid_region, default_size, default_pixel_format, default_num_buffers, default_mirror_mode), std::runtime_error);
252 EXPECT_THROW(screencast.create_session(default_region, invalid_size, default_pixel_format, default_num_buffers, default_mirror_mode), std::runtime_error);252 EXPECT_THROW(screencast.create_session(default_region, invalid_size, default_pixel_format, default_num_buffers, default_mirror_mode), std::runtime_error);
253 EXPECT_THROW(screencast.create_session(default_region, default_size, mir_pixel_format_invalid, default_num_buffers, default_mirror_mode), std::runtime_error);253 EXPECT_THROW(screencast.create_session(default_region, default_size, mir_pixel_format_invalid, default_num_buffers, default_mirror_mode), std::runtime_error);
254 EXPECT_THROW(screencast.create_session(default_region, default_size, mir_pixel_format_invalid, 0, default_mirror_mode), std::runtime_error);
255}254}
256255
257TEST_F(CompositingScreencastTest, throws_on_capture_with_invalid_session_id)256TEST_F(CompositingScreencastTest, throws_on_capture_with_invalid_session_id)

Subscribers

People subscribed via source and target branches