Mir

Merge lp:~vanvugt/mir/timerless-multimonitor-frame-sync into lp:~mir-team/mir/trunk

Proposed by Daniel van Vugt
Status: Superseded
Proposed branch: lp:~vanvugt/mir/timerless-multimonitor-frame-sync
Merge into: lp:~mir-team/mir/trunk
Prerequisite: lp:~vanvugt/mir/bypass
Diff against target: 1180 lines (+176/-173)
33 files modified
include/server/mir/compositor/buffer_stream_surfaces.h (+2/-1)
include/server/mir/compositor/renderer.h (+1/-1)
include/server/mir/surfaces/buffer_stream.h (+2/-1)
include/test/mir_test_doubles/mock_buffer_bundle.h (+1/-1)
include/test/mir_test_doubles/mock_buffer_stream.h (+2/-1)
include/test/mir_test_doubles/mock_surface_renderer.h (+1/-1)
include/test/mir_test_doubles/stub_buffer_stream.h (+1/-1)
src/server/compositor/buffer_bundle.h (+2/-1)
src/server/compositor/buffer_stream_surfaces.cpp (+4/-2)
src/server/compositor/default_display_buffer_compositor.cpp (+28/-3)
src/server/compositor/default_display_buffer_compositor.h (+2/-0)
src/server/compositor/gl_renderer.cpp (+4/-2)
src/server/compositor/gl_renderer.h (+3/-1)
src/server/compositor/switching_bundle.cpp (+5/-7)
src/server/compositor/switching_bundle.h (+3/-6)
src/server/compositor/temporary_buffers.cpp (+2/-2)
src/server/compositor/temporary_buffers.h (+1/-1)
src/server/surfaces/surface.cpp (+1/-1)
tests/acceptance-tests/test_server_shutdown.cpp (+1/-1)
tests/integration-tests/compositor/test_buffer_stream.cpp (+15/-21)
tests/integration-tests/compositor/test_swapping_swappers.cpp (+4/-2)
tests/integration-tests/shell/test_session.cpp (+2/-2)
tests/integration-tests/test_surface_first_frame_sync.cpp (+1/-1)
tests/integration-tests/test_swapinterval.cpp (+1/-1)
tests/mir_test_framework/testing_server_options.cpp (+2/-2)
tests/unit-tests/compositor/test_buffer_stream.cpp (+4/-4)
tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp (+8/-8)
tests/unit-tests/compositor/test_gl_renderer.cpp (+1/-1)
tests/unit-tests/compositor/test_rendering_operator.cpp (+1/-1)
tests/unit-tests/compositor/test_switching_bundle.cpp (+65/-91)
tests/unit-tests/compositor/test_temporary_buffers.cpp (+3/-3)
tests/unit-tests/surfaces/test_surface.cpp (+1/-1)
tests/unit-tests/surfaces/test_surface_stack.cpp (+2/-1)
To merge this branch: bzr merge lp:~vanvugt/mir/timerless-multimonitor-frame-sync
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Review via email: mp+182085@code.launchpad.net

This proposal has been superseded by a proposal from 2013-08-29.

Commit message

Dramatically improved multi-monitor frame synchronization, using a global
frame count equivalent to the highest refresh rate of all monitors. This is
much more reliable than the old logic which was based on timers.

This fixes LP: #1210478

Description of the change

This version depends on the bypass branch in order to minimize conflicts. But I can remove that dependency if required.

Also, this branch conflicts with lp:~vanvugt/mir/remove-unused-buffer-methods.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Chris Halse Rogers (raof) wrote :

Mostly looks good to me, only nitpick:

160 + local_frame_count <= 0) // Wrap around, unlikely, but handle it...

I'm not a huge fan of testing unsigned values for <= 0. Maybe make it == 0?

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I prefer to keep "<= 0". It's extra protection against regressions if anyone changes it to signed in future.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I have what looks like a test setup to reproduce LP: #1216472 now, and it looks like it is not fixed by this :(

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

I like the approach, but some small concerns:

159 + if (global_frame_count.load() < local_frame_count ||
160 + local_frame_count <= 0) // Wrap around, unlikely, but handle it...
161 + {
162 + global_frame_count.store(local_frame_count);
163 + }
164 + else
165 + {
166 + local_frame_count = global_frame_count.load();
167 + }

As there is no synchronization between the first load and the store I don't think the logic is mathematically correct. Could we improve on this by using compare_exchange? (Not that I think there's much chance of a problem in practice.)

~~~~

134 +std::atomic_ulong mc::DefaultDisplayBufferCompositor::global_frame_count(0);

There's no reason for this to be "published" in a header: it could be a namespace scope variable (in anonymous namespace) rather than a static class member.

~~~~

I don't have a better name but "frameno" doesn't really indicate what the parameter is for.

review: Needs Information
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Alan, I was thinking the same. Just haven't got to it yet.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

Review: Needs Fixing

162 + if (global_frame_count < local_frame_count || local_frame_count <= 0)
163 + global_frame_count = local_frame_count;
164 + else
165 + local_frame_count = global_frame_count;
166 + }

Start with:

thread 1: local_frame_count = MAX_UNIT
thread 2: local_frame_count = MAX_UNIT-1

thread 1 runs through this code leaving:

global_frame_count == (t1)local_frame_count == 0

Then thread 2 runs through it leaving:

global_frame_count == (t2)local_frame_count == MAX_UNIT

When the result needed by the algorithm is:

global_frame_count == (t2)local_frame_count == 0

Things do sort themselves out and the error is mostly harmless (and only occurs occasionally) but it could be improved upon. Vis:

162 + if (global_frame_count < local_frame_count || local_frame_count <= 0)
          if (global_frame_count - local_frame_count > UNIT_MAX/2)

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

