Mir

Merge lp:~cemil-azizoglu/mir/mir-render-surface into lp:mir

Proposed by Cemil Azizoglu
Status: Work in progress
Proposed branch: lp:~cemil-azizoglu/mir/mir-render-surface
Merge into: lp:mir
Diff against target: 1709 lines (+1267/-6)
27 files modified
CMakeLists.txt (+8/-0)
playground/CMakeLists.txt (+19/-0)
playground/eglflash_render_surface.c (+152/-0)
playground/render_surface.cpp (+253/-0)
src/client/CMakeLists.txt (+2/-0)
src/client/buffer_stream.cpp (+9/-0)
src/client/buffer_stream.h (+4/-0)
src/client/client_buffer_stream.h (+2/-0)
src/client/connection_surface_map.h (+6/-1)
src/client/error_stream.cpp (+16/-0)
src/client/error_stream.h (+8/-0)
src/client/mir_buffer_stream_api.cpp (+6/-1)
src/client/mir_connection.cpp (+29/-2)
src/client/mir_connection.h (+2/-0)
src/client/mir_render_surface.h (+58/-0)
src/client/mir_render_surface_api.cpp (+140/-0)
src/client/mir_surface.cpp (+2/-0)
src/client/mir_surface.h (+3/-1)
src/client/mir_surface_api.cpp (+40/-1)
src/client/render_surface.cpp (+278/-0)
src/client/render_surface.h (+128/-0)
src/client/screencast_stream.cpp (+5/-0)
src/client/screencast_stream.h (+1/-0)
src/client/surface_map.cpp (+14/-0)
src/client/symbols.map (+8/-0)
src/include/client/mir_toolkit/client_types_nbs.h (+1/-0)
src/include/client/mir_toolkit/mir_render_surface.h (+73/-0)
To merge this branch: bzr merge lp:~cemil-azizoglu/mir/mir-render-surface
Reviewer Review Type Date Requested Status
Mir development team Pending
Review via email: mp+300125@code.launchpad.net
To post a comment you must log in.
3591. By Kevin DuBois

Suppress memory leak in libhybris generated when probing android platforms.