I'm still not entirely happy with the naming - frameno, global_frame_count and local_frame_count are not really what their names suggest. They are neither identifiers nor counts but actually sequence numbers.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/server/mir/compositor/buffer_stream_surfaces.h'
--- include/server/mir/compositor/buffer_stream_surfaces.h 2013-08-09 01:37:53 +0000
+++ include/server/mir/compositor/buffer_stream_surfaces.h 2013-08-29 09:10:29 +0000
@@ -41,7 +41,8 @@
4141
42 std::shared_ptr<graphics::Buffer> secure_client_buffer();42 std::shared_ptr<graphics::Buffer> secure_client_buffer();
4343
44 std::shared_ptr<graphics::Buffer> lock_compositor_buffer() override;44 std::shared_ptr<graphics::Buffer>
45 lock_compositor_buffer(unsigned long frameno) override;
45 std::shared_ptr<graphics::Buffer> lock_snapshot_buffer() override;46 std::shared_ptr<graphics::Buffer> lock_snapshot_buffer() override;
4647
47 geometry::PixelFormat get_stream_pixel_format();48 geometry::PixelFormat get_stream_pixel_format();
4849
=== modified file 'include/server/mir/compositor/renderer.h'
--- include/server/mir/compositor/renderer.h 2013-08-09 01:37:53 +0000
+++ include/server/mir/compositor/renderer.h 2013-08-29 09:10:29 +0000
@@ -37,7 +37,7 @@
37public:37public:
38 virtual ~Renderer() = default;38 virtual ~Renderer() = default;
3939
40 virtual void clear() = 0;40 virtual void clear(unsigned long frameno) = 0;
41 virtual void render(std::function<void(std::shared_ptr<void> const&)> save_resource,41 virtual void render(std::function<void(std::shared_ptr<void> const&)> save_resource,
42 CompositingCriteria const& info, surfaces::BufferStream& stream) = 0;42 CompositingCriteria const& info, surfaces::BufferStream& stream) = 0;
4343
4444
=== modified file 'include/server/mir/surfaces/buffer_stream.h'
--- include/server/mir/surfaces/buffer_stream.h 2013-08-09 01:37:53 +0000
+++ include/server/mir/surfaces/buffer_stream.h 2013-08-29 09:10:29 +0000
@@ -42,7 +42,8 @@
42 virtual ~BufferStream() {/* TODO: make nothrow */}42 virtual ~BufferStream() {/* TODO: make nothrow */}
4343
44 virtual std::shared_ptr<graphics::Buffer> secure_client_buffer() = 0;44 virtual std::shared_ptr<graphics::Buffer> secure_client_buffer() = 0;
45 virtual std::shared_ptr<graphics::Buffer> lock_compositor_buffer() = 0;45 virtual std::shared_ptr<graphics::Buffer>
46 lock_compositor_buffer(unsigned long frameno) = 0;
46 virtual std::shared_ptr<graphics::Buffer> lock_snapshot_buffer() = 0;47 virtual std::shared_ptr<graphics::Buffer> lock_snapshot_buffer() = 0;
47 virtual geometry::PixelFormat get_stream_pixel_format() = 0;48 virtual geometry::PixelFormat get_stream_pixel_format() = 0;
48 virtual geometry::Size stream_size() = 0;49 virtual geometry::Size stream_size() = 0;
4950
=== modified file 'include/test/mir_test_doubles/mock_buffer_bundle.h'
--- include/test/mir_test_doubles/mock_buffer_bundle.h 2013-08-09 01:37:53 +0000
+++ include/test/mir_test_doubles/mock_buffer_bundle.h 2013-08-29 09:10:29 +0000
@@ -39,7 +39,7 @@
3939
40 MOCK_METHOD0(client_acquire, std::shared_ptr<graphics::Buffer>());40 MOCK_METHOD0(client_acquire, std::shared_ptr<graphics::Buffer>());
41 MOCK_METHOD1(client_release, void(std::shared_ptr<graphics::Buffer> const&));41 MOCK_METHOD1(client_release, void(std::shared_ptr<graphics::Buffer> const&));
42 MOCK_METHOD0(compositor_acquire, std::shared_ptr<graphics::Buffer>());42 MOCK_METHOD1(compositor_acquire, std::shared_ptr<graphics::Buffer>(unsigned long));
43 MOCK_METHOD1(compositor_release, void(std::shared_ptr<graphics::Buffer> const&));43 MOCK_METHOD1(compositor_release, void(std::shared_ptr<graphics::Buffer> const&));
44 MOCK_METHOD0(snapshot_acquire, std::shared_ptr<graphics::Buffer>());44 MOCK_METHOD0(snapshot_acquire, std::shared_ptr<graphics::Buffer>());
45 MOCK_METHOD1(snapshot_release, void(std::shared_ptr<graphics::Buffer> const&));45 MOCK_METHOD1(snapshot_release, void(std::shared_ptr<graphics::Buffer> const&));
4646
=== modified file 'include/test/mir_test_doubles/mock_buffer_stream.h'
--- include/test/mir_test_doubles/mock_buffer_stream.h 2013-08-09 01:37:53 +0000
+++ include/test/mir_test_doubles/mock_buffer_stream.h 2013-08-29 09:10:29 +0000
@@ -32,7 +32,8 @@
32struct MockBufferStream : public surfaces::BufferStream32struct MockBufferStream : public surfaces::BufferStream
33{33{
34 MOCK_METHOD0(secure_client_buffer, std::shared_ptr<graphics::Buffer>());34 MOCK_METHOD0(secure_client_buffer, std::shared_ptr<graphics::Buffer>());
35 MOCK_METHOD0(lock_compositor_buffer, std::shared_ptr<graphics::Buffer>());35 MOCK_METHOD1(lock_compositor_buffer,
36 std::shared_ptr<graphics::Buffer>(unsigned long));
36 MOCK_METHOD0(lock_snapshot_buffer, std::shared_ptr<graphics::Buffer>());37 MOCK_METHOD0(lock_snapshot_buffer, std::shared_ptr<graphics::Buffer>());
3738
38 MOCK_METHOD0(get_stream_pixel_format, geometry::PixelFormat());39 MOCK_METHOD0(get_stream_pixel_format, geometry::PixelFormat());
3940
=== modified file 'include/test/mir_test_doubles/mock_surface_renderer.h'
--- include/test/mir_test_doubles/mock_surface_renderer.h 2013-08-09 01:37:53 +0000
+++ include/test/mir_test_doubles/mock_surface_renderer.h 2013-08-29 09:10:29 +0000
@@ -33,7 +33,7 @@
33{33{
34 MOCK_METHOD3(render, void(34 MOCK_METHOD3(render, void(
35 std::function<void(std::shared_ptr<void> const&)>, compositor::CompositingCriteria const&, surfaces::BufferStream&));35 std::function<void(std::shared_ptr<void> const&)>, compositor::CompositingCriteria const&, surfaces::BufferStream&));
36 MOCK_METHOD0(clear, void());36 MOCK_METHOD1(clear, void(unsigned long));
3737
38 ~MockSurfaceRenderer() noexcept {}38 ~MockSurfaceRenderer() noexcept {}
39};39};
4040
=== modified file 'include/test/mir_test_doubles/stub_buffer_stream.h'
--- include/test/mir_test_doubles/stub_buffer_stream.h 2013-08-09 01:37:53 +0000
+++ include/test/mir_test_doubles/stub_buffer_stream.h 2013-08-29 09:10:29 +0000
@@ -42,7 +42,7 @@
42 return stub_client_buffer;42 return stub_client_buffer;
43 }43 }
4444
45 std::shared_ptr<graphics::Buffer> lock_compositor_buffer()45 std::shared_ptr<graphics::Buffer> lock_compositor_buffer(unsigned long)
46 {46 {
47 return stub_compositor_buffer;47 return stub_compositor_buffer;
48 }48 }
4949
=== modified file 'src/server/compositor/buffer_bundle.h'
--- src/server/compositor/buffer_bundle.h 2013-08-09 01:37:53 +0000
+++ src/server/compositor/buffer_bundle.h 2013-08-29 09:10:29 +0000
@@ -36,7 +36,8 @@
36 virtual ~BufferBundle() noexcept {}36 virtual ~BufferBundle() noexcept {}
37 virtual std::shared_ptr<graphics::Buffer> client_acquire() = 0;37 virtual std::shared_ptr<graphics::Buffer> client_acquire() = 0;
38 virtual void client_release(std::shared_ptr<graphics::Buffer> const&) = 0;38 virtual void client_release(std::shared_ptr<graphics::Buffer> const&) = 0;
39 virtual std::shared_ptr<graphics::Buffer> compositor_acquire() = 0;39 virtual std::shared_ptr<graphics::Buffer>
40 compositor_acquire(unsigned long frameno) = 0;
40 virtual void compositor_release(std::shared_ptr<graphics::Buffer> const&) = 0;41 virtual void compositor_release(std::shared_ptr<graphics::Buffer> const&) = 0;
41 virtual std::shared_ptr<graphics::Buffer> snapshot_acquire() = 0;42 virtual std::shared_ptr<graphics::Buffer> snapshot_acquire() = 0;
42 virtual void snapshot_release(std::shared_ptr<graphics::Buffer> const&) = 0;43 virtual void snapshot_release(std::shared_ptr<graphics::Buffer> const&) = 0;
4344
=== modified file 'src/server/compositor/buffer_stream_surfaces.cpp'
--- src/server/compositor/buffer_stream_surfaces.cpp 2013-08-09 01:37:53 +0000
+++ src/server/compositor/buffer_stream_surfaces.cpp 2013-08-29 09:10:29 +0000
@@ -37,9 +37,11 @@
37 force_requests_to_complete();37 force_requests_to_complete();
38}38}
3939
40std::shared_ptr<mg::Buffer> mc::BufferStreamSurfaces::lock_compositor_buffer()40std::shared_ptr<mg::Buffer> mc::BufferStreamSurfaces::lock_compositor_buffer(
41 unsigned long frameno)
41{42{
42 return std::make_shared<mc::TemporaryCompositorBuffer>(buffer_bundle);43 return std::make_shared<mc::TemporaryCompositorBuffer>(
44 buffer_bundle, frameno);
43}45}
4446
45std::shared_ptr<mg::Buffer> mc::BufferStreamSurfaces::lock_snapshot_buffer()47std::shared_ptr<mg::Buffer> mc::BufferStreamSurfaces::lock_snapshot_buffer()
4648
=== modified file 'src/server/compositor/default_display_buffer_compositor.cpp'
--- src/server/compositor/default_display_buffer_compositor.cpp 2013-08-26 03:21:56 +0000
+++ src/server/compositor/default_display_buffer_compositor.cpp 2013-08-29 09:10:29 +0000
@@ -49,6 +49,14 @@
49 mir::geometry::Rectangle const& enclosing_region;49 mir::geometry::Rectangle const& enclosing_region;
50};50};
5151
52std::mutex global_frameno_lock;
53unsigned long global_frameno = 0;
54
55bool wrapped_greater_or_equal(unsigned long a, unsigned long b)
56{
57 return (a - b) < (~0UL / 2UL);
58}
59
52}60}
5361
54mc::DefaultDisplayBufferCompositor::DefaultDisplayBufferCompositor(62mc::DefaultDisplayBufferCompositor::DefaultDisplayBufferCompositor(
@@ -59,16 +67,32 @@
59 : mc::BasicDisplayBufferCompositor{display_buffer},67 : mc::BasicDisplayBufferCompositor{display_buffer},
60 scene{scene},68 scene{scene},
61 renderer{renderer},69 renderer{renderer},
62 overlay_renderer{overlay_renderer}70 overlay_renderer{overlay_renderer},
71 local_frameno{global_frameno}
63{72{
64}73}
6574
75
66void mc::DefaultDisplayBufferCompositor::composite()76void mc::DefaultDisplayBufferCompositor::composite()
67{77{
68 static bool got_bypass_env = false;78 static bool got_bypass_env = false;
69 static bool bypass_env = true;79 static bool bypass_env = true;
70 bool bypassed = false;80 bool bypassed = false;
7181
82 /*
83 * Increment frame counts for each tick of the fastest instance of
84 * DefaultDisplayBufferCompositor. This means for the fastest refresh
85 * rate of all attached outputs.
86 */
87 local_frameno++;
88 {
89 std::lock_guard<std::mutex> lock(global_frameno_lock);
90 if (wrapped_greater_or_equal(local_frameno, global_frameno))
91 global_frameno = local_frameno;
92 else
93 local_frameno = global_frameno;
94 }
95
72 if (!got_bypass_env)96 if (!got_bypass_env)
73 {97 {
74 const char *env = getenv("MIR_BYPASS");98 const char *env = getenv("MIR_BYPASS");
@@ -91,7 +115,8 @@
91 if (filter.fullscreen_on_top())115 if (filter.fullscreen_on_top())
92 {116 {
93 auto bypass_buf =117 auto bypass_buf =
94 match.topmost_fullscreen()->lock_compositor_buffer();118 match.topmost_fullscreen()->lock_compositor_buffer(
119 local_frameno);
95120
96 if (bypass_buf->can_bypass())121 if (bypass_buf->can_bypass())
97 {122 {
@@ -110,7 +135,7 @@
110 mir::geometry::Rectangle const& view_area,135 mir::geometry::Rectangle const& view_area,
111 std::function<void(std::shared_ptr<void> const&)> save_resource)136 std::function<void(std::shared_ptr<void> const&)> save_resource)
112{137{
113 renderer->clear();138 renderer->clear(local_frameno);
114139
115 mc::RenderingOperator applicator(*renderer, save_resource);140 mc::RenderingOperator applicator(*renderer, save_resource);
116 FilterForVisibleSceneInRegion selector(view_area);141 FilterForVisibleSceneInRegion selector(view_area);
117142
=== modified file 'src/server/compositor/default_display_buffer_compositor.h'
--- src/server/compositor/default_display_buffer_compositor.h 2013-07-25 04:18:04 +0000
+++ src/server/compositor/default_display_buffer_compositor.h 2013-08-29 09:10:29 +0000
@@ -53,6 +53,8 @@
53 std::shared_ptr<Scene> const scene;53 std::shared_ptr<Scene> const scene;
54 std::shared_ptr<Renderer> const renderer;54 std::shared_ptr<Renderer> const renderer;
55 std::shared_ptr<OverlayRenderer> const overlay_renderer;55 std::shared_ptr<OverlayRenderer> const overlay_renderer;
56
57 unsigned long local_frameno;
56};58};
5759
58}60}
5961
=== modified file 'src/server/compositor/gl_renderer.cpp'
--- src/server/compositor/gl_renderer.cpp 2013-08-23 01:44:53 +0000
+++ src/server/compositor/gl_renderer.cpp 2013-08-29 09:10:29 +0000
@@ -235,6 +235,7 @@
235}235}
236236
237mc::GLRenderer::GLRenderer(geom::Rectangle const& display_area)237mc::GLRenderer::GLRenderer(geom::Rectangle const& display_area)
238 : frameno{0}
238{239{
239 resources.setup(display_area);240 resources.setup(display_area);
240}241}
@@ -265,7 +266,7 @@
265 /* Use the renderable's texture */266 /* Use the renderable's texture */
266 glBindTexture(GL_TEXTURE_2D, resources.texture);267 glBindTexture(GL_TEXTURE_2D, resources.texture);
267268
268 auto region_resource = stream.lock_compositor_buffer();269 auto region_resource = stream.lock_compositor_buffer(frameno);
269 region_resource->bind_to_texture();270 region_resource->bind_to_texture();
270 save_resource(region_resource);271 save_resource(region_resource);
271272
@@ -277,8 +278,9 @@
277 glDisableVertexAttribArray(resources.position_attr_loc);278 glDisableVertexAttribArray(resources.position_attr_loc);
278}279}
279280
280void mc::GLRenderer::clear()281void mc::GLRenderer::clear(unsigned long frame)
281{282{
283 frameno = frame;
282 glClear(GL_COLOR_BUFFER_BIT);284 glClear(GL_COLOR_BUFFER_BIT);
283}285}
284286
285287
=== modified file 'src/server/compositor/gl_renderer.h'
--- src/server/compositor/gl_renderer.h 2013-08-09 01:37:53 +0000
+++ src/server/compositor/gl_renderer.h 2013-08-29 09:10:29 +0000
@@ -36,7 +36,7 @@
36 /* From renderer */36 /* From renderer */
37 void render(std::function<void(std::shared_ptr<void> const&)> save_resource,37 void render(std::function<void(std::shared_ptr<void> const&)> save_resource,
38 CompositingCriteria const& info, surfaces::BufferStream& stream);38 CompositingCriteria const& info, surfaces::BufferStream& stream);
39 void clear();39 void clear(unsigned long frameno) override;
4040
41 ~GLRenderer() noexcept {}41 ~GLRenderer() noexcept {}
4242
@@ -60,6 +60,8 @@
60 };60 };
6161
62 Resources resources;62 Resources resources;
63
64 unsigned long frameno;
63};65};
6466
65}67}
6668
=== modified file 'src/server/compositor/switching_bundle.cpp'
--- src/server/compositor/switching_bundle.cpp 2013-08-09 01:37:53 +0000
+++ src/server/compositor/switching_bundle.cpp 2013-08-29 09:10:29 +0000
@@ -76,6 +76,7 @@
76 first_ready{0}, nready{0},76 first_ready{0}, nready{0},
77 first_client{0}, nclients{0},77 first_client{0}, nclients{0},
78 snapshot{-1}, nsnapshotters{0},78 snapshot{-1}, nsnapshotters{0},
79 last_consumed{0},
79 overlapping_compositors{false},80 overlapping_compositors{false},
80 framedropping{false}, force_drop{0}81 framedropping{false}, force_drop{0}
81{82{
@@ -85,8 +86,6 @@
85 "nbuffers betwee 1 and " +86 "nbuffers betwee 1 and " +
86 std::to_string(MAX_NBUFFERS)));87 std::to_string(MAX_NBUFFERS)));
87 }88 }
88
89 last_consumed = now() - std::chrono::seconds(1);
90}89}
9190
92int mc::SwitchingBundle::nfree() const91int mc::SwitchingBundle::nfree() const
@@ -259,15 +258,14 @@
259 cond.notify_all();258 cond.notify_all();
260}259}
261260
262std::shared_ptr<mg::Buffer> mc::SwitchingBundle::compositor_acquire()261std::shared_ptr<mg::Buffer> mc::SwitchingBundle::compositor_acquire(
262 unsigned long frameno)
263{263{
264 std::unique_lock<std::mutex> lock(guard);264 std::unique_lock<std::mutex> lock(guard);
265 int compositor;265 int compositor;
266266
267 auto t = now();
268
269 // Multi-monitor acquires close to each other get the same frame:267 // Multi-monitor acquires close to each other get the same frame:
270 bool same_frame = (t - last_consumed) < std::chrono::milliseconds(10);268 bool same_frame = (frameno == last_consumed);
271269
272 int avail = nfree();270 int avail = nfree();
273 bool can_recycle = ncompositors || avail;271 bool can_recycle = ncompositors || avail;
@@ -296,7 +294,7 @@
296 first_ready = next(first_ready);294 first_ready = next(first_ready);
297 nready--;295 nready--;
298 ncompositors++;296 ncompositors++;
299 last_consumed = t;297 last_consumed = frameno;
300 }298 }
301299
302 overlapping_compositors = (ncompositors > 1);300 overlapping_compositors = (ncompositors > 1);
303301
=== modified file 'src/server/compositor/switching_bundle.h'
--- src/server/compositor/switching_bundle.h 2013-08-09 01:37:53 +0000
+++ src/server/compositor/switching_bundle.h 2013-08-29 09:10:29 +0000
@@ -24,7 +24,6 @@
24#include <condition_variable>24#include <condition_variable>
25#include <mutex>25#include <mutex>
26#include <memory>26#include <memory>
27#include <chrono>
2827
29namespace mir28namespace mir
30{29{
@@ -47,7 +46,8 @@
4746
48 std::shared_ptr<graphics::Buffer> client_acquire();47 std::shared_ptr<graphics::Buffer> client_acquire();
49 void client_release(std::shared_ptr<graphics::Buffer> const&);48 void client_release(std::shared_ptr<graphics::Buffer> const&);
50 std::shared_ptr<graphics::Buffer> compositor_acquire();49 std::shared_ptr<graphics::Buffer>
50 compositor_acquire(unsigned long frameno) override;
51 void compositor_release(std::shared_ptr<graphics::Buffer> const& released_buffer);51 void compositor_release(std::shared_ptr<graphics::Buffer> const& released_buffer);
52 std::shared_ptr<graphics::Buffer> snapshot_acquire();52 std::shared_ptr<graphics::Buffer> snapshot_acquire();
53 void snapshot_release(std::shared_ptr<graphics::Buffer> const& released_buffer);53 void snapshot_release(std::shared_ptr<graphics::Buffer> const& released_buffer);
@@ -89,10 +89,7 @@
89 std::mutex guard;89 std::mutex guard;
90 std::condition_variable cond;90 std::condition_variable cond;
9191
92 typedef std::chrono::high_resolution_clock::time_point time_point;92 unsigned long last_consumed;
93 static time_point now()
94 { return std::chrono::high_resolution_clock::now(); }
95 time_point last_consumed;
9693
97 bool overlapping_compositors;94 bool overlapping_compositors;
9895
9996
=== modified file 'src/server/compositor/temporary_buffers.cpp'
--- src/server/compositor/temporary_buffers.cpp 2013-08-13 07:56:50 +0000
+++ src/server/compositor/temporary_buffers.cpp 2013-08-29 09:10:29 +0000
@@ -41,8 +41,8 @@
41}41}
4242
43mc::TemporaryCompositorBuffer::TemporaryCompositorBuffer(43mc::TemporaryCompositorBuffer::TemporaryCompositorBuffer(
44 std::shared_ptr<BufferBundle> const& bun)44 std::shared_ptr<BufferBundle> const& bun, unsigned long frameno)
45 : TemporaryBuffer(bun->compositor_acquire()),45 : TemporaryBuffer(bun->compositor_acquire(frameno)),
46 bundle(bun)46 bundle(bun)
47{47{
48}48}
4949
=== modified file 'src/server/compositor/temporary_buffers.h'
--- src/server/compositor/temporary_buffers.h 2013-08-13 07:56:50 +0000
+++ src/server/compositor/temporary_buffers.h 2013-08-29 09:10:29 +0000
@@ -62,7 +62,7 @@
62{62{
63public:63public:
64 explicit TemporaryCompositorBuffer(64 explicit TemporaryCompositorBuffer(
65 std::shared_ptr<BufferBundle> const& bun);65 std::shared_ptr<BufferBundle> const& bun, unsigned long frameno);
66 ~TemporaryCompositorBuffer();66 ~TemporaryCompositorBuffer();
6767
68private:68private:
6969
=== modified file 'src/server/surfaces/surface.cpp'
--- src/server/surfaces/surface.cpp 2013-08-09 01:37:53 +0000
+++ src/server/surfaces/surface.cpp 2013-08-29 09:10:29 +0000
@@ -125,7 +125,7 @@
125125
126std::shared_ptr<mg::Buffer> ms::Surface::compositor_buffer() const126std::shared_ptr<mg::Buffer> ms::Surface::compositor_buffer() const
127{127{
128 return surface_buffer_stream->lock_compositor_buffer();128 return surface_buffer_stream->lock_compositor_buffer(0);
129}129}
130130
131std::shared_ptr<mg::Buffer> ms::Surface::snapshot_buffer() const131std::shared_ptr<mg::Buffer> ms::Surface::snapshot_buffer() const
132132
=== modified file 'tests/acceptance-tests/test_server_shutdown.cpp'
--- tests/acceptance-tests/test_server_shutdown.cpp 2013-08-26 03:00:33 +0000
+++ tests/acceptance-tests/test_server_shutdown.cpp 2013-08-29 09:10:29 +0000
@@ -58,7 +58,7 @@
58 std::this_thread::yield();58 std::this_thread::yield();
59 }59 }
6060
61 void clear() {}61 void clear(unsigned long) override {}
62};62};
6363
6464
6565
=== modified file 'tests/integration-tests/compositor/test_buffer_stream.cpp'
--- tests/integration-tests/compositor/test_buffer_stream.cpp 2013-08-09 01:37:53 +0000
+++ tests/integration-tests/compositor/test_buffer_stream.cpp 2013-08-29 09:10:29 +0000
@@ -64,11 +64,6 @@
64 mc::BufferStreamSurfaces buffer_stream;64 mc::BufferStreamSurfaces buffer_stream;
65};65};
6666
67void sleep_one_frame()
68{
69 std::this_thread::sleep_for(std::chrono::milliseconds(16));
70}
71
72}67}
7368
74TEST_F(BufferStreamTest, gives_same_back_buffer_until_more_available)69TEST_F(BufferStreamTest, gives_same_back_buffer_until_more_available)
@@ -77,8 +72,8 @@
77 auto client1_id = client1->id();72 auto client1_id = client1->id();
78 client1.reset();73 client1.reset();
7974
80 auto comp1 = buffer_stream.lock_compositor_buffer();75 auto comp1 = buffer_stream.lock_compositor_buffer(1);
81 auto comp2 = buffer_stream.lock_compositor_buffer();76 auto comp2 = buffer_stream.lock_compositor_buffer(1);
8277
83 EXPECT_EQ(comp1->id(), comp2->id());78 EXPECT_EQ(comp1->id(), comp2->id());
84 EXPECT_EQ(comp1->id(), client1_id);79 EXPECT_EQ(comp1->id(), client1_id);
@@ -86,8 +81,7 @@
86 comp1.reset();81 comp1.reset();
8782
88 buffer_stream.secure_client_buffer().reset();83 buffer_stream.secure_client_buffer().reset();
89 sleep_one_frame();84 auto comp3 = buffer_stream.lock_compositor_buffer(2);
90 auto comp3 = buffer_stream.lock_compositor_buffer();
9185
92 EXPECT_NE(client1_id, comp3->id());86 EXPECT_NE(client1_id, comp3->id());
9387
@@ -95,7 +89,7 @@
95 auto comp3_id = comp3->id();89 auto comp3_id = comp3->id();
96 comp3.reset();90 comp3.reset();
9791
98 auto comp4 = buffer_stream.lock_compositor_buffer();92 auto comp4 = buffer_stream.lock_compositor_buffer(2);
99 EXPECT_EQ(comp3_id, comp4->id());93 EXPECT_EQ(comp3_id, comp4->id());
100}94}
10195
@@ -104,13 +98,13 @@
104 for (int i = 0; i < nbuffers - 1; i++)98 for (int i = 0; i < nbuffers - 1; i++)
105 buffer_stream.secure_client_buffer().reset();99 buffer_stream.secure_client_buffer().reset();
106100
107 auto first_monitor = buffer_stream.lock_compositor_buffer();101 auto first_monitor = buffer_stream.lock_compositor_buffer(1);
108 auto first_compositor_id = first_monitor->id();102 auto first_compositor_id = first_monitor->id();
109 first_monitor.reset();103 first_monitor.reset();
110104
111 for (int m = 0; m < 10; m++)105 for (int m = 0; m < 10; m++)
112 {106 {
113 auto monitor = buffer_stream.lock_compositor_buffer();107 auto monitor = buffer_stream.lock_compositor_buffer(1);
114 ASSERT_EQ(first_compositor_id, monitor->id());108 ASSERT_EQ(first_compositor_id, monitor->id());
115 }109 }
116}110}
@@ -120,12 +114,10 @@
120 if (nbuffers > 1)114 if (nbuffers > 1)
121 {115 {
122 buffer_stream.secure_client_buffer().reset();116 buffer_stream.secure_client_buffer().reset();
123 auto comp1 = buffer_stream.lock_compositor_buffer();117 auto comp1 = buffer_stream.lock_compositor_buffer(1);
124
125 sleep_one_frame();
126118
127 buffer_stream.secure_client_buffer().reset();119 buffer_stream.secure_client_buffer().reset();
128 auto comp2 = buffer_stream.lock_compositor_buffer();120 auto comp2 = buffer_stream.lock_compositor_buffer(2);
129 121
130 EXPECT_NE(comp1->id(), comp2->id());122 EXPECT_NE(comp1->id(), comp2->id());
131 123
@@ -139,14 +131,14 @@
139 buffer_stream.secure_client_buffer().reset();131 buffer_stream.secure_client_buffer().reset();
140 auto client1 = buffer_stream.secure_client_buffer();132 auto client1 = buffer_stream.secure_client_buffer();
141133
142 auto comp1 = buffer_stream.lock_compositor_buffer();134 auto comp1 = buffer_stream.lock_compositor_buffer(123);
143 auto comp2 = buffer_stream.lock_compositor_buffer();135 auto comp2 = buffer_stream.lock_compositor_buffer(123);
144136
145 EXPECT_EQ(comp1->id(), comp2->id());137 EXPECT_EQ(comp1->id(), comp2->id());
146138
147 comp1.reset();139 comp1.reset();
148140
149 auto comp3 = buffer_stream.lock_compositor_buffer();141 auto comp3 = buffer_stream.lock_compositor_buffer(123);
150142
151 EXPECT_EQ(comp2->id(), comp3->id());143 EXPECT_EQ(comp2->id(), comp3->id());
152}144}
@@ -167,13 +159,15 @@
167void compositor_loop(ms::BufferStream &stream,159void compositor_loop(ms::BufferStream &stream,
168 std::atomic<bool> &done)160 std::atomic<bool> &done)
169{161{
162 unsigned long count = 0;
163
170 while (!done.load())164 while (!done.load())
171 {165 {
172 auto comp1 = stream.lock_compositor_buffer();166 auto comp1 = stream.lock_compositor_buffer(++count);
173 ASSERT_NE(nullptr, comp1);167 ASSERT_NE(nullptr, comp1);
174168
175 // Also stress test getting a second compositor buffer before yielding169 // Also stress test getting a second compositor buffer before yielding
176 auto comp2 = stream.lock_compositor_buffer();170 auto comp2 = stream.lock_compositor_buffer(count);
177 ASSERT_NE(nullptr, comp2);171 ASSERT_NE(nullptr, comp2);
178172
179 std::this_thread::yield();173 std::this_thread::yield();
180174
=== modified file 'tests/integration-tests/compositor/test_swapping_swappers.cpp'
--- tests/integration-tests/compositor/test_swapping_swappers.cpp 2013-08-09 01:37:53 +0000
+++ tests/integration-tests/compositor/test_swapping_swappers.cpp 2013-08-29 09:10:29 +0000
@@ -72,9 +72,10 @@
72 auto g = std::async(std::launch::async,72 auto g = std::async(std::launch::async,
73 [this]73 [this]
74 {74 {
75 unsigned long count = 0;
75 while(!client_thread_done)76 while(!client_thread_done)
76 {77 {
77 auto b = switching_bundle->compositor_acquire();78 auto b = switching_bundle->compositor_acquire(++count);
78 std::this_thread::yield();79 std::this_thread::yield();
79 switching_bundle->compositor_release(b);80 switching_bundle->compositor_release(b);
80 }81 }
@@ -116,9 +117,10 @@
116 auto g = std::async(std::launch::async,117 auto g = std::async(std::launch::async,
117 [this]118 [this]
118 {119 {
120 unsigned long count = 0;
119 while(!client_thread_done)121 while(!client_thread_done)
120 {122 {
121 auto b = switching_bundle->compositor_acquire();123 auto b = switching_bundle->compositor_acquire(++count);
122 std::this_thread::yield();124 std::this_thread::yield();
123 switching_bundle->compositor_release(b);125 switching_bundle->compositor_release(b);
124 }126 }
125127
=== modified file 'tests/integration-tests/shell/test_session.cpp'
--- tests/integration-tests/shell/test_session.cpp 2013-08-12 01:44:15 +0000
+++ tests/integration-tests/shell/test_session.cpp 2013-08-29 09:10:29 +0000
@@ -95,11 +95,11 @@
95 {95 {
96 struct StubRenderer : public mc::Renderer96 struct StubRenderer : public mc::Renderer
97 {97 {
98 void clear() {}98 void clear(unsigned long) override {}
99 void render(std::function<void(std::shared_ptr<void> const&)>,99 void render(std::function<void(std::shared_ptr<void> const&)>,
100 mc::CompositingCriteria const&, mir::surfaces::BufferStream& stream)100 mc::CompositingCriteria const&, mir::surfaces::BufferStream& stream)
101 {101 {
102 stream.lock_compositor_buffer();102 stream.lock_compositor_buffer(0);
103 }103 }
104104
105 void ensure_no_live_buffers_bound() {}105 void ensure_no_live_buffers_bound() {}
106106
=== modified file 'tests/integration-tests/test_surface_first_frame_sync.cpp'
--- tests/integration-tests/test_surface_first_frame_sync.cpp 2013-08-26 03:00:33 +0000
+++ tests/integration-tests/test_surface_first_frame_sync.cpp 2013-08-29 09:10:29 +0000
@@ -96,7 +96,7 @@
96 {96 {
97 }97 }
9898
99 void clear() {}99 void clear(unsigned long) override {}
100100
101 void render(std::function<void(std::shared_ptr<void> const&)>, mc::CompositingCriteria const&, ms::BufferStream&)101 void render(std::function<void(std::shared_ptr<void> const&)>, mc::CompositingCriteria const&, ms::BufferStream&)
102 {102 {
103103
=== modified file 'tests/integration-tests/test_swapinterval.cpp'
--- tests/integration-tests/test_swapinterval.cpp 2013-08-26 03:00:33 +0000
+++ tests/integration-tests/test_swapinterval.cpp 2013-08-29 09:10:29 +0000
@@ -57,7 +57,7 @@
57 }57 }
5858
59 std::shared_ptr<mg::Buffer> secure_client_buffer() { return std::make_shared<mtd::StubBuffer>(); }59 std::shared_ptr<mg::Buffer> secure_client_buffer() { return std::make_shared<mtd::StubBuffer>(); }
60 std::shared_ptr<mg::Buffer> lock_compositor_buffer() { return std::make_shared<mtd::StubBuffer>(); }60 std::shared_ptr<mg::Buffer> lock_compositor_buffer(unsigned long) { return std::make_shared<mtd::StubBuffer>(); }
61 std::shared_ptr<mg::Buffer> lock_snapshot_buffer() { return std::make_shared<mtd::StubBuffer>(); }61 std::shared_ptr<mg::Buffer> lock_snapshot_buffer() { return std::make_shared<mtd::StubBuffer>(); }
62 geom::PixelFormat get_stream_pixel_format() { return geom::PixelFormat::abgr_8888; }62 geom::PixelFormat get_stream_pixel_format() { return geom::PixelFormat::abgr_8888; }
63 geom::Size stream_size() { return geom::Size{}; }63 geom::Size stream_size() { return geom::Size{}; }
6464
=== modified file 'tests/mir_test_framework/testing_server_options.cpp'
--- tests/mir_test_framework/testing_server_options.cpp 2013-08-27 10:19:54 +0000
+++ tests/mir_test_framework/testing_server_options.cpp 2013-08-29 09:10:29 +0000
@@ -200,10 +200,10 @@
200 mc::CompositingCriteria const&, ms::BufferStream& stream)200 mc::CompositingCriteria const&, ms::BufferStream& stream)
201 {201 {
202 // Need to acquire the texture to cycle buffers202 // Need to acquire the texture to cycle buffers
203 stream.lock_compositor_buffer();203 stream.lock_compositor_buffer(0);
204 }204 }
205205
206 void clear() {}206 void clear(unsigned long) override {}
207};207};
208208
209class StubRendererFactory : public mc::RendererFactory209class StubRendererFactory : public mc::RendererFactory
210210
=== modified file 'tests/unit-tests/compositor/test_buffer_stream.cpp'
--- tests/unit-tests/compositor/test_buffer_stream.cpp 2013-08-09 01:37:53 +0000
+++ tests/unit-tests/compositor/test_buffer_stream.cpp 2013-08-29 09:10:29 +0000
@@ -95,7 +95,7 @@
95{95{
96 using namespace testing;96 using namespace testing;
9797
98 EXPECT_CALL(*mock_bundle, compositor_acquire())98 EXPECT_CALL(*mock_bundle, compositor_acquire(_))
99 .Times(1)99 .Times(1)
100 .WillOnce(Return(mock_buffer));100 .WillOnce(Return(mock_buffer));
101 EXPECT_CALL(*mock_bundle, compositor_release(_))101 EXPECT_CALL(*mock_bundle, compositor_release(_))
@@ -103,14 +103,14 @@
103103
104 mc::BufferStreamSurfaces buffer_stream(mock_bundle);104 mc::BufferStreamSurfaces buffer_stream(mock_bundle);
105105
106 buffer_stream.lock_compositor_buffer();106 buffer_stream.lock_compositor_buffer(0);
107}107}
108108
109TEST_F(BufferStreamTest, get_buffer_for_compositor_can_lock)109TEST_F(BufferStreamTest, get_buffer_for_compositor_can_lock)
110{110{
111 using namespace testing;111 using namespace testing;
112112
113 EXPECT_CALL(*mock_bundle, compositor_acquire())113 EXPECT_CALL(*mock_bundle, compositor_acquire(_))
114 .Times(1)114 .Times(1)
115 .WillOnce(Return(mock_buffer));115 .WillOnce(Return(mock_buffer));
116 EXPECT_CALL(*mock_bundle, compositor_release(_))116 EXPECT_CALL(*mock_bundle, compositor_release(_))
@@ -118,7 +118,7 @@
118118
119 mc::BufferStreamSurfaces buffer_stream(mock_bundle);119 mc::BufferStreamSurfaces buffer_stream(mock_bundle);
120120
121 buffer_stream.lock_compositor_buffer();121 buffer_stream.lock_compositor_buffer(0);
122}122}
123123
124TEST_F(BufferStreamTest, get_buffer_for_client_releases_resources)124TEST_F(BufferStreamTest, get_buffer_for_client_releases_resources)
125125
=== modified file 'tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp'
--- tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2013-08-26 03:00:33 +0000
+++ tests/unit-tests/compositor/test_default_display_buffer_compositor.cpp 2013-08-29 09:10:29 +0000
@@ -97,7 +97,7 @@
97 {97 {
98 }98 }
9999
100 void clear() { renderer->clear(); }100 void clear(unsigned long f) override { renderer->clear(f); }
101 void render(std::function<void(std::shared_ptr<void> const&)> save_resource,101 void render(std::function<void(std::shared_ptr<void> const&)> save_resource,
102 mc::CompositingCriteria const& info, mir::surfaces::BufferStream& stream)102 mc::CompositingCriteria const& info, mir::surfaces::BufferStream& stream)
103 {103 {
@@ -254,7 +254,7 @@
254 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();254 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();
255 EXPECT_CALL(*compositor_buffer, can_bypass())255 EXPECT_CALL(*compositor_buffer, can_bypass())
256 .WillOnce(Return(true));256 .WillOnce(Return(true));
257 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())257 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
258 .WillOnce(Return(compositor_buffer));258 .WillOnce(Return(compositor_buffer));
259259
260 mc::DefaultDisplayBufferCompositorFactory factory(260 mc::DefaultDisplayBufferCompositorFactory factory(
@@ -303,7 +303,7 @@
303 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();303 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();
304 EXPECT_CALL(*compositor_buffer, can_bypass())304 EXPECT_CALL(*compositor_buffer, can_bypass())
305 .Times(0);305 .Times(0);
306 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())306 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
307 .Times(0);307 .Times(0);
308308
309 mc::DefaultDisplayBufferCompositorFactory factory(309 mc::DefaultDisplayBufferCompositorFactory factory(
@@ -352,7 +352,7 @@
352 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();352 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();
353 EXPECT_CALL(*compositor_buffer, can_bypass())353 EXPECT_CALL(*compositor_buffer, can_bypass())
354 .Times(0);354 .Times(0);
355 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())355 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
356 .Times(0);356 .Times(0);
357357
358 mc::DefaultDisplayBufferCompositorFactory factory(358 mc::DefaultDisplayBufferCompositorFactory factory(
@@ -399,7 +399,7 @@
399 FakeScene scene(renderable_vec);399 FakeScene scene(renderable_vec);
400400
401 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();401 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();
402 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())402 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
403 .WillOnce(Return(compositor_buffer));403 .WillOnce(Return(compositor_buffer));
404 EXPECT_CALL(*compositor_buffer, can_bypass())404 EXPECT_CALL(*compositor_buffer, can_bypass())
405 .WillRepeatedly(Return(false));405 .WillRepeatedly(Return(false));
@@ -450,7 +450,7 @@
450 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();450 auto compositor_buffer = std::make_shared<mtd::MockBuffer>();
451 EXPECT_CALL(*compositor_buffer, can_bypass())451 EXPECT_CALL(*compositor_buffer, can_bypass())
452 .Times(0);452 .Times(0);
453 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())453 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
454 .Times(0);454 .Times(0);
455455
456 mc::DefaultDisplayBufferCompositorFactory factory(456 mc::DefaultDisplayBufferCompositorFactory factory(
@@ -476,7 +476,7 @@
476 .Times(0);476 .Times(0);
477 EXPECT_CALL(renderer_factory.mock_renderer, render(_,Ref(fullscreen),_))477 EXPECT_CALL(renderer_factory.mock_renderer, render(_,Ref(fullscreen),_))
478 .Times(0);478 .Times(0);
479 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())479 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
480 .WillOnce(Return(compositor_buffer));480 .WillOnce(Return(compositor_buffer));
481 EXPECT_CALL(*compositor_buffer, can_bypass())481 EXPECT_CALL(*compositor_buffer, can_bypass())
482 .WillOnce(Return(true));482 .WillOnce(Return(true));
@@ -494,7 +494,7 @@
494 .Times(1);494 .Times(1);
495 EXPECT_CALL(renderer_factory.mock_renderer, render(_,Ref(fullscreen),_))495 EXPECT_CALL(renderer_factory.mock_renderer, render(_,Ref(fullscreen),_))
496 .Times(0);496 .Times(0);
497 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer())497 EXPECT_CALL(scene.stub_stream, lock_compositor_buffer(_))
498 .Times(0);498 .Times(0);
499 EXPECT_CALL(*compositor_buffer, can_bypass())499 EXPECT_CALL(*compositor_buffer, can_bypass())
500 .Times(0);500 .Times(0);
501501
=== modified file 'tests/unit-tests/compositor/test_gl_renderer.cpp'
--- tests/unit-tests/compositor/test_gl_renderer.cpp 2013-08-09 01:37:53 +0000
+++ tests/unit-tests/compositor/test_gl_renderer.cpp 2013-08-29 09:10:29 +0000
@@ -319,7 +319,7 @@
319319
320 EXPECT_CALL(mock_gl, glBindTexture(GL_TEXTURE_2D, stub_texture));320 EXPECT_CALL(mock_gl, glBindTexture(GL_TEXTURE_2D, stub_texture));
321321
322 EXPECT_CALL(stream, lock_compositor_buffer())322 EXPECT_CALL(stream, lock_compositor_buffer(_))
323 .Times(1)323 .Times(1)
324 .WillOnce(Return(mt::fake_shared(gr)));324 .WillOnce(Return(mt::fake_shared(gr)));
325 EXPECT_CALL(gr, bind_to_texture());325 EXPECT_CALL(gr, bind_to_texture());
326326
=== modified file 'tests/unit-tests/compositor/test_rendering_operator.cpp'
--- tests/unit-tests/compositor/test_rendering_operator.cpp 2013-08-09 01:37:53 +0000
+++ tests/unit-tests/compositor/test_rendering_operator.cpp 2013-08-29 09:10:29 +0000
@@ -46,7 +46,7 @@
46 {46 {
47 }47 }
4848
49 void clear() {}49 void clear(unsigned long) override {}
5050
51 void render(std::function<void(std::shared_ptr<void> const&)> save_resource,51 void render(std::function<void(std::shared_ptr<void> const&)> save_resource,
52 mc::CompositingCriteria const&, ms::BufferStream&)52 mc::CompositingCriteria const&, ms::BufferStream&)
5353
=== modified file 'tests/unit-tests/compositor/test_switching_bundle.cpp'
--- tests/unit-tests/compositor/test_switching_bundle.cpp 2013-08-09 01:37:53 +0000
+++ tests/unit-tests/compositor/test_switching_bundle.cpp 2013-08-29 09:10:29 +0000
@@ -102,19 +102,12 @@
102102
103namespace103namespace
104{104{
105 const int frame_rate = 60;
106 const std::chrono::microseconds frame_time(1000000 / frame_rate);
107
108 void sleep_one_frame()
109 {
110 std::this_thread::sleep_for(frame_time);
111 }
112
113 void composite_thread(mc::SwitchingBundle &bundle,105 void composite_thread(mc::SwitchingBundle &bundle,
106 unsigned long &frameno,
114 mg::BufferID &composited)107 mg::BufferID &composited)
115 {108 {
116 sleep_one_frame();109 frameno++;
117 auto buffer = bundle.compositor_acquire();110 auto buffer = bundle.compositor_acquire(frameno);
118 composited = buffer->id();111 composited = buffer->id();
119 bundle.compositor_release(buffer);112 bundle.compositor_release(buffer);
120 }113 }
@@ -126,6 +119,7 @@
126 {119 {
127 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);120 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
128 mg::BufferID prev_id, prev_prev_id;121 mg::BufferID prev_id, prev_prev_id;
122 unsigned long frameno = 0;
129123
130 ASSERT_FALSE(bundle.framedropping_allowed());124 ASSERT_FALSE(bundle.framedropping_allowed());
131125
@@ -137,6 +131,7 @@
137131
138 std::thread compositor(composite_thread,132 std::thread compositor(composite_thread,
139 std::ref(bundle),133 std::ref(bundle),
134 std::ref(frameno),
140 std::ref(composited_id));135 std::ref(composited_id));
141136
142 compositor.join();137 compositor.join();
@@ -148,7 +143,7 @@
148 prev_prev_id = prev_id;143 prev_prev_id = prev_id;
149 prev_id = composited_id;144 prev_id = composited_id;
150145
151 auto second_monitor = bundle.compositor_acquire();146 auto second_monitor = bundle.compositor_acquire(frameno);
152 ASSERT_EQ(composited_id, second_monitor->id());147 ASSERT_EQ(composited_id, second_monitor->id());
153 bundle.compositor_release(second_monitor);148 bundle.compositor_release(second_monitor);
154 }149 }
@@ -160,6 +155,7 @@
160 for (int nbuffers = 2; nbuffers <= 5; nbuffers++)155 for (int nbuffers = 2; nbuffers <= 5; nbuffers++)
161 {156 {
162 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);157 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
158 unsigned int frameno = 0;
163159
164 bundle.allow_framedropping(true);160 bundle.allow_framedropping(true);
165 mg::BufferID last_client_id;161 mg::BufferID last_client_id;
@@ -176,11 +172,12 @@
176 // Flush the pipeline of previously ready buffers172 // Flush the pipeline of previously ready buffers
177 for (int k = 0; k < nbuffers-1; k++)173 for (int k = 0; k < nbuffers-1; k++)
178 {174 {
179 bundle.compositor_release(bundle.compositor_acquire());175 frameno++;
180 sleep_one_frame();176 bundle.compositor_release(bundle.compositor_acquire(frameno));
181 }177 }
182178
183 auto compositor = bundle.compositor_acquire();179 frameno++;
180 auto compositor = bundle.compositor_acquire(frameno);
184 ASSERT_EQ(last_client_id, compositor->id());181 ASSERT_EQ(last_client_id, compositor->id());
185 bundle.compositor_release(compositor);182 bundle.compositor_release(compositor);
186 }183 }
@@ -200,7 +197,7 @@
200 bundle.client_release(client2);197 bundle.client_release(client2);
201 client2.reset();198 client2.reset();
202199
203 auto compositor = bundle.compositor_acquire();200 auto compositor = bundle.compositor_acquire(1);
204 EXPECT_EQ(client1_id, compositor->id());201 EXPECT_EQ(client1_id, compositor->id());
205 bundle.compositor_release(compositor);202 bundle.compositor_release(compositor);
206}203}
@@ -231,6 +228,7 @@
231 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)228 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)
232 {229 {
233 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);230 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
231 unsigned long frameno = 0;
234232
235 auto client = bundle.client_acquire();233 auto client = bundle.client_acquire();
236 auto client_id = client->id();234 auto client_id = client->id();
@@ -238,7 +236,8 @@
238236
239 for (int monitor = 0; monitor < 10; monitor++)237 for (int monitor = 0; monitor < 10; monitor++)
240 {238 {
241 auto compositor = bundle.compositor_acquire();239 frameno++;
240 auto compositor = bundle.compositor_acquire(frameno);
242 ASSERT_EQ(client_id, compositor->id());241 ASSERT_EQ(client_id, compositor->id());
243 bundle.compositor_release(compositor);242 bundle.compositor_release(compositor);
244 }243 }
@@ -250,13 +249,14 @@
250 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)249 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)
251 {250 {
252 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);251 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
252 unsigned long frameno = 0;
253 const int N = 100;253 const int N = 100;
254254
255 bundle.force_requests_to_complete();255 bundle.force_requests_to_complete();
256256
257 std::shared_ptr<mg::Buffer> buf[N];257 std::shared_ptr<mg::Buffer> buf[N];
258 for (int i = 0; i < N; i++)258 for (int i = 0; i < N; i++)
259 buf[i] = bundle.compositor_acquire();259 buf[i] = bundle.compositor_acquire(++frameno);
260260
261 for (int i = 0; i < N; i++)261 for (int i = 0; i < N; i++)
262 bundle.compositor_release(buf[i]);262 bundle.compositor_release(buf[i]);
@@ -268,6 +268,7 @@
268 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)268 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)
269 {269 {
270 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);270 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
271 unsigned long frameno = 1;
271272
272 mg::BufferID client_id;273 mg::BufferID client_id;
273274
@@ -282,12 +283,12 @@
282283
283 for (int monitor_id = 0; monitor_id < 10; monitor_id++)284 for (int monitor_id = 0; monitor_id < 10; monitor_id++)
284 {285 {
285 auto compositor = bundle.compositor_acquire();286 auto compositor = bundle.compositor_acquire(frameno);
286 ASSERT_EQ(client_id, compositor->id());287 ASSERT_EQ(client_id, compositor->id());
287 bundle.compositor_release(compositor);288 bundle.compositor_release(compositor);
288 }289 }
289290
290 sleep_one_frame();291 frameno++;
291 }292 }
292 }293 }
293}294}
@@ -297,6 +298,7 @@
297 for (int nbuffers = 2; nbuffers <= 5; nbuffers++)298 for (int nbuffers = 2; nbuffers <= 5; nbuffers++)
298 {299 {
299 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);300 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
301 unsigned long frameno = 0;
300302
301 auto client = bundle.client_acquire();303 auto client = bundle.client_acquire();
302304
@@ -306,7 +308,7 @@
306 );308 );
307 bundle.client_release(client);309 bundle.client_release(client);
308310
309 auto compositor1 = bundle.compositor_acquire();311 auto compositor1 = bundle.compositor_acquire(++frameno);
310 bundle.compositor_release(compositor1);312 bundle.compositor_release(compositor1);
311 EXPECT_THROW(313 EXPECT_THROW(
312 bundle.compositor_release(compositor1),314 bundle.compositor_release(compositor1),
@@ -321,15 +323,16 @@
321 for (int nbuffers = 2; nbuffers <= 5; nbuffers++)323 for (int nbuffers = 2; nbuffers <= 5; nbuffers++)
322 {324 {
323 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);325 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
326 unsigned long frameno = 1;
324327
325 std::shared_ptr<mg::Buffer> compositor[2];328 std::shared_ptr<mg::Buffer> compositor[2];
326329
327 bundle.client_release(bundle.client_acquire());330 bundle.client_release(bundle.client_acquire());
328 compositor[0] = bundle.compositor_acquire();331 compositor[0] = bundle.compositor_acquire(frameno);
329332
330 sleep_one_frame();333 frameno++;
331 bundle.client_release(bundle.client_acquire());334 bundle.client_release(bundle.client_acquire());
332 compositor[1] = bundle.compositor_acquire();335 compositor[1] = bundle.compositor_acquire(frameno);
333336
334 for (int i = 0; i < 20; i++)337 for (int i = 0; i < 20; i++)
335 {338 {
@@ -340,8 +343,8 @@
340 int oldest = i & 1;343 int oldest = i & 1;
341 bundle.compositor_release(compositor[oldest]);344 bundle.compositor_release(compositor[oldest]);
342 bundle.client_release(bundle.client_acquire());345 bundle.client_release(bundle.client_acquire());
343 sleep_one_frame();346 frameno++;
344 compositor[oldest] = bundle.compositor_acquire();347 compositor[oldest] = bundle.compositor_acquire(frameno);
345 }348 }
346349
347 bundle.compositor_release(compositor[0]);350 bundle.compositor_release(compositor[0]);
@@ -355,7 +358,7 @@
355 {358 {
356 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);359 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
357360
358 auto compositor = bundle.compositor_acquire();361 auto compositor = bundle.compositor_acquire(1);
359 auto snapshot = bundle.snapshot_acquire();362 auto snapshot = bundle.snapshot_acquire();
360 EXPECT_EQ(snapshot->id(), compositor->id());363 EXPECT_EQ(snapshot->id(), compositor->id());
361 bundle.compositor_release(compositor);364 bundle.compositor_release(compositor);
@@ -385,7 +388,7 @@
385 {388 {
386 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);389 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
387390
388 auto compositor = bundle.compositor_acquire();391 auto compositor = bundle.compositor_acquire(1);
389392
390 EXPECT_THROW(393 EXPECT_THROW(
391 bundle.snapshot_release(compositor),394 bundle.snapshot_release(compositor),
@@ -418,9 +421,10 @@
418 void compositor_thread(mc::SwitchingBundle &bundle,421 void compositor_thread(mc::SwitchingBundle &bundle,
419 std::atomic<bool> &done)422 std::atomic<bool> &done)
420 {423 {
424 unsigned long frameno = 0;
421 while (!done)425 while (!done)
422 {426 {
423 bundle.compositor_release(bundle.compositor_acquire());427 bundle.compositor_release(bundle.compositor_acquire(++frameno));
424 std::this_thread::yield();428 std::this_thread::yield();
425 }429 }
426 }430 }
@@ -510,6 +514,7 @@
510 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)514 for (int nbuffers = 1; nbuffers <= 5; nbuffers++)
511 {515 {
512 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);516 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
517 unsigned long frameno = 0;
513518
514 bundle.allow_framedropping(false);519 bundle.allow_framedropping(false);
515520
@@ -520,9 +525,9 @@
520525
521 for (int frame = 0; frame < nframes; frame++)526 for (int frame = 0; frame < nframes; frame++)
522 {527 {
523 sleep_one_frame();528 frameno++;
524529
525 auto compositor = bundle.compositor_acquire();530 auto compositor = bundle.compositor_acquire(frameno);
526 auto compositor_id = compositor->id();531 auto compositor_id = compositor->id();
527 bundle.compositor_release(compositor);532 bundle.compositor_release(compositor);
528533
@@ -542,15 +547,16 @@
542 for (int nbuffers = 3; nbuffers <= 5; nbuffers++)547 for (int nbuffers = 3; nbuffers <= 5; nbuffers++)
543 {548 {
544 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);549 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
550 unsigned long frameno = 1;
545551
546 std::shared_ptr<mg::Buffer> compositor[2];552 std::shared_ptr<mg::Buffer> compositor[2];
547553
548 bundle.client_release(bundle.client_acquire());554 bundle.client_release(bundle.client_acquire());
549 compositor[0] = bundle.compositor_acquire();555 compositor[0] = bundle.compositor_acquire(frameno);
550556
551 sleep_one_frame();557 frameno++;
552 bundle.client_release(bundle.client_acquire());558 bundle.client_release(bundle.client_acquire());
553 compositor[1] = bundle.compositor_acquire();559 compositor[1] = bundle.compositor_acquire(frameno);
554560
555 for (int i = 0; i < 20; i++)561 for (int i = 0; i < 20; i++)
556 {562 {
@@ -566,8 +572,8 @@
566 int oldest = i & 1;572 int oldest = i & 1;
567 bundle.compositor_release(compositor[oldest]);573 bundle.compositor_release(compositor[oldest]);
568574
569 sleep_one_frame();575 frameno++;
570 compositor[oldest] = bundle.compositor_acquire();576 compositor[oldest] = bundle.compositor_acquire(frameno);
571 }577 }
572578
573 bundle.compositor_release(compositor[0]);579 bundle.compositor_release(compositor[0]);
@@ -649,85 +655,53 @@
649namespace655namespace
650{656{
651 void realtime_compositor_thread(mc::SwitchingBundle &bundle,657 void realtime_compositor_thread(mc::SwitchingBundle &bundle,
658 unsigned long frames,
652 std::atomic<bool> &done)659 std::atomic<bool> &done)
653 {660 {
654 while (!done)661 std::this_thread::sleep_for(std::chrono::milliseconds(1000));
662
663 for (unsigned long frame = 0; frame < frames; frame++)
655 {664 {
656 auto buf = bundle.compositor_acquire();665 std::this_thread::sleep_for(std::chrono::milliseconds(100));
657 sleep_one_frame();666
667 auto buf = bundle.compositor_acquire(frame);
658 bundle.compositor_release(buf);668 bundle.compositor_release(buf);
659 }669 }
670 done.store(true);
660 }671 }
661}672}
662673
663TEST_F(SwitchingBundleTest, client_framerate_matches_compositor)674TEST_F(SwitchingBundleTest, client_framerate_matches_compositor)
664{675{
665 const int expected =
666 std::chrono::duration_cast<std::chrono::microseconds>(frame_time)
667 .count();
668
669 int nframes = 0;
670 int nhiccups = 0;
671
672 for (int nbuffers = 2; nbuffers <= 3; nbuffers++)676 for (int nbuffers = 2; nbuffers <= 3; nbuffers++)
673 {677 {
674 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);678 mc::SwitchingBundle bundle(nbuffers, allocator, basic_properties);
679 unsigned long client_frames = 0;
680 const unsigned long compose_frames = 20;
675681
676 bundle.allow_framedropping(false);682 bundle.allow_framedropping(false);
677683
678 std::atomic<bool> done;684 std::atomic<bool> done(false);
679 done = false;
680685
681 std::thread monitor1(realtime_compositor_thread,686 std::thread monitor1(realtime_compositor_thread,
682 std::ref(bundle), std::ref(done));687 std::ref(bundle),
683 std::thread monitor2(realtime_compositor_thread,688 compose_frames,
684 std::ref(bundle), std::ref(done));689 std::ref(done));
685 std::thread monitor3(realtime_compositor_thread,690
686 std::ref(bundle), std::ref(done));691 bundle.client_release(bundle.client_acquire());
687692
688 for (int attempt = 0; attempt < 2; attempt++)693 while (!done.load())
689 {694 {
690 // Initial queue filling is not throttled...695 bundle.client_release(bundle.client_acquire());
691 for (int f = 0; f < nbuffers + 1; f++)696 client_frames++;
692 bundle.client_release(bundle.client_acquire());697 std::this_thread::yield();
693
694 auto prev = std::chrono::high_resolution_clock::now();
695
696 for (int second = 0; second < 2; second++)
697 {
698 for (int frame = 0; frame < frame_rate; frame++)
699 {
700 bundle.client_release(bundle.client_acquire());
701
702 auto t = std::chrono::high_resolution_clock::now();
703 auto d = t - prev;
704 prev = t;
705
706 int measured_frame_time_usec =
707 std::chrono::duration_cast<std::chrono::microseconds>(d)
708 .count();
709
710 nframes++;
711 if (expected * 0.7f > measured_frame_time_usec ||
712 expected * 1.3f < measured_frame_time_usec)
713 {
714 nhiccups++;
715 }
716 }
717 }
718
719 // Simulate a pause/resume like VT switching
720 bundle.force_requests_to_complete();
721 }698 }
722699
723 done = true;
724
725 monitor1.join();700 monitor1.join();
726 monitor2.join();
727 monitor3.join();
728701
729 int hiccups_percent = nhiccups * 100 / nframes;702 // Roughly compose_frames == client_frames within 50%
730 ASSERT_LT(hiccups_percent, 10);703 ASSERT_GT(client_frames, compose_frames / 2);
704 ASSERT_LT(client_frames, compose_frames * 3 / 2);
731 }705 }
732}706}
733707
734708
=== modified file 'tests/unit-tests/compositor/test_temporary_buffers.cpp'
--- tests/unit-tests/compositor/test_temporary_buffers.cpp 2013-08-09 01:37:53 +0000
+++ tests/unit-tests/compositor/test_temporary_buffers.cpp 2013-08-29 09:10:29 +0000
@@ -54,7 +54,7 @@
5454
55 ON_CALL(*mock_bundle, client_acquire())55 ON_CALL(*mock_bundle, client_acquire())
56 .WillByDefault(Return(mock_buffer));56 .WillByDefault(Return(mock_buffer));
57 ON_CALL(*mock_bundle, compositor_acquire())57 ON_CALL(*mock_bundle, compositor_acquire(_))
58 .WillByDefault(Return(mock_buffer));58 .WillByDefault(Return(mock_buffer));
59 }59 }
6060
@@ -92,12 +92,12 @@
92TEST_F(TemporaryBuffersTest, compositor_buffer_acquires_and_releases)92TEST_F(TemporaryBuffersTest, compositor_buffer_acquires_and_releases)
93{93{
94 using namespace testing;94 using namespace testing;
95 EXPECT_CALL(*mock_bundle, compositor_acquire())95 EXPECT_CALL(*mock_bundle, compositor_acquire(_))
96 .WillOnce(Return(mock_buffer));96 .WillOnce(Return(mock_buffer));
97 EXPECT_CALL(*mock_bundle, compositor_release(_))97 EXPECT_CALL(*mock_bundle, compositor_release(_))
98 .Times(1);98 .Times(1);
9999
100 mc::TemporaryCompositorBuffer proxy_buffer(mock_bundle);100 mc::TemporaryCompositorBuffer proxy_buffer(mock_bundle, 0);
101}101}
102102
103TEST_F(TemporaryBuffersTest, snapshot_buffer_acquires_and_releases)103TEST_F(TemporaryBuffersTest, snapshot_buffer_acquires_and_releases)
104104
=== modified file 'tests/unit-tests/surfaces/test_surface.cpp'
--- tests/unit-tests/surfaces/test_surface.cpp 2013-08-09 01:37:53 +0000
+++ tests/unit-tests/surfaces/test_surface.cpp 2013-08-29 09:10:29 +0000
@@ -308,7 +308,7 @@
308 ms::Surface surf(mock_basic_state, mock_buffer_stream, std::shared_ptr<mi::InputChannel>());308 ms::Surface surf(mock_basic_state, mock_buffer_stream, std::shared_ptr<mi::InputChannel>());
309 auto buffer_resource = std::make_shared<mtd::StubBuffer>();309 auto buffer_resource = std::make_shared<mtd::StubBuffer>();
310310
311 EXPECT_CALL(*mock_buffer_stream, lock_compositor_buffer())311 EXPECT_CALL(*mock_buffer_stream, lock_compositor_buffer(_))
312 .Times(AtLeast(1))312 .Times(AtLeast(1))
313 .WillOnce(Return(buffer_resource));313 .WillOnce(Return(buffer_resource));
314314
315315
=== modified file 'tests/unit-tests/surfaces/test_surface_stack.cpp'
--- tests/unit-tests/surfaces/test_surface_stack.cpp 2013-08-26 03:00:33 +0000
+++ tests/unit-tests/surfaces/test_surface_stack.cpp 2013-08-29 09:10:29 +0000
@@ -69,7 +69,8 @@
69public:69public:
70 virtual std::shared_ptr<mg::Buffer> client_acquire() { return std::shared_ptr<mg::Buffer>(); }70 virtual std::shared_ptr<mg::Buffer> client_acquire() { return std::shared_ptr<mg::Buffer>(); }
71 virtual void client_release(std::shared_ptr<mg::Buffer> const&) {}71 virtual void client_release(std::shared_ptr<mg::Buffer> const&) {}
72 virtual std::shared_ptr<mg::Buffer> compositor_acquire(){ return std::shared_ptr<mg::Buffer>(); };72 virtual std::shared_ptr<mg::Buffer> compositor_acquire(unsigned long)
73 { return std::shared_ptr<mg::Buffer>(); };
73 virtual void compositor_release(std::shared_ptr<mg::Buffer> const&){}74 virtual void compositor_release(std::shared_ptr<mg::Buffer> const&){}
74 virtual std::shared_ptr<mg::Buffer> snapshot_acquire(){ return std::shared_ptr<mg::Buffer>(); };75 virtual std::shared_ptr<mg::Buffer> snapshot_acquire(){ return std::shared_ptr<mg::Buffer>(); };
75 virtual void snapshot_release(std::shared_ptr<mg::Buffer> const&){}76 virtual void snapshot_release(std::shared_ptr<mg::Buffer> const&){}

Subscribers

People subscribed via source and target branches