also disable a failing mir_privileged_test until proper fix can be found.
(LP: #1603145)

Fixes: LP: #1602199

3592. By Alan Griffiths

Add missing dependencies to mirtest.pc (LP: #1603080)

3593. By Daniel van Vugt

Fix build/autolanding failure due to ODR violation in MockEGL
(LP: #1603303)

Since /usr/include/EGL/eglplatform.h is full of #ifdefs and the Mir
source uses multiple different interpretations of those #ifdefs,
we can't safely define any C++ class that accepts the Native* types
as parameters.
. Fixes: https://bugs.launchpad.net/bugs/1603303.

Approved by Daniel van Vugt, mir-ci-bot.

3594. By Daniel van Vugt

Fix Super key not working any more since r3565 (LP: #1602966), so that
the kernel's KEY_LEFTMETA once again maps to Mir's
mir_input_event_modifier_meta_left.

It was an understandable mistake as the Super key is actually:
   Kernel: KEY_LEFTMETA
   XKB: XKB_KEY_Super_L (not XKB_KEY_Meta_L)
   Mir: mir_input_event_modifier_meta_left
. Fixes: https://bugs.launchpad.net/bugs/1602966.

Approved by mir-ci-bot, Cemil Azizoglu.

3595. By Daniel van Vugt

Bump version to 0.25.0; we already branched series 0.24.

Approved by mir-ci-bot, Cemil Azizoglu.

3596. By Daniel van Vugt

Forward-port a one-line fix from lp:mir/0.24 where the fix for
LP: #1603303 caused build failure. Only fails in lp:mir/0.24 right now
but best to keep the branches in sync. Fixes: https://bugs.launchpad.net/bugs/1603303.

Approved by Alan Griffiths, mir-ci-bot.

3597. By Alan Griffiths

Avoid statically linking mircommon objects - having just one copy in the .so avoids (potential) issues.

Approved by Kevin DuBois, mir-ci-bot.

3598. By Alan Griffiths

Enhanced mir_test_framework::library_path() to better locate the Mir library directory (and fix problems using libmir-test-assist.a downstream). Fixes: https://bugs.launchpad.net/bugs/1603091.

Approved by mir-ci-bot, Kevin DuBois.

3599. By Kevin DuBois

fix LP: #1603114 by removing the stub_input_platform.cpp from the mir-test-assist.a library (its header is private anyways). Link mir_umock_unit_tests to the object file instead.

fixes: LP: #1603114. Fixes: https://bugs.launchpad.net/bugs/1603114.

Approved by mir-ci-bot, Alan Griffiths.

3600. By Daniel van Vugt

Attempt to build and package missing arm64 binaries for
the Android platform (LP: #1579866). Fixes: https://bugs.launchpad.net/bugs/1579866.

Approved by mir-ci-bot, Łukasz Zemczak, Kevin DuBois.

3601. By Kevin DuBois

fix ftbfs in xenial and yakkety overlays. Problem seems to be some sort of template instantiation location problem problem with gmock in libmir-test-assist, but haven't been able to find a solution that keeps mir_umock_acceptance_tests reliant on mir-test-assist though.

fixes LP: #1601810. Fixes: https://bugs.launchpad.net/bugs/1601810.

Approved by mir-ci-bot, Cemil Azizoglu, Alan Griffiths.

3602. By Daniel van Vugt

bzrignore: Don't ignore the 'build' directory. That prevents the command
'bzr clean-tree' from removing it. Which for my muscle memory at least
is annoying.

Also, doesn't anyone else occasionally have other build directories not
called 'build'? Treating that name as special is inconsistent as only
the other build dirs not called 'build' will get cleaned out.

Approved by Kevin DuBois, mir-ci-bot.

3603. By Kevin DuBois

update symbols to reflect the symbols actually captured in the 0.24 release.

Approved by Daniel van Vugt, mir-ci-bot.

3604. By Alan Griffiths

Deprecate useless mir_connection_create_spec_for_tooltip() and add mir_connection_create_spec_for_tip(). Fixes: https://bugs.launchpad.net/bugs/1603922.

Approved by mir-ci-bot, Kevin DuBois, Cemil Azizoglu.

3605. By Daniel van Vugt

Fix one space typo that's the only obviously wrong difference between
0.24 and 0.25 after this lands: lp:~kdub/mir/update-symbols-from-0.24
.

Approved by mir-ci-bot, Cemil Azizoglu.

3606. By Alan Griffiths

Use "struct Rectangle" consistently.

Approved by mir-ci-bot, Cemil Azizoglu, Kevin DuBois.

3607. By Kevin DuBois

android: plumb the fencing support that the NBS api needs. Specifically, add timeout-based fence waits.

Also change the public MirNativeFence* (which was a void**) to just a MirNativeFence (void*) to be easier to use/less misleading.

Approved by Cemil Azizoglu, Alan Griffiths, mir-ci-bot.

3608. By Daniel van Vugt

Revert previous commit. It fails to build on yakkety desktop.

3609. By Kevin DuBois

reorganize the nested code a bit so that there's a mgn::Platform that overrides the display creation, instead of relying on the DefaultConfiguration to intercept create_display calls. Prepares for "nested passthrough" where the nested server will have to give a MirBuffer from the host server to its client. (And will have to override the GraphicsBufferAllocator, much like its currently overriding the Display).

Approved by Alexandros Frantzis, Chris Halse Rogers, mir-ci-bot.

3610. By Daniel van Vugt

Make desktop zoom with touchpads smoother and more usable.

This doesn't change anything for mouse wheels as they emit vscroll values
of 1 or -1 anyway. For touchpads, this makes zooming smoother and more
controllable. (Super+mousewheel or Super+two-finger-scroll).

Approved by Alexandros Frantzis, mir-ci-bot, Chris Halse Rogers.

3611. By Brandon Schaefer

Update the confine region if we are modifying the state/width/height. Fixes: https://bugs.launchpad.net/bugs/1604673.

Approved by Alan Griffiths, mir-ci-bot.

3612. By Brandon Schaefer

Put the symbol in the 0.24 section (which has already been split for release). Make a new symbol section 0.25 and put that symbol there.

Approved by mir-ci-bot, Daniel van Vugt, Chris Halse Rogers.

3613. By Cemil Azizoglu

Refine x11 build files.

Approved by Alexandros Frantzis, mir-ci-bot.

3614. By Alexandros Frantzis

platform: Introduce Display::native_display().

Approved by mir-ci-bot, Cemil Azizoglu, Andreas Pokorny, Kevin DuBois.

3615. By Chris Halse Rogers

Improvements to no-TLS-future.

Since we hope that the bionic-and-hybris-fight-over-TLS-slots bug will - in some halcyon future - be fixed this branch makes NoTLSFuture behave more like std::future so we hopefully don't rely on non-standard behaviour.

Additionally, because a continuation interface would be really handy for removing an implicit RPC wait in BufferStream, implement a reasonable approximation of the .then() interface in the Concurrency TS (N4107 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4107.html#future).

Approved by Alexandros Frantzis, Alan Griffiths, mir-ci-bot.

3616. By Andreas Pokorny

Combine mirclientrpc-static and mirclient-static itself into a single static library

This avoids static library linking order problems between code that is defined inside client/events and client/rpc which before ended up in mirclient-static and mirclientrpc-static.

Approved by Kevin DuBois, Alan Griffiths, mir-ci-bot.

3617. By Alexandros Frantzis

tests: Fix ServerConfigurationOptions test to run safely with ptest. Fixes: https://bugs.launchpad.net/bugs/1607351.

Approved by mir-ci-bot, Alan Griffiths.

3618. By Kevin DuBois

android: Plumb the fencing support that the NBS API needs. Specifically, add timeout-based fence waits.

Also change the public MirNativeFence* (which was a void**) to just a MirNativeFence (void*) to be easier to use/less misleading.

Approved by mir-ci-bot, Cemil Azizoglu, Alan Griffiths.

3619. By Alexandros Frantzis

platform: Move GL specific methods from mg::Display to mir::renderer::gl::ContextSource.

Approved by Alan Griffiths, Cemil Azizoglu, Kevin DuBois, mir-ci-bot.

3620. By Daniel van Vugt

Add some value totals to a few enums visible in the client API.
And also fix some switch statements that then complain due to missing
'default:'.

I needed these enum values yesterday when working on Xmir but found
they did not exist.
.

Approved by mir-ci-bot, Alan Griffiths, Cemil Azizoglu.

3621. By Brandon Schaefer

Use a different way to tell the abstract shell to update its seat.

Fixes a race in the test. We update the confinement on a resized_to or a move_to in the surface observer. The order is not guaranteed or rather most cases we are getting the callback in the test that we resized before the abstract shell. Leading to a race.

To fix this, we have implemented a seat report that will report when events are done. Now we can mock this and check we got this report. This will be good for normal logging. I will finish up the rest of the events for the seat report after this branch. Fixes: https://bugs.launchpad.net/bugs/1606418.

Approved by mir-ci-bot, Alan Griffiths, Andreas Pokorny.

3622. By Daniel van Vugt

Document the FAQ about mirvanity accuracy.

Approved by Cemil Azizoglu, mir-ci-bot.

3623. By Daniel van Vugt

Clarify comments around full desktop GL support. It's likely no further
changes are required in the Mir source and we're just waiting on an
upstream Mesa fix.
. Fixes: https://bugs.launchpad.net/bugs/1420581.

Approved by mir-ci-bot, Cemil Azizoglu.

3624. By Brandon Schaefer

A demo to show off pointer confinement and a way to test it out. Need to look at fullscreen and other possible issues.

Approved by mir-ci-bot, Daniel van Vugt, Alan Griffiths.

3625. By Daniel van Vugt

Fix lots of clang warnings/errors that cause build failure.

Approved by Alan Griffiths, mir-ci-bot.

3626. By Alexandros Frantzis

Fix precompiled header builds with gcc-6.

Approved by mir-ci-bot, Alan Griffiths.

3627. By Alexandros Frantzis

renderer: Begin extraction of renderer interfaces to their own library and package.

Approved by Alan Griffiths, Cemil Azizoglu, mir-ci-bot.

3628. By Daniel van Vugt

FD zero is valid and not an error. Just highly unlikely you'll ever see
zero being used unless you've closed your stdin first.

Approved by mir-ci-bot, Alan Griffiths.

3629. By Alan Griffiths

Add new dependency on mir-renderer-gl-dev to mirtest.pc

3630. By Kevin DuBois

fix "cmake .. -DMIR_PLATFORM=android" build.

fixes: LP: #1609916
. Fixes: https://bugs.launchpad.net/bugs/1609916.

Approved by Daniel van Vugt, mir-ci-bot.

3631. By Daniel van Vugt

Fix a few problems that have prevented cross-compile-chroot.sh from
actually working in a while (LP: #1609329)

  * Fixed error: Some build deps not found (because they are in
    universe rather than main?).
  * Fixed error: Building on yakkety as of recently (today) defaults
    to GCC 6, so the default compiler version when targeting xenial
    or wily now needs to be explicitly set to 5.
  * Fixed error: Precompiled headers from GCC 6 don't work when
    targeting any distro other than yakkety, so don't use them.
  * Fixed error: Some headers from android-headers-23 are missing
    #includes, but apparently only when cross-compiling.
  * Fixed warning: Missing public keys for Ubuntu archive.
. Fixes: https://bugs.launchpad.net/bugs/1609329.

Approved by mir-ci-bot, Chris Halse Rogers, Kevin DuBois.

3632. By Alan Griffiths

We don't need mir_add_library_with_symbols() (a self confessed "abysmal hack"). We should use LINK_DEPENDS which is "intended to specify dependencies on “linker scripts” for custom Makefile link rules.".

Approved by Daniel van Vugt, Kevin DuBois, mir-ci-bot.

3633. By Daniel van Vugt

eglstream: Simplify logging calls
.

Approved by Alan Griffiths, Andreas Pokorny, mir-ci-bot.

3634. By Alexandros Frantzis

tests: Don't build with LTO. Fixes: https://bugs.launchpad.net/bugs/1610215.

Approved by Daniel van Vugt, Cemil Azizoglu, Kevin DuBois, mir-ci-bot.

3635. By Daniel van Vugt

Work around clang build failure on yakkety with the gcc6 headers
(LP: #1609612)

It seems like such a simple problem, but I can't figure out a solution
yet. Only removing the expectation allows the build to complete. And
all tests pass.
. Fixes: https://bugs.launchpad.net/bugs/1609612.

Approved by Cemil Azizoglu, mir-ci-bot.

3636. By Ratchanan Srirattanamet

android: make use of new PbufferGLContext constructor in DeviceQuirks

Originally, DeviceQuirks creates a PbufferGLContext with
mir_pixel_format_abgr_8888 hard-coded as a format. This causes a problem
on a device without mir_pixel_format_abgr_8888 support. This revision
make use of new PbufferGLContext constructor which doesn't have to
specify a display format. This makes the code not depending on the
availability of mir_pixel_format_abgr_8888 format on the device.

Approved by: camako, kdub, alan_g, duflu

3637. By Alan Griffiths

Avoid potential use of an unspecified state when testing with the stub graphics platform (LP: #1611337). Fixes: https://bugs.launchpad.net/bugs/1611337.

Approved by Daniel van Vugt, mir-ci-bot.

3638. By Daniel van Vugt

On those devices that have KMS but no hardware cursor support,
fall back automatically to the software cursor (LP: #1610054). Fixes: https://bugs.launchpad.net/bugs/1610054.

Approved by Cemil Azizoglu, mir-ci-bot.

3639. By Andreas Pokorny

Fix server hang ups and allocation failures when client recreate buffer streams

When a mir client destroys a buffer stream the destruction result callback will trigger a buffer release of the associated buffers. That buffer release request inevitable fails in session mediator because it fails to resolve the BufferStreamId. This change handles exceptions during the attempt to disassociate buffers from already deleted buffer streams to ensure that the actual buffer release can happen.

This error is not really a leak - the buffers were deleted when the client disconnects and the server would be able to serve new clients.

Approved by Kevin DuBois, mir-ci-bot.

3640. By Kevin DuBois

Increase timeout for MultiThreadedCompositor.cleans_up_after_throw_in_start test,
which can fail when CI is very slow

fixes: LP: #1595940. Fixes: https://bugs.launchpad.net/bugs/1595940.

Approved by mir-ci-bot, Alan Griffiths, Cemil Azizoglu.

3641. By Alexandros Frantzis

Fix clang build on yakkety. Fixes: https://bugs.launchpad.net/bugs/1609612.

Approved by mir-ci-bot, Chris Halse Rogers, Daniel van Vugt, Alan Griffiths, Cemil Azizoglu.

3642. By Chris Halse Rogers

Add subpixel arrangement info to the display configuration API.

Current platforms only provide mir_subpixel_arrangement_unknown, and need to add support for setting this to platform-provided values before this will be useful.

Fixes (part one): https://bugs.launchpad.net/mir/+bug/1393578. Fixes: https://bugs.launchpad.net/bugs/1393578.

Approved by mir-ci-bot, Cemil Azizoglu, Daniel van Vugt, Kevin DuBois.

3643. By Chris Halse Rogers

Improvements to mtd::FakeDisplay.

Throw an exception when writing to/reading from the configuration change event trigger fails rather than silently continuing, blithely unaware that the call has failed.

Switch from a pipe to an eventfd; eventfd is the solution tailored for this use-case.

Presented in the forlorn hope that it makes a test that appears to be flaky on vivid+clang, but does not appear that it's possible for it to be flaky, stops being flaky. Either by consistently passing, or consistently failing!.

Approved by Alexandros Frantzis, Kevin DuBois, mir-ci-bot.

3644. By Kevin DuBois

Have the MirSurface report the shell-designated size like it used to, instead of the spec-requested size.

fixes: LP: #1612256. Fixes: https://bugs.launchpad.net/bugs/1612256.

Approved by mir-ci-bot, Alan Griffiths.

3645. By Andreas Pokorny

Use the pixel format of the individual buffer stream to infer shaped()

It is a valid scenario to have an opaque buffer (or buffer stream) for the first layer in a surface and have further transparent or also opaque layers on top. This change removes the constant "non_rectangular" parameter of BasicSurface, and instead looks at the actual streams that are attached to surface.

With mir_presentation_queue it might be worth thinking about going one step further and actually look at the mg::Buffer that would be drawn next. An attempt to do so showed that it would require a few further refactoring steps in our integration test setup.
.

Approved by Kevin DuBois, mir-ci-bot, Alexandros Frantzis.

3646. By Chris Halse Rogers

Provide subpixel arrangement info from the mesa-kms platform. Fixes: https://bugs.launchpad.net/bugs/1393578.

Approved by mir-ci-bot, Kevin DuBois, Cemil Azizoglu.

Unmerged revisions

3647. By Cemil Azizoglu

MirRenderSurface works - no tests

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-08-10 10:43:39 +0000
3+++ CMakeLists.txt 2016-08-12 21:54:21 +0000
4@@ -189,6 +189,14 @@
5 endif()
6 endforeach(platform)
7
8+#set(EGL_LIBRARIES EGL)
9+#set(EGL_INCLUDE_DIRS /home/camako/git/mesa/usr/local/include)
10+
11+#set(GLESv2_LIBRARIES GLESv2)
12+#set(GLESv2_INCLUDE_DIRS /home/camako/git/mesa/usr/local/include)
13+
14+#link_directories(/home/camako/git/mesa/usr/local/lib)
15+
16 find_package(EGL REQUIRED)
17 find_package(GLESv2 REQUIRED)
18 find_package(GLM REQUIRED)
19
20=== modified file 'playground/CMakeLists.txt'
21--- playground/CMakeLists.txt 2016-08-01 14:43:19 +0000
22+++ playground/CMakeLists.txt 2016-08-12 21:54:21 +0000
23@@ -30,6 +30,15 @@
24 m
25 )
26
27+mir_add_wrapped_executable(mir_demo_client_render_surface
28+ render_surface.cpp
29+)
30+
31+target_link_libraries(mir_demo_client_render_surface
32+ mirclient
33+ eglapp
34+)
35+
36 mir_add_wrapped_executable(mir_demo_client_chain_jumping_buffers
37 mir_demo_client_chain_jumping_buffers.c
38 )
39@@ -37,3 +46,13 @@
40 target_link_libraries(mir_demo_client_chain_jumping_buffers
41 mirclient
42 )
43+
44+mir_add_wrapped_executable(mir_demo_client_eglflash_render_surface
45+ eglflash_render_surface.c
46+)
47+
48+target_link_libraries(mir_demo_client_eglflash_render_surface
49+ mirclient
50+ ${EGL_LIBRARIES}
51+ ${GLESv2_LIBRARIES}
52+)
53
54=== added file 'playground/eglflash_render_surface.c'
55--- playground/eglflash_render_surface.c 1970-01-01 00:00:00 +0000
56+++ playground/eglflash_render_surface.c 2016-08-12 21:54:21 +0000
57@@ -0,0 +1,152 @@
58+/*
59+ * Trivial GL demo; flashes the screen with colors using a MirRenderSurface.
60+ *
61+ * Copyright © 2016 Canonical Ltd.
62+ *
63+ * This program is free software: you can redistribute it and/or modify
64+ * it under the terms of the GNU General Public License version 3 as
65+ * published by the Free Software Foundation.
66+ *
67+ * This program is distributed in the hope that it will be useful,
68+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
69+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70+ * GNU General Public License for more details.
71+ *
72+ * You should have received a copy of the GNU General Public License
73+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
74+ *
75+ * Author: Cemil Azizoglu <cemil.azizoglu@canonical.com>
76+ */
77+
78+#include <mir_toolkit/mir_client_library.h>
79+#include "mir_toolkit/mir_render_surface.h"
80+
81+#include <stdio.h>
82+#include <string.h>
83+#include <unistd.h>
84+#include <EGL/egl.h>
85+#include <GLES2/gl2.h>
86+#include <pthread.h>
87+
88+typedef struct Color
89+{
90+ GLfloat r, g, b, a;
91+} Color;
92+
93+#define CHECK(_cond, _err) \
94+ if (!(_cond)) \
95+ { \
96+ printf("%s\n", (_err)); \
97+ return -1; \
98+ }
99+
100+int main(int argc, char *argv[])
101+{
102+ (void) argc;
103+ (void) argv;
104+ unsigned int num_frames = 0;
105+ const char* appname = "EGL Render Surface Demo";
106+ int width = 100;
107+ int height = 100;
108+ EGLDisplay egldisplay;
109+ EGLSurface eglsurface;
110+ EGLint ctxattribs[] =
111+ {
112+ EGL_CONTEXT_CLIENT_VERSION, 2,
113+ EGL_NONE
114+ };
115+ EGLContext eglctx;
116+ EGLConfig eglconfig;
117+ EGLint neglconfigs;
118+ EGLBoolean ok;
119+ MirConnection* connection = NULL;
120+ MirSurface* surface = NULL;
121+ MirRenderSurface* render_surface = NULL;
122+
123+ connection = mir_connect_sync(NULL, appname);
124+ CHECK(mir_connection_is_valid(connection), "Can't get connection");
125+
126+ egldisplay = eglGetDisplay(
127+ mir_connection_get_egl_native_display(connection));
128+ CHECK(egldisplay != EGL_NO_DISPLAY, "Can't eglGetDisplay");
129+
130+ ok = eglInitialize(egldisplay, NULL, NULL);
131+ CHECK(ok, "Can't eglInitialize");
132+
133+ const EGLint attribs[] =
134+ {
135+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
136+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
137+ EGL_RED_SIZE, 8,
138+ EGL_GREEN_SIZE, 8,
139+ EGL_BLUE_SIZE, 8,
140+ EGL_ALPHA_SIZE, 8,
141+ EGL_NONE
142+ };
143+
144+ ok = eglChooseConfig(egldisplay, attribs, &eglconfig, 1, &neglconfigs);
145+ CHECK(ok, "Could not eglChooseConfig");
146+ CHECK(neglconfigs > 0, "No EGL config available");
147+
148+ MirPixelFormat pixel_format =
149+ mir_connection_get_egl_pixel_format(connection, egldisplay, eglconfig);
150+
151+ printf("Mir chose pixel format %d.\n", pixel_format);
152+
153+ MirSurfaceSpec *spec =
154+ mir_connection_create_spec_for_normal_surface(connection, width, height, pixel_format);
155+ CHECK(spec, "Can't create a surface spec");
156+
157+ mir_surface_spec_set_name(spec, appname);
158+
159+ render_surface = mir_connection_create_render_surface(connection);
160+ CHECK(mir_render_surface_is_valid(render_surface), "could not create render surface");
161+
162+ mir_surface_spec_add_render_surface(spec, width, height, 0, 0, render_surface);
163+
164+ surface = mir_surface_create_sync(spec);
165+
166+ mir_surface_spec_release(spec);
167+
168+ eglsurface = eglCreateWindowSurface(egldisplay, eglconfig,
169+ (EGLNativeWindowType)mir_render_surface_egl_native_window(render_surface), NULL);
170+ CHECK(eglsurface != EGL_NO_SURFACE, "eglCreateWindowSurface failed");
171+
172+ eglctx = eglCreateContext(egldisplay, eglconfig, EGL_NO_CONTEXT,
173+ ctxattribs);
174+ CHECK(eglctx != EGL_NO_CONTEXT, "eglCreateContext failed");
175+
176+ ok = eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglctx);
177+ CHECK(ok, "Can't eglMakeCurrent");
178+
179+ Color red = {1.0f, 0.0f, 0.0f, 1.0f};
180+ Color green = {0.0f, 1.0f, 0.0f, 1.0f};
181+ Color blue = {0.0f, 0.0f, 1.0f, 1.0f};
182+
183+ do
184+ {
185+ printf("here %d\n", num_frames);
186+ glClearColor(red.r, red.g, red.b, red.a);
187+ glClear(GL_COLOR_BUFFER_BIT);
188+ eglSwapBuffers(egldisplay, eglsurface);
189+ sleep(1);
190+
191+ glClearColor(green.r, green.g, green.b, green.a);
192+ glClear(GL_COLOR_BUFFER_BIT);
193+ eglSwapBuffers(egldisplay, eglsurface);
194+ sleep(1);
195+
196+ glClearColor(blue.r, blue.g, blue.b, blue.a);
197+ glClear(GL_COLOR_BUFFER_BIT);
198+ eglSwapBuffers(egldisplay, eglsurface);
199+ sleep(1);
200+ } while (num_frames++ < 3);
201+
202+ eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
203+ eglTerminate(egldisplay);
204+ mir_render_surface_release(render_surface);
205+ mir_surface_release_sync(surface);
206+ mir_connection_release(connection);
207+
208+ return 0;
209+}
210
211=== added file 'playground/render_surface.cpp'
212--- playground/render_surface.cpp 1970-01-01 00:00:00 +0000
213+++ playground/render_surface.cpp 2016-08-12 21:54:21 +0000
214@@ -0,0 +1,253 @@
215+/*
216+ * Copyright © 2016 Canonical Ltd.
217+ *
218+ * This program is free software: you can redistribute it and/or modify
219+ * it under the terms of the GNU General Public License version 3 as
220+ * published by the Free Software Foundation.
221+ *
222+ * This program is distributed in the hope that it will be useful,
223+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
224+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
225+ * GNU General Public License for more details.
226+ *
227+ * You should have received a copy of the GNU General Public License
228+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
229+ *
230+ * Author:
231+ * Cemil Azizoglu <cemil.azizoglu@canonical.com>
232+ */
233+
234+#include <boost/program_options.hpp>
235+#include <iostream>
236+#include <thread>
237+#include <signal.h>
238+#include <sys/signalfd.h>
239+#include <poll.h>
240+
241+#include "mir_toolkit/mir_client_library.h"
242+#include "mir_toolkit/mir_render_surface.h"
243+#include "mir_toolkit/mir_presentation_chain.h"
244+
245+#include "client_helpers.h"
246+
247+namespace me = mir::examples;
248+
249+class Pixel
250+{
251+public:
252+ Pixel(void* addr, MirPixelFormat format)
253+ : addr{addr},
254+ format{format}
255+ {
256+ }
257+
258+ void write(int r, int g, int b, int a)
259+ {
260+ switch (format)
261+ {
262+ case mir_pixel_format_abgr_8888:
263+ *((uint32_t*) addr) =
264+ (uint32_t) a << 24 |
265+ (uint32_t) b << 16 |
266+ (uint32_t) g << 8 |
267+ (uint32_t) r;
268+ break;
269+ case mir_pixel_format_xbgr_8888:
270+ *((uint32_t*) addr) =
271+ /* Not filling in the X byte is correct but buggy (LP: #1423462) */
272+ (uint32_t) b << 16 |
273+ (uint32_t) g << 8 |
274+ (uint32_t) r;
275+ break;
276+ case mir_pixel_format_argb_8888:
277+ *((uint32_t*) addr) =
278+ (uint32_t) a << 24 |
279+ (uint32_t) r << 16 |
280+ (uint32_t) g << 8 |
281+ (uint32_t) b;
282+ break;
283+ case mir_pixel_format_xrgb_8888:
284+ *((uint32_t*) addr) =
285+ /* Not filling in the X byte is correct but buggy (LP: #1423462) */
286+ (uint32_t) r << 16 |
287+ (uint32_t) g << 8 |
288+ (uint32_t) b;
289+ break;
290+ case mir_pixel_format_rgb_888:
291+ *((uint8_t*) addr) = r;
292+ *((uint8_t*) addr + 1) = g;
293+ *((uint8_t*) addr + 2) = b;
294+ break;
295+ case mir_pixel_format_bgr_888:
296+ *((uint8_t*) addr) = b;
297+ *((uint8_t*) addr + 1) = g;
298+ *((uint8_t*) addr + 2) = r;
299+ break;
300+ default:
301+ throw std::runtime_error{"Pixel format unsupported by Pixel::write!"};
302+ }
303+ }
304+
305+public:
306+ void* const addr;
307+ MirPixelFormat const format;
308+};
309+
310+class pixel_iterator : std::iterator<std::random_access_iterator_tag, Pixel>
311+{
312+public:
313+ pixel_iterator(MirGraphicsRegion const& region, int x, int y)
314+ : x{x},
315+ y{y},
316+ buffer(region)
317+ {
318+ }
319+
320+ pixel_iterator(MirGraphicsRegion const& region)
321+ : pixel_iterator(region, 0, 0)
322+ {
323+ }
324+
325+
326+ pixel_iterator& operator++()
327+ {
328+ x++;
329+ if (x == buffer.width)
330+ {
331+ x = 0;
332+ y++;
333+ }
334+ return *this;
335+ }
336+ pixel_iterator operator++(int)
337+ {
338+ auto old = *this;
339+ ++(*this);
340+ return old;
341+ }
342+
343+ Pixel operator*() const
344+ {
345+ return Pixel{
346+ buffer.vaddr + (x * MIR_BYTES_PER_PIXEL(buffer.pixel_format)) + (y * buffer.stride), buffer.pixel_format};
347+ }
348+
349+ bool operator==(pixel_iterator const& rhs)
350+ {
351+ return rhs.buffer.vaddr == buffer.vaddr &&
352+ rhs.x == x &&
353+ rhs.y == y;
354+ }
355+
356+ bool operator!=(pixel_iterator const& rhs)
357+ {
358+ return !(*this == rhs);
359+ }
360+
361+private:
362+ int x, y;
363+ MirGraphicsRegion const buffer;
364+};
365+
366+pixel_iterator begin(MirGraphicsRegion const& region)
367+{
368+ return pixel_iterator(region);
369+}
370+
371+pixel_iterator end(MirGraphicsRegion const& region)
372+{
373+ return pixel_iterator{region, 0, region.height};
374+}
375+
376+void fill_stream_with(MirBufferStream* stream, int r, int g, int b, int a)
377+{
378+ MirGraphicsRegion buffer;
379+ mir_buffer_stream_get_graphics_region(stream, &buffer);
380+
381+ for (auto pixel : buffer)
382+ {
383+ pixel.write(r, g, b, a);
384+ }
385+}
386+
387+void bounce_position(int& position, int& delta, int min, int max)
388+{
389+ if (position <= min || position >= max)
390+ {
391+ delta = -delta;
392+ }
393+ position += delta;
394+}
395+
396+int main(int /*argc*/, char* /*argv*/[])
397+{
398+ char const* socket = nullptr;
399+ int const width = 200;
400+ int const height = 200;
401+ int baseColour = 255, dbase = 1;
402+ unsigned int nformats{0};
403+ MirPixelFormat pixel_format;
404+
405+ me::Connection connection{socket, "MirRenderSurface example"};
406+ auto render_surface = mir_connection_create_render_surface(connection);
407+
408+ if (!mir_render_surface_is_valid(render_surface))
409+ throw std::runtime_error(std::string("could not create render surface"));
410+
411+ mir_connection_get_available_surface_formats(connection, &pixel_format, 1, &nformats);
412+ if (nformats == 0)
413+ throw std::runtime_error("no pixel formats for buffer stream");
414+
415+ auto spec = mir_connection_create_spec_for_normal_surface(
416+ connection,
417+ width, height,
418+ pixel_format);
419+
420+ mir_surface_spec_set_name(spec, "Stream");
421+ mir_surface_spec_set_buffer_usage(spec, mir_buffer_usage_software);
422+
423+ auto buffer_stream = mir_render_surface_create_buffer_stream_sync(
424+ render_surface,
425+ width, height,
426+ pixel_format,
427+ mir_buffer_usage_software);
428+
429+ mir_surface_spec_add_render_surface(spec, width, height, 0, 0, render_surface);
430+
431+ auto surface = mir_surface_create_sync(spec);
432+ mir_surface_spec_release(spec);
433+
434+ fill_stream_with(buffer_stream, 255, 0, 0, 128);
435+ mir_buffer_stream_swap_buffers_sync(buffer_stream);
436+
437+ sigset_t halt_signals;
438+ sigemptyset(&halt_signals);
439+ sigaddset(&halt_signals, SIGTERM);
440+ sigaddset(&halt_signals, SIGQUIT);
441+ sigaddset(&halt_signals, SIGINT);
442+
443+ sigprocmask(SIG_BLOCK, &halt_signals, nullptr);
444+ int const signal_watch{signalfd(-1, &halt_signals, SFD_CLOEXEC)};
445+
446+ pollfd signal_poll{
447+ signal_watch,
448+ POLLIN | POLLERR,
449+ 0
450+ };
451+
452+ while (poll(&signal_poll, 1, 0) <= 0)
453+ {
454+ bounce_position(baseColour, dbase, 128, 255);
455+
456+ fill_stream_with(buffer_stream, baseColour, 0, 0, 128);
457+
458+ mir_buffer_stream_swap_buffers_sync(buffer_stream);
459+ }
460+
461+ mir_buffer_stream_release_sync(buffer_stream);
462+ mir_render_surface_release(render_surface);
463+ mir_surface_release_sync(surface);
464+ close(signal_watch);
465+
466+ return 0;
467+}
468
469=== modified file 'src/client/CMakeLists.txt'
470--- src/client/CMakeLists.txt 2016-08-08 03:22:02 +0000
471+++ src/client/CMakeLists.txt 2016-08-12 21:54:21 +0000
472@@ -83,6 +83,8 @@
473 presentation_chain.cpp
474 mir_presentation_chain_api.cpp
475 mir_buffer_api.cpp
476+ mir_render_surface_api.cpp
477+ render_surface.cpp
478 display_configuration_api.cpp
479 protobuf_to_native_buffer.cpp
480 buffer_factory.cpp
481
482=== modified file 'src/client/buffer_stream.cpp'
483--- src/client/buffer_stream.cpp 2016-08-01 07:24:32 +0000
484+++ src/client/buffer_stream.cpp 2016-08-12 21:54:21 +0000
485@@ -419,6 +419,7 @@
486
487 mcl::BufferStream::BufferStream(
488 MirConnection* connection,
489+ MirRenderSurface* render_surface,
490 std::shared_ptr<MirWaitHandle> creation_wait_handle,
491 mclr::DisplayServer& server,
492 std::shared_ptr<mcl::ClientPlatform> const& client_platform,
493@@ -430,6 +431,7 @@
494 geom::Size ideal_size,
495 size_t nbuffers)
496 : connection_(connection),
497+ render_surface_(render_surface),
498 display_server(server),
499 client_platform(client_platform),
500 protobuf_bs{mcl::make_protobuf_object<mir::protobuf::BufferStream>(a_protobuf_bs)},
501@@ -518,6 +520,7 @@
502
503 mcl::BufferStream::BufferStream(
504 MirConnection* connection,
505+ MirRenderSurface* render_surface,
506 std::shared_ptr<MirWaitHandle> creation_wait_handle,
507 mclr::DisplayServer& server,
508 std::shared_ptr<mcl::ClientPlatform> const& client_platform,
509@@ -527,6 +530,7 @@
510 std::shared_ptr<mcl::PerfReport> const& perf_report,
511 size_t nbuffers)
512 : connection_(connection),
513+ render_surface_(render_surface),
514 display_server(server),
515 client_platform(client_platform),
516 protobuf_bs{mcl::make_protobuf_object<mir::protobuf::BufferStream>()},
517@@ -782,3 +786,8 @@
518 {
519 return connection_;
520 }
521+
522+MirRenderSurface* mcl::BufferStream::render_surface() const
523+{
524+ return render_surface_;
525+}
526
527=== modified file 'src/client/buffer_stream.h'
528--- src/client/buffer_stream.h 2016-06-02 05:33:50 +0000
529+++ src/client/buffer_stream.h 2016-08-12 21:54:21 +0000
530@@ -73,6 +73,7 @@
531 public:
532 BufferStream(
533 MirConnection* connection,
534+ MirRenderSurface* render_surface,
535 std::shared_ptr<MirWaitHandle> creation_wait_handle,
536 mir::client::rpc::DisplayServer& server,
537 std::shared_ptr<ClientPlatform> const& native_window_factory,
538@@ -85,6 +86,7 @@
539 // For surfaceless buffer streams
540 BufferStream(
541 MirConnection* connection,
542+ MirRenderSurface* render_surface,
543 std::shared_ptr<MirWaitHandle> creation_wait_handle,
544 mir::client::rpc::DisplayServer& server,
545 std::shared_ptr<ClientPlatform> const& native_window_factory,
546@@ -127,6 +129,7 @@
547 MirWaitHandle* set_scale(float scale) override;
548 char const* get_error_message() const override;
549 MirConnection* connection() const override;
550+ MirRenderSurface* render_surface() const override;
551
552 protected:
553 BufferStream(BufferStream const&) = delete;
554@@ -144,6 +147,7 @@
555 mutable std::mutex mutex; // Protects all members of *this
556
557 MirConnection* connection_;
558+ MirRenderSurface* render_surface_;
559 mir::client::rpc::DisplayServer& display_server;
560 std::shared_ptr<ClientPlatform> const client_platform;
561 std::unique_ptr<mir::protobuf::BufferStream> protobuf_bs;
562
563=== modified file 'src/client/client_buffer_stream.h'
564--- src/client/client_buffer_stream.h 2016-06-02 05:33:50 +0000
565+++ src/client/client_buffer_stream.h 2016-08-12 21:54:21 +0000
566@@ -23,6 +23,7 @@
567 #include "mir/geometry/size.h"
568
569 #include "mir_toolkit/client_types.h"
570+#include "mir_toolkit/client_types_nbs.h"
571 #include "mir_toolkit/mir_native_buffer.h"
572 #include "mir_wait_handle.h"
573
574@@ -91,6 +92,7 @@
575 virtual MirWaitHandle* set_scale(float) = 0;
576 virtual char const* get_error_message() const = 0;
577 virtual MirConnection* connection() const = 0;
578+ virtual MirRenderSurface* render_surface() const = 0;
579
580 virtual void buffer_available(mir::protobuf::Buffer const& buffer) = 0;
581 virtual void buffer_unavailable() = 0;
582
583=== modified file 'src/client/connection_surface_map.h'
584--- src/client/connection_surface_map.h 2016-06-06 11:51:31 +0000
585+++ src/client/connection_surface_map.h 2016-08-12 21:54:21 +0000
586@@ -23,14 +23,15 @@
587
588 #include <shared_mutex>
589 #include <unordered_map>
590+#include <set>
591
592 class MirPresentationChain;
593+class MirRenderSurface;
594 namespace mir
595 {
596 namespace client
597 {
598 class MirBuffer;
599-class PresentationChain;
600 class ConnectionSurfaceMap : public SurfaceMap
601 {
602 public:
603@@ -50,6 +51,9 @@
604 void erase(int buffer_id) override;
605 std::shared_ptr<MirBuffer> buffer(int buffer_id) const override;
606
607+ void insert(void* render_surface_key, std::shared_ptr<MirRenderSurface> const& render_surface);
608+ void erase(void* render_surface_key);
609+
610 private:
611 std::shared_timed_mutex mutable guard;
612 std::unordered_map<frontend::SurfaceId, std::shared_ptr<MirSurface>> surfaces;
613@@ -58,6 +62,7 @@
614 std::unordered_map<frontend::BufferStreamId, std::shared_ptr<MirPresentationChain>> chains;
615 std::shared_timed_mutex mutable buffer_guard;
616 std::unordered_map<int, std::shared_ptr<MirBuffer>> buffers;
617+ std::unordered_map<void*, std::shared_ptr<MirRenderSurface>> render_surfaces;
618 };
619
620 }
621
622=== modified file 'src/client/error_stream.cpp'
623--- src/client/error_stream.cpp 2016-01-18 15:24:00 +0000
624+++ src/client/error_stream.cpp 2016-08-12 21:54:21 +0000
625@@ -17,6 +17,7 @@
626 */
627
628 #include "error_stream.h"
629+#include "render_surface.h"
630
631 namespace mcl = mir::client;
632
633@@ -30,6 +31,16 @@
634 {
635 }
636
637+mcl::ErrorStream::ErrorStream(
638+ std::string const& error_msg, RenderSurface* render_surface,
639+ mir::frontend::BufferStreamId id, std::shared_ptr<MirWaitHandle> const& wh) :
640+ error(error_msg),
641+ connection_(render_surface->connection()),
642+ id(id),
643+ wh(wh)
644+{
645+}
646+
647 char const* mcl::ErrorStream::get_error_message() const
648 {
649 return error.c_str();
650@@ -45,6 +56,11 @@
651 return connection_;
652 }
653
654+MirRenderSurface* mcl::ErrorStream::render_surface() const
655+{
656+ return nullptr;
657+}
658+
659 mir::frontend::BufferStreamId mcl::ErrorStream::rpc_id() const
660 {
661 return id;
662
663=== modified file 'src/client/error_stream.h'
664--- src/client/error_stream.h 2016-01-18 15:24:00 +0000
665+++ src/client/error_stream.h 2016-08-12 21:54:21 +0000
666@@ -24,6 +24,9 @@
667 {
668 namespace client
669 {
670+
671+class RenderSurface;
672+
673 class ErrorStream : public ClientBufferStream
674 {
675 public:
676@@ -31,6 +34,10 @@
677 std::string const& error_msg, MirConnection* conn,
678 frontend::BufferStreamId id, std::shared_ptr<MirWaitHandle> const& wh);
679
680+ ErrorStream(
681+ std::string const& error_msg, RenderSurface* render_surface,
682+ frontend::BufferStreamId id, std::shared_ptr<MirWaitHandle> const& wh);
683+
684 MirWaitHandle* get_create_wait_handle();
685 MirSurfaceParameters get_parameters() const;
686 std::shared_ptr<ClientBuffer> get_current_buffer();
687@@ -51,6 +58,7 @@
688 MirWaitHandle* set_scale(float);
689 char const* get_error_message() const;
690 MirConnection* connection() const;
691+ MirRenderSurface* render_surface() const;
692 private:
693 std::string const error;
694 MirConnection* const connection_;
695
696=== modified file 'src/client/mir_buffer_stream_api.cpp'
697--- src/client/mir_buffer_stream_api.cpp 2016-05-03 06:55:25 +0000
698+++ src/client/mir_buffer_stream_api.cpp 2016-08-12 21:54:21 +0000
699@@ -22,6 +22,7 @@
700 #include "mir_surface.h"
701 #include "mir_connection.h"
702 #include "buffer_stream.h"
703+#include "mir_render_surface.h"
704
705 #include "mir_toolkit/mir_buffer.h"
706 #include "mir/client_buffer.h"
707@@ -88,7 +89,11 @@
708 {
709 auto bs = reinterpret_cast<mcl::ClientBufferStream*>(buffer_stream);
710 auto connection = bs->connection();
711- return connection->release_buffer_stream(bs, callback, context);
712+ auto rs = reinterpret_cast<MirRenderSurface*>(bs->render_surface());
713+ if (rs)
714+ return rs->release_buffer_stream(bs, callback, context);
715+ else
716+ return connection->release_buffer_stream(bs, callback, context);
717 }
718
719 void mir_buffer_stream_release_sync(MirBufferStream *buffer_stream)
720
721=== modified file 'src/client/mir_connection.cpp'
722--- src/client/mir_connection.cpp 2016-06-28 12:18:18 +0000
723+++ src/client/mir_connection.cpp 2016-08-12 21:54:21 +0000
724@@ -37,6 +37,7 @@
725 #include "screencast_stream.h"
726 #include "perf_report.h"
727 #include "presentation_chain.h"
728+#include "render_surface.h"
729 #include "error_chain.h"
730 #include "logging/perf_report.h"
731 #include "lttng/perf_report.h"
732@@ -383,7 +384,7 @@
733 try
734 {
735 default_stream = std::make_shared<mcl::BufferStream>(
736- this, request->wh, server, platform, surface_map, buffer_factory,
737+ this, nullptr, request->wh, server, platform, surface_map, buffer_factory,
738 surface_proto->buffer_stream(), make_perf_report(logger), name,
739 mir::geometry::Size{surface_proto->width(), surface_proto->height()}, nbuffers);
740 surface_map->insert(default_stream->rpc_id(), default_stream);
741@@ -404,6 +405,8 @@
742 std::shared_ptr<MirSurface> surf {nullptr};
743 if (surface_proto->has_error() || !surface_proto->has_id())
744 {
745+ printf("ERROR: creating surface\n");
746+
747 std::string reason;
748 if (surface_proto->has_error())
749 reason += surface_proto->error();
750@@ -417,9 +420,18 @@
751 }
752 else
753 {
754+ printf("created surface\n");
755 surf = std::make_shared<MirSurface>(
756 this, server, &debug, default_stream, input_platform, spec, *surface_proto, request->wh);
757 surface_map->insert(mf::SurfaceId{surface_proto->id().value()}, surf);
758+ printf("created surface, setting into render surfaces\n");
759+ if (spec.render_surfaces.is_set())
760+ {
761+ for (auto& rs_it : spec.render_surfaces.value())
762+ {
763+ rs_it->set_container(reinterpret_cast<MirSurface*>(surf.get()));
764+ }
765+ }
766 }
767
768 callback(surf.get(), context);
769@@ -822,7 +834,7 @@
770 try
771 {
772 auto stream = std::make_shared<mcl::BufferStream>(
773- this, request->wh, server, platform, surface_map, buffer_factory,
774+ this, nullptr, request->wh, server, platform, surface_map, buffer_factory,
775 *protobuf_bs, make_perf_report(logger), std::string{},
776 mir::geometry::Size{request->parameters.width(), request->parameters.height()}, nbuffers);
777 surface_map->insert(mf::BufferStreamId(protobuf_bs->id().value()), stream);
778@@ -1252,3 +1264,18 @@
779 released_buffer->set_buffer_id(buffer->rpc_id());
780 server.release_buffers(&request, ignored.get(), gp::NewCallback(ignore));
781 }
782+
783+MirRenderSurface* MirConnection::create_render_surface()
784+{
785+ std::shared_ptr<MirRenderSurface> rs {nullptr};
786+
787+ rs = std::make_shared<mcl::RenderSurface>(
788+ this, server, surface_map, nbuffers, platform, buffer_factory, logger);
789+ surface_map->insert(static_cast<void*>(rs.get()), rs);
790+ return rs.get();
791+}
792+
793+void MirConnection::release_render_surface(MirRenderSurface* render_surface)
794+{
795+ surface_map->erase(static_cast<void*>(render_surface));
796+}
797
798=== modified file 'src/client/mir_connection.h'
799--- src/client/mir_connection.h 2016-06-28 12:18:18 +0000
800+++ src/client/mir_connection.h 2016-08-12 21:54:21 +0000
801@@ -200,6 +200,8 @@
802 mir_buffer_callback callback, void* context);
803 void release_buffer(mir::client::MirBuffer* buffer);
804
805+ MirRenderSurface* create_render_surface();
806+ void release_render_surface(MirRenderSurface* render_surface);
807 private:
808 //google cant have callbacks with more than 2 args
809 struct SurfaceCreationRequest
810
811=== added file 'src/client/mir_render_surface.h'
812--- src/client/mir_render_surface.h 1970-01-01 00:00:00 +0000
813+++ src/client/mir_render_surface.h 2016-08-12 21:54:21 +0000
814@@ -0,0 +1,58 @@
815+/*
816+ * Copyright © 2016 Canonical Ltd.
817+ *
818+ * This program is free software: you can redistribute it and/or modify
819+ * it under the terms of the GNU Lesser General Public License version 3 as
820+ * published by the Free Software Foundation.
821+ *
822+ * This program is distributed in the hope that it will be useful,
823+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
824+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
825+ * GNU Lesser General Public License for more details.
826+ *
827+ * You should have received a copy of the GNU Lesser General Public License
828+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
829+ *
830+ * Authored by:
831+ * Cemil Azizoglu <cemil.azizoglu@canonical.com>
832+ */
833+
834+#ifndef MIR_CLIENT_MIR_RENDER_SURFACE_H
835+#define MIR_CLIENT_MIR_RENDER_SURFACE_H
836+
837+#include "mir_toolkit/mir_render_surface.h"
838+
839+namespace mir
840+{
841+namespace client
842+{
843+class ClientBufferStream;
844+}
845+}
846+
847+class MirRenderSurface
848+{
849+public:
850+ virtual ~MirRenderSurface() = default;
851+ virtual MirConnection* connection() const = 0;
852+ virtual MirWaitHandle* create_client_buffer_stream(
853+ int width, int height,
854+ MirPixelFormat format,
855+ MirBufferUsage buffer_usage,
856+ mir_buffer_stream_callback callback,
857+ void* context) = 0;
858+ virtual MirWaitHandle* release_buffer_stream(
859+ mir::client::ClientBufferStream* stream,
860+ mir_buffer_stream_callback callback,
861+ void* context) = 0;
862+ virtual int stream_id() = 0;
863+ virtual MirSurface* container() = 0;
864+ virtual MirEGLNativeWindowType egl_native_window() = 0;
865+
866+protected:
867+ MirRenderSurface(MirRenderSurface const&) = delete;
868+ MirRenderSurface& operator=(MirRenderSurface const&) = delete;
869+ MirRenderSurface() = default;
870+};
871+
872+#endif /* MIR_CLIENT_MIR_RENDER_SURFACE_H */
873
874=== added file 'src/client/mir_render_surface_api.cpp'
875--- src/client/mir_render_surface_api.cpp 1970-01-01 00:00:00 +0000
876+++ src/client/mir_render_surface_api.cpp 2016-08-12 21:54:21 +0000
877@@ -0,0 +1,140 @@
878+/*
879+ * Copyright © 2016 Canonical Ltd.
880+ *
881+ * This program is free software: you can redistribute it and/or modify it
882+ * under the terms of the GNU Lesser General Public License version 3,
883+ * as published by the Free Software Foundation.
884+ *
885+ * This program is distributed in the hope that it will be useful,
886+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
887+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
888+ * GNU Lesser General Public License for more details.
889+ *
890+ * You should have received a copy of the GNU Lesser General Public License
891+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
892+ *
893+ * Authored by: Cemil Azizoglu <cemil.azizoglu@canonical.com>
894+ */
895+
896+#include "mir_connection.h"
897+#include "render_surface.h"
898+#include "mir/uncaught.h"
899+#include "mir/require.h"
900+
901+namespace mcl = mir::client;
902+
903+namespace
904+{
905+// assign_result is compatible with all 2-parameter callbacks
906+void assign_result(void* result, void** context)
907+{
908+ if (context)
909+ *context = result;
910+}
911+}
912+
913+MirRenderSurface* mir_connection_create_render_surface(
914+ MirConnection* connection)
915+try
916+{
917+ mir::require(connection);
918+ return connection->create_render_surface();
919+}
920+catch (std::exception const& ex)
921+{
922+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
923+ return nullptr;
924+}
925+
926+bool mir_render_surface_is_valid(
927+ MirRenderSurface* render_surface)
928+try
929+{
930+ mir::require(render_surface);
931+ return true;
932+}
933+catch (std::exception const& ex)
934+{
935+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
936+ return false;
937+}
938+
939+void mir_render_surface_release(
940+ MirRenderSurface* render_surface)
941+try
942+{
943+ mir::require(render_surface);
944+ render_surface->connection()->release_render_surface(render_surface);
945+}
946+catch (std::exception const& ex)
947+{
948+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
949+}
950+
951+MirBufferStream* mir_render_surface_create_buffer_stream_sync(
952+ MirRenderSurface* render_surface,
953+ int width, int height,
954+ MirPixelFormat format,
955+ MirBufferUsage buffer_usage)
956+try
957+{
958+ mir::require(render_surface);
959+ MirBufferStream* stream = nullptr;
960+ auto rs = reinterpret_cast<mcl::RenderSurface*>(render_surface);
961+
962+ auto wh = rs->create_client_buffer_stream(
963+ width,
964+ height,
965+ format,
966+ buffer_usage,
967+ reinterpret_cast<mir_buffer_stream_callback>(assign_result),
968+ &stream);
969+ wh->wait_for_all();
970+ return stream;
971+}
972+catch (std::exception const& ex)
973+{
974+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
975+ return nullptr;
976+}
977+
978+MirConnection* mir_render_surface_connection(
979+ MirRenderSurface* render_surface)
980+try
981+{
982+ mir::require(render_surface);
983+ return render_surface->connection();
984+}
985+catch (std::exception const& ex)
986+{
987+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
988+ return nullptr;
989+}
990+
991+MirSurface* mir_render_surface_container(
992+ MirRenderSurface* render_surface)
993+try
994+{
995+ mir::require(render_surface);
996+
997+ return render_surface->container();
998+}
999+catch (std::exception const& ex)
1000+{
1001+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
1002+ return nullptr;
1003+}
1004+
1005+MirEGLNativeWindowType mir_render_surface_egl_native_window(
1006+ MirRenderSurface* render_surface)
1007+try
1008+{
1009+ mir::require(render_surface);
1010+
1011+ return render_surface->egl_native_window();
1012+}
1013+catch (std::exception const& ex)
1014+{
1015+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
1016+ return nullptr;
1017+}
1018
1019=== modified file 'src/client/mir_surface.cpp'
1020--- src/client/mir_surface.cpp 2016-08-12 12:57:50 +0000
1021+++ src/client/mir_surface.cpp 2016-08-12 21:54:21 +0000
1022@@ -526,6 +526,7 @@
1023 MirWaitHandle* MirSurface::modify(MirSurfaceSpec const& spec)
1024 {
1025 mp::SurfaceModifications mods;
1026+ printf("modify\n");
1027
1028 {
1029 std::unique_lock<decltype(mutex)> lock(mutex);
1030@@ -629,6 +630,7 @@
1031 new_shape->set_height(rect.height);
1032 }
1033 }
1034+ printf("modify2\n");
1035
1036 modify_wait_handle.expect_result();
1037 server->modify_surface(&mods, modify_result.get(),
1038
1039=== modified file 'src/client/mir_surface.h'
1040--- src/client/mir_surface.h 2016-06-09 00:38:26 +0000
1041+++ src/client/mir_surface.h 2016-08-12 21:54:21 +0000
1042@@ -71,6 +71,7 @@
1043 class ClientBuffer;
1044 class ClientBufferStream;
1045 class ClientBufferStreamFactory;
1046+class RenderSurface;
1047
1048 struct MemoryRegion;
1049 }
1050@@ -131,6 +132,7 @@
1051 };
1052 mir::optional_value<EventHandler> event_handler;
1053 mir::optional_value<MirShellChrome> shell_chrome;
1054+ mir::optional_value<std::vector<mir::client::RenderSurface*>> render_surfaces;
1055 };
1056
1057 struct MirPersistentId
1058@@ -252,4 +254,4 @@
1059
1060 };
1061
1062-#endif /* MIR_CLIENT_PRIVATE_MIR_WAIT_HANDLE_H_ */
1063+#endif /* MIR_CLIENT_MIR_SURFACE_H_ */
1064
1065=== modified file 'src/client/mir_surface_api.cpp'
1066--- src/client/mir_surface_api.cpp 2016-07-18 10:11:34 +0000
1067+++ src/client/mir_surface_api.cpp 2016-08-12 21:54:21 +0000
1068@@ -20,12 +20,12 @@
1069
1070 #include "mir_toolkit/mir_surface.h"
1071 #include "mir_toolkit/mir_wait.h"
1072-#include "mir_toolkit/mir_presentation_chain.h"
1073 #include "mir/require.h"
1074
1075 #include "mir_connection.h"
1076 #include "mir_surface.h"
1077 #include "presentation_chain.h"
1078+#include "render_surface.h"
1079 #include "error_connections.h"
1080 #include "mir/uncaught.h"
1081
1082@@ -558,6 +558,7 @@
1083 void mir_surface_apply_spec(MirSurface* surface, MirSurfaceSpec* spec)
1084 try
1085 {
1086+ printf("setting into render surfaces\n");
1087 mir::require(mir_surface_is_valid(surface));
1088 mir::require(spec);
1089
1090@@ -632,6 +633,44 @@
1091 MIR_LOG_UNCAUGHT_EXCEPTION(ex);
1092 }
1093
1094+void mir_surface_spec_add_render_surface(
1095+ MirSurfaceSpec* spec,
1096+ int /*scaled_width*/, int /*scaled_height*/,
1097+ int displacement_x, int displacement_y,
1098+ MirRenderSurface* render_surface)
1099+try
1100+{
1101+ mir::require(spec && render_surface);
1102+ auto rs = reinterpret_cast<mcl::RenderSurface*>(render_surface);
1103+ auto id = rs->stream_id();
1104+
1105+ if (id >= 0)
1106+ {
1107+ printf("stream_id = %d\n", id);
1108+ ContentInfo info{{displacement_x, displacement_y}, id, {}};
1109+
1110+ if (spec->streams.is_set())
1111+ spec->streams.value().push_back(info);
1112+ else
1113+ spec->streams = std::vector<ContentInfo>{info};
1114+ }
1115+
1116+ if (spec->render_surfaces.is_set())
1117+ {
1118+ spec->render_surfaces.value().push_back(rs);
1119+ printf("render_surface is set\n");
1120+ }
1121+ else
1122+ {
1123+ spec->render_surfaces = std::vector<mcl::RenderSurface*>{rs};
1124+ printf("render_surface is NOT set\n");
1125+ }
1126+}
1127+catch (std::exception const& ex)
1128+{
1129+ MIR_LOG_UNCAUGHT_EXCEPTION(ex);
1130+}
1131+
1132 void mir_surface_spec_set_input_shape(MirSurfaceSpec *spec, MirRectangle const* rectangles,
1133 size_t n_rects)
1134 try
1135
1136=== added file 'src/client/render_surface.cpp'
1137--- src/client/render_surface.cpp 1970-01-01 00:00:00 +0000
1138+++ src/client/render_surface.cpp 2016-08-12 21:54:21 +0000
1139@@ -0,0 +1,278 @@
1140+/*
1141+ * Copyright © 2016 Canonical Ltd.
1142+ *
1143+ * This program is free software: you can redistribute it and/or modify it
1144+ * under the terms of the GNU Lesser General Public License version 3,
1145+ * as published by the Free Software Foundation.
1146+ *
1147+ * This program is distributed in the hope that it will be useful,
1148+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1149+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1150+ * GNU Lesser General Public License for more details.
1151+ *
1152+ * You should have received a copy of the GNU Lesser General Public License
1153+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1154+ *
1155+ * Authored by:
1156+ * Cemil Azizoglu <cemil.azizoglu@canonical.com>
1157+ */
1158+
1159+#include "render_surface.h"
1160+#include "mir_wait_handle.h"
1161+#include "rpc/mir_display_server.h"
1162+#include "connection_surface_map.h"
1163+#include "buffer_stream.h"
1164+#include "error_stream.h"
1165+#include "perf_report.h"
1166+#include "logging/perf_report.h"
1167+#include "lttng/perf_report.h"
1168+#include "make_protobuf_object.h"
1169+#include "mir_toolkit/mir_surface.h"
1170+
1171+#include <algorithm>
1172+#include <unistd.h>
1173+#include <boost/exception/diagnostic_information.hpp>
1174+
1175+namespace mcl = mir::client;
1176+namespace mclr = mcl::rpc;
1177+namespace mp = mir::protobuf;
1178+namespace gp = google::protobuf;
1179+namespace mf = mir::frontend;
1180+namespace ml = mir::logging;
1181+
1182+namespace
1183+{
1184+void assign_result(void* result, void** context)
1185+{
1186+ if (context)
1187+ *context = result;
1188+}
1189+
1190+std::shared_ptr<mcl::PerfReport>
1191+make_perf_report(std::shared_ptr<ml::Logger> const& logger)
1192+{
1193+ // TODO: It seems strange that this directly uses getenv
1194+ const char* report_target = getenv("MIR_CLIENT_PERF_REPORT");
1195+ if (report_target && !strcmp(report_target, "log"))
1196+ {
1197+ return std::make_shared<mcl::logging::PerfReport>(logger);
1198+ }
1199+ else if (report_target && !strcmp(report_target, "lttng"))
1200+ {
1201+ return std::make_shared<mcl::lttng::PerfReport>();
1202+ }
1203+ else
1204+ {
1205+ return std::make_shared<mcl::NullPerfReport>();
1206+ }
1207+}
1208+}
1209+
1210+mcl::RenderSurface::RenderSurface(
1211+ MirConnection* const connection,
1212+ mclr::DisplayServer& display_server,
1213+ std::shared_ptr<ConnectionSurfaceMap> connection_surface_map,
1214+ int num_buffers,
1215+ std::shared_ptr<ClientPlatform> client_platform,
1216+ std::shared_ptr<AsyncBufferFactory> async_buffer_factory,
1217+ std::shared_ptr<ml::Logger> mir_logger) :
1218+ connection_(connection),
1219+ server(display_server),
1220+ surface_map(connection_surface_map),
1221+ nbuffers(num_buffers),
1222+ platform(client_platform),
1223+ buffer_factory(async_buffer_factory),
1224+ logger(mir_logger),
1225+ void_response(mcl::make_protobuf_object<mp::Void>()),
1226+ container_(nullptr)
1227+{
1228+}
1229+
1230+MirConnection* mcl::RenderSurface::connection() const
1231+{
1232+ return connection_;
1233+}
1234+
1235+MirWaitHandle* mcl::RenderSurface::create_client_buffer_stream(
1236+ int width, int height,
1237+ MirPixelFormat format,
1238+ MirBufferUsage buffer_usage,
1239+ mir_buffer_stream_callback callback,
1240+ void* context)
1241+{
1242+ mp::BufferStreamParameters params;
1243+ params.set_width(width);
1244+ params.set_height(height);
1245+ params.set_pixel_format(format);
1246+ params.set_buffer_usage(buffer_usage);
1247+
1248+ auto request = std::make_shared<StreamCreationRequest>(callback, context, params);
1249+ request->wh->expect_result();
1250+
1251+ {
1252+ std::lock_guard<decltype(mutex)> lock(mutex);
1253+ stream_requests.push_back(request);
1254+ }
1255+
1256+ try
1257+ {
1258+ server.create_buffer_stream(&params, request->response.get(),
1259+ gp::NewCallback(this, &mcl::RenderSurface::stream_created, request.get()));
1260+ } catch (std::exception& e)
1261+ {
1262+ //if this throws, our socket code will run the closure, which will make an error object.
1263+ //its nicer to return a stream with an error message, so just ignore the exception.
1264+ }
1265+
1266+ return request->wh.get();
1267+}
1268+
1269+mf::SurfaceId mcl::RenderSurface::next_error_id(std::unique_lock<std::mutex> const&)
1270+{
1271+ return mf::SurfaceId{stream_error_id--};
1272+}
1273+
1274+void mcl::RenderSurface::stream_error(std::string const& error_msg, std::shared_ptr<StreamCreationRequest> const& request)
1275+{
1276+ std::unique_lock<decltype(mutex)> lock(mutex);
1277+ mf::BufferStreamId id(next_error_id(lock).as_value());
1278+ auto stream = std::make_shared<mcl::ErrorStream>(error_msg, this, id, request->wh);
1279+ surface_map->insert(id, stream);
1280+
1281+ if (request->callback)
1282+ {
1283+ request->callback(reinterpret_cast<MirBufferStream*>(dynamic_cast<mcl::ClientBufferStream*>(stream.get())), request->context);
1284+ }
1285+ request->wh->result_received();
1286+}
1287+
1288+void mcl::RenderSurface::stream_created(StreamCreationRequest* request_raw)
1289+{
1290+ std::shared_ptr<StreamCreationRequest> request {nullptr};
1291+ {
1292+ std::lock_guard<decltype(mutex)> lock(mutex);
1293+ auto stream_it = std::find_if(stream_requests.begin(), stream_requests.end(),
1294+ [&request_raw] (std::shared_ptr<StreamCreationRequest> const& req)
1295+ { return req.get() == request_raw; });
1296+ if (stream_it == stream_requests.end())
1297+ return;
1298+ request = *stream_it;
1299+ stream_requests.erase(stream_it);
1300+ }
1301+ auto& protobuf_bs = request->response;
1302+
1303+ if (!protobuf_bs->has_id())
1304+ {
1305+ if (!protobuf_bs->has_error())
1306+ protobuf_bs->set_error("no ID in response (disconnected?)");
1307+ }
1308+
1309+ if (protobuf_bs->has_error())
1310+ {
1311+ for (int i = 0; i < protobuf_bs->buffer().fd_size(); i++)
1312+ ::close(protobuf_bs->buffer().fd(i));
1313+ stream_error(
1314+ std::string{"Error processing buffer stream response: "} + protobuf_bs->error(),
1315+ request);
1316+ return;
1317+ }
1318+
1319+ try
1320+ {
1321+ auto stream = std::make_shared<mcl::BufferStream>(
1322+ connection(), this, request->wh, server, platform, surface_map, buffer_factory,
1323+ *protobuf_bs, make_perf_report(logger), std::string{},
1324+ mir::geometry::Size{request->parameters.width(), request->parameters.height()}, nbuffers);
1325+ id = protobuf_bs->id().value();
1326+ surface_map->insert(mf::BufferStreamId(id), stream);
1327+
1328+ if (request->callback)
1329+ request->callback(reinterpret_cast<MirBufferStream*>(dynamic_cast<mcl::ClientBufferStream*>(stream.get())), request->context);
1330+ request->wh->result_received();
1331+ }
1332+ catch (std::exception const& error)
1333+ {
1334+ for (int i = 0; i < protobuf_bs->buffer().fd_size(); i++)
1335+ ::close(protobuf_bs->buffer().fd(i));
1336+
1337+ stream_error(
1338+ std::string{"Error processing buffer stream creating response:"} + boost::diagnostic_information(error),
1339+ request);
1340+ }
1341+}
1342+
1343+int mcl::RenderSurface::stream_id()
1344+{
1345+ return id;
1346+}
1347+
1348+struct mcl::RenderSurface::StreamRelease
1349+{
1350+ ClientBufferStream* stream;
1351+ MirWaitHandle* handle;
1352+ mir_buffer_stream_callback callback;
1353+ void* context;
1354+ int rpc_id;
1355+};
1356+
1357+MirWaitHandle* mcl::RenderSurface::release_buffer_stream(
1358+ ClientBufferStream* stream,
1359+ mir_buffer_stream_callback callback,
1360+ void* context)
1361+{
1362+ auto new_wait_handle = new MirWaitHandle;
1363+
1364+ StreamRelease stream_release{stream, new_wait_handle, callback, context, stream->rpc_id().as_value() };
1365+
1366+ mp::BufferStreamId buffer_stream_id;
1367+ buffer_stream_id.set_value(stream->rpc_id().as_value());
1368+
1369+ {
1370+ std::lock_guard<decltype(release_wait_handle_guard)> rel_lock(release_wait_handle_guard);
1371+ release_wait_handles.push_back(new_wait_handle);
1372+ }
1373+
1374+ new_wait_handle->expect_result();
1375+ server.release_buffer_stream(
1376+ &buffer_stream_id, void_response.get(),
1377+ google::protobuf::NewCallback(this, &RenderSurface::released, stream_release));
1378+ return new_wait_handle;
1379+}
1380+
1381+void mcl::RenderSurface::released(StreamRelease data)
1382+{
1383+ if (data.callback)
1384+ data.callback(reinterpret_cast<MirBufferStream*>(data.stream), data.context);
1385+ if (data.handle)
1386+ data.handle->result_received();
1387+ surface_map->erase(mf::BufferStreamId(data.rpc_id));
1388+}
1389+
1390+void mcl::RenderSurface::set_container(MirSurface* const surface)
1391+{
1392+ container_ = surface;
1393+}
1394+
1395+MirSurface* mcl::RenderSurface::container()
1396+{
1397+ return container_;
1398+}
1399+
1400+MirEGLNativeWindowType mcl::RenderSurface::egl_native_window()
1401+{
1402+ MirBufferStream* stream = nullptr;
1403+ auto wh = create_client_buffer_stream(
1404+ 100,
1405+ 100,
1406+ mir_pixel_format_argb_8888,
1407+ mir_buffer_usage_hardware,
1408+ reinterpret_cast<mir_buffer_stream_callback>(assign_result),
1409+ &stream);
1410+ wh->wait_for_all();
1411+ auto spec = mir_connection_create_spec_for_changes(connection_);
1412+ mir_surface_spec_add_render_surface(spec, 100, 100, 0, 0, this);
1413+ mir_surface_apply_spec(container_, spec);
1414+ mir_surface_spec_release(spec);
1415+ mcl::ClientBufferStream *bs = reinterpret_cast<mcl::ClientBufferStream*>(stream);
1416+ return reinterpret_cast<MirEGLNativeWindowType>(bs->egl_native_window());
1417+}
1418
1419=== added file 'src/client/render_surface.h'
1420--- src/client/render_surface.h 1970-01-01 00:00:00 +0000
1421+++ src/client/render_surface.h 2016-08-12 21:54:21 +0000
1422@@ -0,0 +1,128 @@
1423+/*
1424+ * Copyright © 2016 Canonical Ltd.
1425+ *
1426+ * This program is free software: you can redistribute it and/or modify
1427+ * it under the terms of the GNU Lesser General Public License version 3 as
1428+ * published by the Free Software Foundation.
1429+ *
1430+ * This program is distributed in the hope that it will be useful,
1431+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1432+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1433+ * GNU Lesser General Public License for more details.
1434+ *
1435+ * You should have received a copy of the GNU Lesser General Public License
1436+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1437+ *
1438+ * Authored by:
1439+ * Cemil Azizoglu <cemil.azizoglu@canonical.com>
1440+ */
1441+
1442+#ifndef MIR_CLIENT_RENDER_SURFACE_H
1443+#define MIR_CLIENT_RENDER_SURFACE_H
1444+
1445+#include "mir_render_surface.h"
1446+#include "mir_toolkit/mir_render_surface.h"
1447+#include "mir_toolkit/client_types.h"
1448+#include "mir_protobuf.pb.h"
1449+#include "mir/frontend/surface_id.h"
1450+#include <mutex>
1451+#include <memory>
1452+
1453+namespace mir
1454+{
1455+
1456+namespace protobuf
1457+{
1458+class BufferStream;
1459+}
1460+
1461+namespace logging
1462+{
1463+class Logger;
1464+}
1465+
1466+namespace client
1467+{
1468+
1469+class ConnectionSurfaceMap;
1470+class ClientPlatform;
1471+class AsyncBufferFactory;
1472+
1473+namespace rpc
1474+{
1475+class DisplayServer;
1476+}
1477+
1478+class RenderSurface : public MirRenderSurface
1479+{
1480+public:
1481+ RenderSurface(MirConnection* const connection,
1482+ rpc::DisplayServer& display_server,
1483+ std::shared_ptr<ConnectionSurfaceMap> connection_surface_map,
1484+ int num_buffers,
1485+ std::shared_ptr<ClientPlatform> client_platform,
1486+ std::shared_ptr<AsyncBufferFactory> async_buffer_factory,
1487+ std::shared_ptr<mir::logging::Logger> mir_logger);
1488+ MirConnection* connection() const override;
1489+ MirWaitHandle* create_client_buffer_stream(
1490+ int width, int height,
1491+ MirPixelFormat format,
1492+ MirBufferUsage buffer_usage,
1493+ mir_buffer_stream_callback callback,
1494+ void *context) override;
1495+ int stream_id() override;
1496+ MirWaitHandle* release_buffer_stream(
1497+ ClientBufferStream* stream,
1498+ mir_buffer_stream_callback callback,
1499+ void* context) override;
1500+ void set_container(MirSurface* const surface);
1501+ MirSurface* container() override;
1502+ MirEGLNativeWindowType egl_native_window() override;
1503+
1504+
1505+private:
1506+ MirConnection* const connection_;
1507+ rpc::DisplayServer& server;
1508+ std::shared_ptr<ConnectionSurfaceMap> surface_map;
1509+ int const nbuffers;
1510+ std::shared_ptr<ClientPlatform> platform;
1511+ std::shared_ptr<AsyncBufferFactory> buffer_factory;
1512+ std::shared_ptr<mir::logging::Logger> const logger;
1513+ std::unique_ptr<mir::protobuf::Void> void_response;
1514+ MirSurface* container_;
1515+
1516+ struct StreamCreationRequest
1517+ {
1518+ StreamCreationRequest(
1519+ mir_buffer_stream_callback cb, void* context, protobuf::BufferStreamParameters const& params) :
1520+ callback(cb),
1521+ context(context),
1522+ parameters(params),
1523+ response(std::make_shared<protobuf::BufferStream>()),
1524+ wh(std::make_shared<MirWaitHandle>())
1525+ {
1526+ }
1527+ mir_buffer_stream_callback callback;
1528+ void* context;
1529+ protobuf::BufferStreamParameters const parameters;
1530+ std::shared_ptr<protobuf::BufferStream> response;
1531+ std::shared_ptr<MirWaitHandle> const wh;
1532+ };
1533+
1534+ std::vector<std::shared_ptr<StreamCreationRequest>> stream_requests;
1535+ void stream_created(StreamCreationRequest* request_raw);
1536+ void stream_error(std::string const& error_msg, std::shared_ptr<StreamCreationRequest> const& request);
1537+ struct StreamRelease;
1538+ void released(StreamRelease);
1539+ std::mutex release_wait_handle_guard;
1540+ std::vector<MirWaitHandle*> release_wait_handles;
1541+
1542+ frontend::SurfaceId next_error_id(std::unique_lock<std::mutex> const&);
1543+ int stream_error_id{-1};
1544+ int id{-1};
1545+ std::mutex mutex;
1546+};
1547+
1548+}
1549+}
1550+#endif /* MIR_CLIENT_RENDER_SURFACE_H */
1551
1552=== modified file 'src/client/screencast_stream.cpp'
1553--- src/client/screencast_stream.cpp 2016-06-02 05:33:50 +0000
1554+++ src/client/screencast_stream.cpp 2016-08-12 21:54:21 +0000
1555@@ -234,6 +234,11 @@
1556 return connection_;
1557 }
1558
1559+MirRenderSurface* mcl::ScreencastStream::render_surface() const
1560+{
1561+ return nullptr;
1562+}
1563+
1564 void mcl::ScreencastStream::set_buffer_cache_size(unsigned int)
1565 {
1566 BOOST_THROW_EXCEPTION(std::logic_error("Attempt to set cache size on screencast is invalid"));
1567
1568=== modified file 'src/client/screencast_stream.h'
1569--- src/client/screencast_stream.h 2016-05-03 06:55:25 +0000
1570+++ src/client/screencast_stream.h 2016-08-12 21:54:21 +0000
1571@@ -99,6 +99,7 @@
1572 MirWaitHandle* set_scale(float scale) override;
1573 char const* get_error_message() const override;
1574 MirConnection* connection() const override;
1575+ MirRenderSurface* render_surface() const override;
1576
1577 private:
1578 void process_buffer(protobuf::Buffer const& buffer);
1579
1580=== modified file 'src/client/surface_map.cpp'
1581--- src/client/surface_map.cpp 2016-06-06 11:51:31 +0000
1582+++ src/client/surface_map.cpp 2016-08-12 21:54:21 +0000
1583@@ -129,3 +129,17 @@
1584 else
1585 BOOST_THROW_EXCEPTION(std::runtime_error("could not find buffer"));
1586 }
1587+
1588+void mcl::ConnectionSurfaceMap::insert(void* render_surface_key, std::shared_ptr<MirRenderSurface> const& render_surface)
1589+{
1590+ std::lock_guard<decltype(guard)> lk(guard);
1591+ render_surfaces[render_surface_key] = render_surface;
1592+}
1593+
1594+void mcl::ConnectionSurfaceMap::erase(void* render_surface_key)
1595+{
1596+ std::lock_guard<decltype(guard)> lk(guard);
1597+ auto rs_it = render_surfaces.find(render_surface_key);
1598+ if (rs_it != render_surfaces.end())
1599+ render_surfaces.erase(rs_it);
1600+}
1601
1602=== modified file 'src/client/symbols.map'
1603--- src/client/symbols.map 2016-08-09 06:44:52 +0000
1604+++ src/client/symbols.map 2016-08-12 21:54:21 +0000
1605@@ -383,6 +383,14 @@
1606 mir_buffer_get_buffer_usage;
1607 mir_buffer_is_valid;
1608 mir_buffer_get_error_message;
1609+ mir_connection_create_render_surface;
1610+ mir_render_surface_is_valid;
1611+ mir_render_surface_release;
1612+ mir_surface_spec_add_render_surface;
1613+ mir_render_surface_create_buffer_stream_sync;
1614+ mir_render_surface_connection;
1615+ mir_render_surface_container;
1616+ mir_render_surface_egl_native_window;
1617 local:
1618 *;
1619 } MIR_CLIENT_DETAIL_9v19;
1620
1621=== modified file 'src/include/client/mir_toolkit/client_types_nbs.h'
1622--- src/include/client/mir_toolkit/client_types_nbs.h 2016-06-02 05:33:50 +0000
1623+++ src/include/client/mir_toolkit/client_types_nbs.h 2016-08-12 21:54:21 +0000
1624@@ -32,6 +32,7 @@
1625 typedef struct MirPresentationChain MirPresentationChain;
1626 typedef struct MirBuffer MirBuffer;
1627 typedef void* MirNativeFence;
1628+typedef struct MirRenderSurface MirRenderSurface;
1629
1630 typedef void (*mir_buffer_callback)(MirBuffer*, void* context);
1631 typedef void (*mir_presentation_chain_callback)(MirPresentationChain*, void* context);
1632
1633=== added file 'src/include/client/mir_toolkit/mir_render_surface.h'
1634--- src/include/client/mir_toolkit/mir_render_surface.h 1970-01-01 00:00:00 +0000
1635+++ src/include/client/mir_toolkit/mir_render_surface.h 2016-08-12 21:54:21 +0000
1636@@ -0,0 +1,73 @@
1637+/*
1638+ * Copyright © 2016 Canonical Ltd.
1639+ *
1640+ * This program is free software: you can redistribute it and/or modify it
1641+ * under the terms of the GNU Lesser General Public License version 3,
1642+ * as published by the Free Software Foundation.
1643+ *
1644+ * This program is distributed in the hope that it will be useful,
1645+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1646+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1647+ * GNU Lesser General Public License for more details.
1648+ *
1649+ * You should have received a copy of the GNU Lesser General Public License
1650+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1651+ *
1652+ * Authored by:
1653+ * Cemil Azizoglu <cemil.azizoglu@canonical.com>
1654+ */
1655+
1656+#ifndef MIR_TOOLKIT_MIR_RENDER_SURFACE_H_
1657+#define MIR_TOOLKIT_MIR_RENDER_SURFACE_H_
1658+
1659+#include <mir_toolkit/client_types_nbs.h>
1660+
1661+#ifdef __cplusplus
1662+/**
1663+ * \addtogroup mir_toolkit
1664+ * @{
1665+ */
1666+extern "C" {
1667+#endif
1668+
1669+MirRenderSurface* mir_connection_create_render_surface(
1670+ MirConnection* connection);
1671+
1672+bool mir_render_surface_is_valid(
1673+ MirRenderSurface* render_surface);
1674+
1675+void mir_render_surface_release(
1676+ MirRenderSurface* render_surface);
1677+
1678+void mir_surface_spec_add_render_surface(
1679+ MirSurfaceSpec* spec,
1680+ int scaled_width, int scaled_height,
1681+ int displacement_x, int displacement_y,
1682+ MirRenderSurface* render_surface);
1683+
1684+MirBufferStream* mir_render_surface_create_buffer_stream_sync(
1685+ MirRenderSurface* render_surface,
1686+ int width, int height,
1687+ MirPixelFormat format,
1688+ MirBufferUsage buffer_usage);
1689+
1690+MirConnection* mir_render_surface_connection(
1691+ MirRenderSurface* render_surface);
1692+
1693+MirSurface* mir_render_surface_container(
1694+ MirRenderSurface* render_surface);
1695+
1696+MirEGLNativeWindowType mir_render_surface_egl_native_window(
1697+ MirRenderSurface* render_surface);
1698+
1699+#if 0
1700+MirPresentationChain* mir_render_surface_create_presentation_chain_sync(
1701+ MirRenderSurface*);
1702+#endif
1703+
1704+#ifdef __cplusplus
1705+}
1706+/**@}*/
1707+#endif
1708+
1709+#endif // MIR_TOOLKIT_MIR_RENDER_SURFACE_H_

Subscribers

People subscribed via source and target branches