Mir

Merge lp:~mir-team/mir/touchspot-renderable into lp:mir

Proposed by Robert Carr
Status: Merged
Approved by: Cemil Azizoglu
Approved revision: no longer in the source branch.
Merged at revision: 1924
Proposed branch: lp:~mir-team/mir/touchspot-renderable
Merge into: lp:mir
Prerequisite: lp:~kdub/mir/fix-1348330
Diff against target: 3585 lines (+2202/-95)
77 files modified
debian/control (+2/-2)
debian/libmirplatform3.install (+1/-1)
include/platform/mir/graphics/platform.h (+3/-0)
include/platform/mir/options/configuration.h (+1/-0)
include/server/mir/default_server_configuration.h (+5/-2)
include/server/mir/input/cursor_listener.h (+2/-2)
include/server/mir/input/touch_visualizer.h (+6/-2)
platform-ABI-sha1sums (+2/-2)
playground/demo-shell/demo_compositor.cpp (+6/-1)
playground/demo-shell/demo_renderer.cpp (+8/-3)
playground/demo-shell/demo_renderer.h (+7/-1)
server-ABI-sha1sums (+5/-4)
src/include/platform/mir/graphics/buffer_writer.h (+44/-0)
src/include/platform/mir/graphics/native_platform.h (+3/-0)
src/include/server/mir/compositor/scene_element.h (+4/-0)
src/include/server/mir/input/scene.h (+23/-8)
src/include/server/mir/scene/legacy_scene_change_notification.h (+2/-0)
src/include/server/mir/scene/observer.h (+4/-0)
src/platform/CMakeLists.txt (+1/-1)
src/platform/graphics/android/CMakeLists.txt (+1/-0)
src/platform/graphics/android/android_buffer_writer.cpp (+70/-0)
src/platform/graphics/android/android_buffer_writer.h (+50/-0)
src/platform/graphics/android/android_display.cpp (+1/-1)
src/platform/graphics/android/android_platform.cpp (+6/-0)
src/platform/graphics/android/android_platform.h (+1/-0)
src/platform/graphics/mesa/CMakeLists.txt (+1/-0)
src/platform/graphics/mesa/buffer_allocator.cpp (+1/-1)
src/platform/graphics/mesa/buffer_writer.cpp (+40/-0)
src/platform/graphics/mesa/buffer_writer.h (+43/-0)
src/platform/graphics/mesa/native_platform.cpp (+5/-0)
src/platform/graphics/mesa/native_platform.h (+1/-0)
src/platform/graphics/mesa/platform.cpp (+6/-0)
src/platform/graphics/mesa/platform.h (+1/-0)
src/platform/graphics/mesa/shm_buffer.cpp (+13/-0)
src/platform/graphics/mesa/shm_buffer.h (+2/-0)
src/platform/options/default_configuration.cpp (+3/-1)
src/platform/symbols.map (+2/-1)
src/server/graphics/default_configuration.cpp (+10/-0)
src/server/graphics/nested/nested_platform.cpp (+5/-0)
src/server/graphics/nested/nested_platform.h (+1/-0)
src/server/input/CMakeLists.txt (+1/-0)
src/server/input/android/android_input_registrar.cpp (+4/-0)
src/server/input/android/android_input_registrar.h (+1/-0)
src/server/input/android/android_input_target_enumerator.cpp (+4/-4)
src/server/input/android/android_input_target_enumerator.h (+3/-3)
src/server/input/android/input_sender.cpp (+9/-5)
src/server/input/android/input_sender.h (+1/-0)
src/server/input/cursor_controller.cpp (+8/-3)
src/server/input/cursor_controller.h (+3/-3)
src/server/input/default_configuration.cpp (+16/-10)
src/server/input/touchspot_controller.cpp (+166/-0)
src/server/input/touchspot_controller.h (+77/-0)
src/server/input/touchspot_image.c (+1034/-0)
src/server/scene/basic_surface.cpp (+0/-1)
src/server/scene/default_configuration.cpp (+2/-2)
src/server/scene/legacy_scene_change_notification.cpp (+5/-0)
src/server/scene/surface_stack.cpp (+78/-0)
src/server/scene/surface_stack.h (+16/-3)
src/server/symbols.map (+4/-1)
tests/acceptance-tests/test_nested_mir.cpp (+6/-1)
tests/acceptance-tests/test_touchspot_visualization.cpp (+2/-0)
tests/include/mir_test_doubles/null_platform.h (+7/-2)
tests/include/mir_test_doubles/stub_input_scene.h (+16/-5)
tests/include/mir_test_doubles/stub_scene_element.h (+5/-0)
tests/include/mir_test_doubles/stub_touch_visualizer.h (+6/-0)
tests/integration-tests/input/android/test_android_cursor_listener.cpp (+1/-1)
tests/integration-tests/input/android/test_android_input_manager.cpp (+1/-1)
tests/integration-tests/input/test_nested_input.cpp (+1/-1)
tests/mir_test_framework/stubbed_server_configuration.cpp (+13/-0)
tests/unit-tests/frontend/test_session_mediator.cpp (+1/-0)
tests/unit-tests/graphics/mesa/test_shm_buffer.cpp (+1/-1)
tests/unit-tests/graphics/nested/test_nested_platform.cpp (+5/-0)
tests/unit-tests/input/CMakeLists.txt (+1/-0)
tests/unit-tests/input/android/test_android_input_target_enumerator.cpp (+5/-4)
tests/unit-tests/input/test_cursor_controller.cpp (+12/-11)
tests/unit-tests/input/test_touchspot_controller.cpp (+199/-0)
tests/unit-tests/scene/test_surface_stack.cpp (+96/-0)
To merge this branch: bzr merge lp:~mir-team/mir/touchspot-renderable
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Daniel van Vugt Needs Fixing
Andreas Pokorny (community) Approve
Alberto Aguirre (community) Approve
Kevin DuBois (community) Approve
Cemil Azizoglu (community) Approve
Review via email: mp+230555@code.launchpad.net

This proposal supersedes a proposal from 2014-07-30.

Commit message

Add touchspot visualizations toggleable with --enable-touchspots

Description of the change

Add touchspot visualizations toggleable with --enable-touchspots, a runtime configuration method will be added at the USC level.

A humble attempt at a review guide, beginning with comments on the implementation (1, 2):

1. A lot of the diff size comes from touchspot_image.c .I feel that the actual cost from this is minimal and its better than implementing/copy-pasting an anti-aliased circle drawing algorithm. I think I would prefer to implement the drawing algorthmically using libpixman, but there has been some resistance in the past.

2. The core class is TouchspotController (implements TouchVisualizer) (touchspot_controller.cpp). TouchspotController implements a bespoke interface out of android-input (see droidinput::PointerController, and src/server/input/android_android/pointer_controller.cpp). TouchspotController responds to an instantaneous list of touchpoints (that is to say is not responsible for touch state tracking) and maintains an internal set of Renderables which it places at appropriate positions in the scene.

It's come up, should TouchspotController really use a bespoke interface for touch visualization or instead function as a server input filter. I'll give a few reasons why I've chosen this path (a, b, c):

a. Test guidance: There are two tests which guide towards the bespoke interface. First the test which expresses that device touches result in invocation of the TouchspotController. The TouchVisualizer interface allows this to be tested without involving the unrelated parts of MirEvent, it also allows for testing of the touch-visualization loop independent of the TouchspotController, helping solve a problem under test for shells which desire alternate implementations.
b. Reduction of domain: The TouchVisualizer is not interested in key events, the ability to accept/reject events, or a host of other things the InputFilter offers.
c. Decoupling from dispatch loop: The TouchVisualizer (through droidinput::PointerController) operates at the level of the InputReader. Given that it may never consume input events, there is no need for it to exist as part of the dispatch loop where it can stall a greater portion of the server event stream (due to say lock contention on the scene).

Moving on to some comments about the assorted server changes:

1. DemoRenderer requires modification in order to not render decorations on the touchspots. Ultimately I think the overridden ::begin interface is pretty strange...but its not any worse than the existing code. This little hack exposes a wart of DemoRenderer I had yet to notice...it implements mg::Renderer but no one consumes it through this interface.)prop
2. SurfaceStack extended with add/remove input_visualization. Ideally this would use a more scenegraphy style approach...not requiring bespoke methods for input visualizations (this interface is appropriate for touchspots, and then cursors). Changing add_surface/remove_surface to be add_renderable/remove_renderable is not a trivial task though, in particular due to the nature of SurfaceObservers (observing a superset of renderable properties) I estimated that this would add a couple thousand more lines to the diff. Ultimately this method is useful for multiple consumers (touchspot, cursor) and easy to verify (see changes in test_surface_stack) so I decided it had a certain pragmatic elegance.
3. SceneObserver extended with scene_changed, SurfaceStack extended with emit_scene_changed. It's not possible for the TouchspotRenderables to use the SurfaceObserver interface, and so an interface to notify the compositor the renderables have been added/removed/moved is required. In order for the TouchspotRenderable to use the the same interface as SurfaceObservation a few changes would be required. Notably the point at which surface observers are installed (SceneObserver:surface_added/removed) would need to work through a common base interface (presumably mg::Renderable or mc::SceneElement). Then, the SurfaceObserver interface itself would need trimming down, some methods are inappropriate for non surface renderables, i.e. SurfaceAttributes. Actually! If we wish to enforce the notion that the "scene" is a complete representation of the visual output, the SurfaceObserver needs trimming down anyway, the compositor should not be responding directly to a MirSurfaceAttrib change, rather the shell should respond and make changes to directly render-able attributes (i.e. size...) triggering recomposition. This suggests that two interfaces are warranted: mir::shell::SurfaceObserver and mir::compositor::(SceneElement/Renderable)Observer . I estimated this as another 2000 lines or so of diff though, and likely to cause some controversy, so I don't really want to open it up in this mp.
4. mi::InputTargets renamed to mi::Scene, with the addition of add/remove input_visualization and emit_scene_changed I think this is an obvious choice.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

At a quick glance, the things making this a 3685 line proposal actually don't need to be here...

(1) server-ABI-sha1sums: Changes to the ordering of this file are unreviewable (can't tell if things have been deleted or just moved). Please either keep the existing ordering or propose a re-ordering separately as a pre-req.

(2) touchspot_image.c: Obviously big as text. I think we can do better by generating this texture algorithmically. Not a blocker but I might do a proof-of-concept to demonstrate...

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

(3) Unused #includes and whitespace changes can be removed:
src/server/compositor/temporary_buffers.cpp
src/server/compositor/temporary_buffers.h

(4) src/platform/graphics/android/android_buffer_writer.cpp
Hmm, I'm wondering if we should have already abstracted software buffers on the server side so you don't need to write platform-specific code like this.

(5) A touchspot size of 64px is probably too small for high-res displays. If you're actually touching the display then it would be helpful for the touchspot to not be so small that it's completely hidden behind a finger. Consider making the Renderable rectangle dimensions independent of the buffer dimensions. OpenGL will scale for you.

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

(1) server-ABI-sha1sums: Changes to the ordering of this file are unreviewable (can't tell if things have been deleted or just moved). Please either keep the existing ordering or propose a re-ordering separately as a pre-req.

Proposed reoredering as prereq.

(3) Unused #includes and whitespace changes can be removed:
src/server/compositor/temporary_buffers.cpp
src/server/compositor/temporary_buffers.h

Fixed! Thanks.

>> (4) src/platform/graphics/android/android_buffer_writer.cpp
>> Hmm, I'm wondering if we should have already abstracted software buffers on the server side so you
>> don't need to write platform-specific code like this.

You mean something like a generic version of the mesa shm_buffer? At one point I was thinking about something like this...but this way should be faster on platforms like android with HWC which allow generic buffer overlay.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

needed?:
639 + auto mga_buffer = std::dynamic_pointer_cast<mga::Buffer>(buffer);
640 + if (!mga_buffer)
641 + BOOST_THROW_EXCEPTION(std::logic_error("Invalid buffer (did not originate from platform graphics driver)"));

could there be stronger typing than void*?
void mga::AndroidBufferWriter::write(std::shared_ptr<mg::Buffer> const& buffer, void const* data, size_t size)

overlay is a bit overloaded already, maybe just add_cursor_renderable()?
2824 + void add_overlay(std::shared_ptr<graphics::Renderable> const& overlay);
2825 + void remove_overlay(std::weak_ptr<graphics::Renderable> const& overlay);

const&
643 + auto handle = buffer->native_buffer_handle();

we shouldn't be adding this to Renderable without rejecting all 'decorated' renderables down in the hwc code. This function makes the RenderableList indeterminate in terms of what would appear on the screen. It says it should be decorated but doesn't say what this entails.
165 + virtual bool should_be_decorated() const = 0;

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

> You mean something like a generic version of the mesa shm_buffer? At one point
> I was thinking about something like this...but this way should be faster on
> platforms like android with HWC which allow generic buffer overlay.

That's interesting. GBM also allows overlays (bypass) of software buffers. However when I enabled it, the performance was worse, which is quite reasonable to expect but is driver-dependent too. Maybe Android would also benefit from intentionally disallowing overlaying of buffers that reside in CPU memory... Although if the CPU/GPU memory is shared then theoretically there should be no performance disadvantage to overlaying software buffers.

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

Alright my blocking concern (1) is fixed. Please consider issues (2)-(5) still.

review: Abstain
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

needed?:
639 + auto mga_buffer = std::dynamic_pointer_cast<mga::Buffer>(buffer);
640 + if (!mga_buffer)
641 + BOOST_THROW_EXCEPTION(std::logic_error("Invalid buffer (did not originate from platform graphics driver)"));

Yeah...kind of strange I guess, just using static cast.

>> could there be stronger typing than void*?
>> void mga::AndroidBufferWriter::write(std::shared_ptr<mg::Buffer> const& buffer, void const* data, >> size_t size)

Using unsigned char now or did you mean something that encodes the pixel format?

>> overlay is a bit overloaded already, maybe just add_cursor_renderable()?
>> 2824 + void add_overlay(std::shared_ptr<graphics::Renderable> const& overlay);
>> 2825 + void remove_overlay(std::weak_ptr<graphics::Renderable> const& overlay);

How about "input_visualization"

>> const&
>> 643 + auto handle = buffer->native_buffer_handle();

Fixed

>> we shouldn't be adding this to Renderable without rejecting all 'decorated' renderables down in >> the hwc code. This function makes the RenderableList indeterminate in terms of what would appear >> on the screen. It says it should be decorated but doesn't say what this entails.
>> 165 + virtual bool should_be_decorated() const = 0;

I'm not sure the renderables should be / need to be rejected. If a shell wants to draw decorations then it is responsible for recognizing that passing the renderlist to the display buffer isn't appropriate right? So this method is really just for the shell compositor tor ecognize if the renderable is of a type which should be decorated. I agree it's strange...but I don't know how to do anything better without decorations expressed in the scene.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> needed?:
> 639 + auto mga_buffer = std::dynamic_pointer_cast<mga::Buffer>(buffer);
> 640 + if (!mga_buffer)
> 641 + BOOST_THROW_EXCEPTION(std::logic_error("Invalid buffer (did not
> originate from platform graphics driver)"));
>
> Yeah...kind of strange I guess, just using static cast.
>
> >> could there be stronger typing than void*?
> >> void mga::AndroidBufferWriter::write(std::shared_ptr<mg::Buffer> const&
> buffer, void const* data, >> size_t size)
>
> Using unsigned char now or did you mean something that encodes the pixel
> format?
>
> >> overlay is a bit overloaded already, maybe just add_cursor_renderable()?
> >> 2824 + void add_overlay(std::shared_ptr<graphics::Renderable> const&
> overlay);
> >> 2825 + void remove_overlay(std::weak_ptr<graphics::Renderable> const&
> overlay);
>
> How about "input_visualization"
>
>
> >> const&
> >> 643 + auto handle = buffer->native_buffer_handle();
>
> Fixed
>
> >> we shouldn't be adding this to Renderable without rejecting all 'decorated'
> renderables down in >> the hwc code. This function makes the RenderableList
> indeterminate in terms of what would appear >> on the screen. It says it
> should be decorated but doesn't say what this entails.
> >> 165 + virtual bool should_be_decorated() const = 0;
>
> I'm not sure the renderables should be / need to be rejected. If a shell wants
> to draw decorations then it is responsible for recognizing that passing the
> renderlist to the display buffer isn't appropriate right? So this method is
> really just for the shell compositor tor ecognize if the renderable is of a
> type which should be decorated. I agree it's strange...but I don't know how to
> do anything better without decorations expressed in the scene.

The problem is really that:
mg::DisplayBuffer::post_renderables_if_optimizable() has the contract of either rejecting the list as whole, or painting exactly what is contained in the list. The addition of should_be_decorated() throws a big wrench in that contract because the implementer doesn't know what to paint correctly if should_be_decorated() returns true.

This also drives at the conversation in lp:~kdub/mir/prep-for-1348330. The compositors wants to do something different if this is a 'input visualization'. So, a decent compromise to me seems to be:
bool is_a_input_visualization()
instead of
bool should_be_decorated().
That way, the RenderableList remains definite, and can leave it up to the compositors as to what they want to do with the visualization.

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

I think it's safe to say that demo-shell's decorations are a proof of concept that may change dramatically in the case of "everything's in the scene graph".

A scenegraph may exist in memory or in run-time recursion structure (at present, also used in Compiz). If the scenegraph moves to the former then should_be_decorated() wouldn't exist.

At the same time, should_be_decorated() probably shouldn't exist as it will be superseded by improved surface dimension info, that's been started but not finished yet:
  https://code.launchpad.net/~vanvugt/mir/clarify-surface-size-pos/+merge/218578

That said, should_be_decorated() is simple enough that it's easy to drop when and if we're ready.

I suspect we can do better than the way post_renderables_if_optimizable() is designed right now, but until something better is proposed we should try to not block the overlays effort.

Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

should_be_decorated->is_a_surface

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

I guess, still 'needs fixing', as the "is_a_surface" still has no context down within the mg::DisplayBuffer::post_renderables_if_optimizable function. Like, what should the display buffer do if this function returns false? "can hwc draw non-surfaces?" has an ambiguous answer.

In my estimation, mg::Renderable should just be a basic list of squares, the traditional information needed for blitting. A RenderableList should give a defined, specific picture that can be drawn.
I don't mind SceneElement gaining information that's specific to the scene, but Renderable should remain a simple list of squares.

Just for future planning, I think that some of this conflict is just because the name 'Renderable' is liked quite a lot. Perhaps we should rename the stuff down in the compositor BlitSquares, and then the Renderable/SceneElements can expand in whichever ways they need to, without dragging the platform display buffers (and the HWC implementation) along for the ride.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote : Posted in a previous version of this proposal

Kevin: Moved is_a_surface to scene element. Chose is_a_surface over is_an_input_visualization to avoid the term input_visualization sticking (im not that hot on it).

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Per previous discussions (in kdub's proposals I think?) any logic specific to how demo shell does decorations will likely need to be rewritten and/or removed in future as proper window management takes shape. And I think we're already landing too much code that apparently has a short lifespan.

Between that and my previous comments above, Abstain.

review: Abstain
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

#1
86 + void begin(std::unordered_set<graphics::Renderable::ID> &&renderables_not_to_decorate) const;

I think its a bit more flexible not to force the use of the rvalue.
void begin(std::unordered_set<graphics::Renderable::ID> renderables_not_to_decorate) const;

begin(std::move(a)) would still use the move constructor

#2
193 + virtual std::shared_ptr<BufferWriter> create_buffer_writer() = 0;
I had to change to make_* over in my MP :)
<side note> I think that the "display stuff" should get split out of Platform into its own interface to get rid of NativePlatform.

#3
167 + virtual void write(std::shared_ptr<Buffer> const& buffer, unsigned char const* data, size_t size) = 0;

A continuation from the superseded discussion, but a char* and a size seems like it puts more burden on the caller of the interface to make sure that raw data in the char* matches what the buffer expects. (An example of this is line 1059 where we throw if the size is incorrect) The ideal is probably to see something like:
write(Buffer&, std::vector<Pixels>)
where the write function figures out how to get the pixels into that buffer (adjust for stride, format differences, etc etc)

#4
711 + auto mga_buffer = std::static_pointer_cast<mga::Buffer>(buffer);
needs removal.
Somewhat related, but write() could use a Buffer& instead of a shared_ptr<Buffer>

#5
716 + int usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
minor point, but we just need SW_WRITE_OFTEN

#6
696 +mga::AndroidBufferWriter::AndroidBufferWriter()
We recreate the gralloc module in the constructor here, could reuse a single instance.

#7
698 + int err;
699 +
could use auto and get rid of these lines

#8
963 +
2701
whitespace introduction

#9
The 64x64x4 still increases mir's memory and installation footprint a fair amount, maybe we could programatically create a smaller image?

Revision history for this message
Kevin DuBois (kdub) wrote :

okay, so structurally, much better.

I think
#1,2,4,5,7,8
are my 'needs fixings'

and the rest are just suggestions

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Kevin. Thanks for review :) Getting to your comments asap.

Reflected some on the configuration requirements with Anpok this morning. In particular autopilot would like to runtime enable/disable the visualization via IPC. I considered a mirclient function but we lack the necessary infrastructure, i.e.

mir_input_device_enable_touch_visualization could make sense if we supported some sort of client MirInputDevice enumeration.

For now ( some sort of client InputDevice enumeration is available) I have landed on the com.canonical.Unity.Screen DBus interface in USC. USC MP incoming soon.

In order to support this without awkward usage of mir options in USC or exposing the touchspot controller implementation I have added enable/disable methods to the TouchVisualizer interface and ported the default server configuration to use this mechanism for the static touchspot option.

Revision history for this message
Robert Carr (robertcarr) wrote :

kdub 1. Fixed rvalue usage...still not used to move semantics I guess.
2. Aha good call
3. It seems like we really need a Pixels(Array, Size, PixelFormat) kind of type...not for this MP though I think.
4, 5: Good call.
6: Hmm I kind of have the thought that I like it more this way so people can just construct it without getting in to the game of who owns the dependencies. On the other hand its not clear that hiding the depdency in the constructor is really correct. I think you could make an argument for it though in that the gralloc module is effectively a system resource...*shrug* I dont have a strong enough opinion to change it really but maybe someone else will comment.
7, 8: Fixed
9: I've thought about it...the problem is effective circle anti-aliasing algorithms are more than a few dozen that lines long...at which point the question starts to become, should we link in pixman? etc...to which there has been a little resistance in the past so I didn't want to dredge up again.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

Interesting it looks like one of the jenkins jobs missed r1847...ah the perils of real time.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

Not a complete review yet, just some first notes:

162 +class BufferWriter

At first glance it would be more natural to introduce a Buffer::write() method instead of a class that acts on the buffer, unless we want to potentially support multiple implementations of it.

1577 +void mi::TouchspotController::visualize_touches(std::vector<Spot> const& touches)

Perhaps the logic in this method would be more clear if we split it out into different stages, e.g.:

1. grow touchpot renderable vector as needed (already there)
2. for each touch: set up and add renderable to scene
3. for unused renderables: remove from scene

1618 + scene->emit_scene_changed();

We should call this out of lock if possible.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

Why are the touchspots not rendered with just GL draw commands?

Why the need for raw RGB data?

review: Needs Information
Revision history for this message
Robert Carr (robertcarr) wrote :

write/BufferWriter discussed in standup. Calling scene->emit_scene_changed out of lock now.

Will think if visualize touches can be cleared up.

>>
>> Why are the touchspots not rendered with just GL draw commands?
>> Why the need for raw RGB data?
>>

It seems to me that RGB data is simpler in every way except for polluting the launchpad diff. No worry about anti-aliasing approaches, no dealing with GL contexts, etc...

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

touch_visualizer.h should be in the public headers as the USC branch that makes use of this feature will use it.

review: Needs Fixing
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

556 + if (buffer.stride().as_uint32_t() * buffer_size.height.as_uint32_t() != size)
557 + BOOST_THROW_EXCEPTION(std::logic_error("Size of pixels is not equal to size of buffer"));

You should just do a line by line copy. You'll be excluding devices with stride.

review: Needs Fixing
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

1362 + void move_to(geom::Point pos)
1363 + {
1364 + std::lock_guard<std::mutex> lg(guard);
1365 + position = pos;
1366 + }

The position should either represent the centroid of the buffer, or it should be translated so that the renderable position centroid is the position given.

Othewise, the touchspots look like they are offset from the touch location.

review: Needs Fixing
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

With overlays enabled in an android based device, for a device say with 4 overlay layers..

It only renders 3/4 simultaneous touch-spots but the other client surfaces are not getting rendered.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

touchspot_controller.cpp:
 + nits: a lot of additional whitespace ..
 + unsure: from what interfaces it needs it feels more like belonging to scene maybe?
 + needs fixing: visualize_touches will benefit a lot from extracting the three steps inside the mutex block into separate methods, and you could remove some of the comments then
 + needs fixing: touch spot render ables should be centered around the spots

I might have missed the rationale behind it, because looking at how buffer writer is looks like an alternative buffer allocator/constructor function. Especially looking at the behavior - new buffer must match the old buffer in size...?

Nit: mgm::BufferWriter::write should throw std::invalid_argument when no shm buffer is supplied.

So this is a needs information with two small needs fixing.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Thanks!

Republished header.
Fixed touchspot centroid.
Made stride copy line by line.l
Overlay issue revealed to be unrelated.
Will clean up visualize_touches in the next hour or so.
Will reflect on moving touchspot_controller to scene, and continue to reflect on BufferWriter.

Revision history for this message
Robert Carr (robertcarr) wrote :

I found it pretty difficult to refactor visualize_touches...

Splitting out functions seemed only to introduce obscure function names that further impaired readability, e.g.

ensure_renderable_pool_has_size_locked, etc...

I've added a textual description of the spot->renderable assignment algorithm in the hopes that this helps?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

sryy,but i meant something trivial like:

1441 + {
1442 + std::lock_guard<std::mutex> lg(guard);
1443 +
1444 + if (!enabled)
1445 + {
1446 + remove_touchspot_renderables();
1454 + return;
1455 + }
1456 +
1457 + grow_touchspot_renderables(touches.size());
1461 +
1462 + update_touchspot_renderables(touches);
1487 + }
1488 +
1489 + // TODO (hackish): We may have just moved renderables which with the current
1490 + // architecture of surface observers will not trigger a propagation to the
1491 + // compositor damage callback we need this "emit_scene_changed".
1492 + scene->emit_scene_changed();

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> I found it pretty difficult to refactor visualize_touches...
>
> Splitting out functions seemed only to introduce obscure function names that further impaired readability, e.g.

I think that, as a first step at least, moving the operations out of a single, big loop will help, and then we can more easily extract to separate functions if we think it will provide gain in readability. For example (code tested with unit tests):

> 1. grow touchpot renderable vector as needed (already there)
> 2. for each touch: set up and add renderable to scene
> 3. for unused renderables: remove from scene

unsigned int const num_touches = enabled ? touches.size() : 0;

while (touchspot_renderables.size() < num_touches)
    touchspot_renderables.push_back(std::make_shared<TouchspotRenderable>(touchspot_buffer));

// Update renderables used for touches
for (unsigned int i = 0; i < num_touches; ++i)
{
    auto const& renderable = touchspot_renderables[i];

    renderable->move_center_to(touches[i].touch_location);

    if (i >= renderables_in_use)
        scene->add_input_visualization(renderable);
}

// Update unused renderables
for (unsigned int i = num_touches; i < renderables_in_use; ++i)
    scene->remove_input_visualization(touchspot_renderables[i]);

renderables_in_use = num_touches;

Revision history for this message
Robert Carr (robertcarr) wrote :

Oh yeah thats much nicer...thanks alf.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

Pushed a bunch of random cleanup.

Reflected on mg::BufferWriter v. mg::Buffer::write, decided to keep it as is after consulting the guideline:

Prefer non-member non-friend functions.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alberto Aguirre (albaguirre) wrote :

1432 + * Copyright © 2012 Canonical Ltd.

Needs fixing: Wrong year.

1511 +++ src/server/input/touchspot_image.c

I know you already covered this, but given this is mostly a debug thing...What if we are asked to change the color...or the size...

I'd rather just have a dumb basic non-antialiased circle drawing routine (but I don't feel strongly about it so non-blocking).
    for(int y = -radius; y < radius; y++)
    {
        for(int x = -radius; x < radius; x++)
        {
            if( (x*x + y*y) <= radius_sq)
            {
                buffer.setpixel(radius + x, radius + y);
            }
        }
    }

2766 +
2767 + // Intended for input overlays, as described in mir::input::Scene documentation.
2768 + void add_input_visualization(std::shared_ptr<graphics::Renderable> const& overlay);
2769 + void remove_input_visualization(std::weak_ptr<graphics::Renderable> const& overlay);
2770 +
2771 + void emit_scene_changed() override;

I know covered already but seems like a strange interface addition for something named input::scene...But again don't feel too strongly about it since our scene interface is already wonky anyways...

review: Needs Fixing
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

Looks good to me overall.

Minor stuff :

1472 +/// of touchspot renderables for visualization. Touchspot visualization
1473 +/// and must be enabled through a call to ::enable

Incorrect sentence in comment

1003 === modified file 'src/server/input/android/android_input_target_enumerator.cpp'

Should this file be renamed to something like android_scene_enumerator.cpp to reflect the input_target --> scene change?

1037 === modified file 'src/server/input/android/android_input_target_enumerator.h'

Ditto

review: Approve
Revision history for this message
Robert Carr (robertcarr) wrote :

Updated copyright and comments.

Alberto: I agree add/remove_input_visualization is strange. I'd rather see a "layers" API but still don't know how to implement it...

Non antialiased circle would be ok if the main other use weren't screen casting where having a nice antialiased ubuntu orange circle is worth something.

Cemil:

Fixed comment.

Wrt to android_input_target_enumerator, my thought is no, as the InputDispatcher doesn't deal in terms of scene. Perhaps the most accurate name would be AndroidInputWindowHandleEnumerator but I don't think that adds much.

Revision history for this message
Kevin DuBois (kdub) wrote :

looking good!

needs-fixings:
could some of the new files be 'private'?

c-cast:
537 + usage, top, left, width, height, (void**) &vaddr) )

mir::graphics::android::AndroidBufferWriter could just be mir::graphics::android::BufferWriter

suggestions:
enable()/disable() on touch visualizer seems a bit misplaced. Could the compositor just know whether it should draw visualizations or not and then call the visualize_touches according to what it wants to do?
The BufferWriters could also have a test.

Revision history for this message
Kevin DuBois (kdub) wrote :

well, looks good to me then!

review: Approve
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

kdub's comment reminded me a couple of other things that I had in mind but had forgotten by the time I finished reviewing :-). This MP will break the server ABI no matter what but let's try to minimize our exposure :

144 === renamed file 'src/include/server/mir/input/touch_visualizer.h' => 'include/server/mir/input/touch_visualizer.h'

Can this stay private please unless you'll be changing downstreams to use this functionality right away?

1 === added file 'include/platform/mir/graphics/buffer_writer.h'

Can we make this private for now?

Since we are messging with makefiles, symbols, etc., also, can you please make sure the 3 downstreams still build? Finding them out at release time is a real PITA.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

@Cemil,

The touch_visualizer.h header will be needed by this USC branch:
https://code.launchpad.net/~mir-team/unity-system-compositor/touchspot-toggling/+merge/233742

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Cemil Azizoglu (cemil-azizoglu) wrote :

> @Cemil,
>
> The touch_visualizer.h header will be needed by this USC branch:
> https://code.launchpad.net/~mir-team/unity-system-compositor/touchspot-
> toggling/+merge/233742

O ok that's fine.

Revision history for this message
Alberto Aguirre (albaguirre) wrote :

OK.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Andreas Pokorny (andreas-pokorny) wrote :

ok

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

(6) Server ABI broken, and needs bumping due to:
include/server/mir/default_server_configuration.h
include/server/mir/input/cursor_listener.h
etc.

Although you will probably find CI fails on any server ABI bump. We need to fix bug 1293944 to get past that.

review: Needs Fixing
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
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 :

Feel free to ignore my "Needs fixing" above if it causes too much grief. So long as we remember to:
  1. Bump MIRSERVER_ABI to 26 before branching/releasing 0.8.0; and
  2. Not backport this branch or any ABI breaks to 0.7;
then we're OK.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Robert Carr (robertcarr) wrote :

Fixed text conflicts.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-09-10 12:50:53 +0000
3+++ debian/control 2014-09-18 16:04:44 +0000
4@@ -60,7 +60,7 @@
5 .
6 Contains the shared library needed by server applications for Mir.
7
8-Package: libmirplatform2
9+Package: libmirplatform3
10 Section: libs
11 Architecture: i386 amd64 armhf arm64
12 Multi-Arch: same
13@@ -123,7 +123,7 @@
14 Architecture: i386 amd64 armhf arm64
15 Multi-Arch: same
16 Pre-Depends: ${misc:Pre-Depends}
17-Depends: libmirplatform2 (= ${binary:Version}),
18+Depends: libmirplatform3 (= ${binary:Version}),
19 libmircommon-dev,
20 libboost-program-options-dev,
21 ${misc:Depends},
22
23=== renamed file 'debian/libmirplatform2.install' => 'debian/libmirplatform3.install'
24--- debian/libmirplatform2.install 2014-09-10 12:50:53 +0000
25+++ debian/libmirplatform3.install 2014-09-18 16:04:44 +0000
26@@ -1,1 +1,1 @@
27-usr/lib/*/libmirplatform.so.2
28+usr/lib/*/libmirplatform.so.3
29
30=== modified file 'include/platform/mir/graphics/platform.h'
31--- include/platform/mir/graphics/platform.h 2014-09-11 19:07:15 +0000
32+++ include/platform/mir/graphics/platform.h 2014-09-18 16:04:44 +0000
33@@ -53,6 +53,7 @@
34 class GraphicBufferAllocator;
35 class GLConfig;
36 class GLProgramFactory;
37+class BufferWriter;
38
39 enum class BufferIpcMsgType
40 {
41@@ -86,6 +87,8 @@
42
43 virtual std::shared_ptr<GraphicBufferAllocator> create_buffer_allocator(
44 std::shared_ptr<BufferInitializer> const& buffer_initializer) = 0;
45+
46+ virtual std::shared_ptr<BufferWriter> make_buffer_writer() = 0;
47
48 /**
49 * Creates the display subsystem.
50
51=== modified file 'include/platform/mir/options/configuration.h'
52--- include/platform/mir/options/configuration.h 2014-09-10 12:50:53 +0000
53+++ include/platform/mir/options/configuration.h 2014-09-18 16:04:44 +0000
54@@ -41,6 +41,7 @@
55 extern char const* const input_report_opt;
56 extern char const* const host_socket_opt;
57 extern char const* const frontend_threads_opt;
58+extern char const* const touchspots_opt;
59 extern char const* const fatal_abort_opt;
60
61 extern char const* const name_opt;
62
63=== modified file 'include/server/mir/default_server_configuration.h'
64--- include/server/mir/default_server_configuration.h 2014-09-10 12:50:53 +0000
65+++ include/server/mir/default_server_configuration.h 2014-09-18 16:04:44 +0000
66@@ -105,6 +105,7 @@
67 class BufferInitializer;
68 class DisplayReport;
69 class GraphicBufferAllocator;
70+class BufferWriter;
71 class Cursor;
72 class CursorImage;
73 class GLConfig;
74@@ -114,7 +115,7 @@
75 namespace input
76 {
77 class InputReport;
78-class InputTargets;
79+class Scene;
80 class InputManager;
81 class CompositeEventFilter;
82 class InputChannelFactory;
83@@ -214,6 +215,7 @@
84 * dependencies of compositor on the rest of the Mir
85 * @{ */
86 virtual std::shared_ptr<graphics::GraphicBufferAllocator> the_buffer_allocator();
87+ virtual std::shared_ptr<graphics::BufferWriter> the_buffer_writer();
88 virtual std::shared_ptr<compositor::Scene> the_scene();
89 virtual std::shared_ptr<compositor::FrameDroppingPolicyFactory> the_frame_dropping_policy_factory();
90 /** @} */
91@@ -291,7 +293,7 @@
92 virtual std::shared_ptr<input::InputReport> the_input_report();
93 virtual std::shared_ptr<input::CompositeEventFilter> the_composite_event_filter();
94 virtual std::shared_ptr<shell::InputTargeter> the_input_targeter();
95- virtual std::shared_ptr<input::InputTargets> the_input_targets();
96+ virtual std::shared_ptr<input::Scene> the_input_scene();
97 virtual std::shared_ptr<input::CursorListener> the_cursor_listener();
98 virtual std::shared_ptr<input::TouchVisualizer> the_touch_visualizer();
99 virtual std::shared_ptr<input::InputRegion> the_input_region();
100@@ -359,6 +361,7 @@
101 CachedPtr<graphics::NativePlatform> graphics_native_platform;
102 CachedPtr<graphics::BufferInitializer> buffer_initializer;
103 CachedPtr<graphics::GraphicBufferAllocator> buffer_allocator;
104+ CachedPtr<graphics::BufferWriter> buffer_writer;
105 CachedPtr<graphics::Display> display;
106 CachedPtr<graphics::Cursor> cursor;
107 CachedPtr<graphics::CursorImage> default_cursor_image;
108
109=== modified file 'include/server/mir/input/cursor_listener.h'
110--- include/server/mir/input/cursor_listener.h 2013-04-30 20:44:31 +0000
111+++ include/server/mir/input/cursor_listener.h 2014-09-18 16:04:44 +0000
112@@ -35,8 +35,8 @@
113
114 protected:
115 CursorListener() = default;
116- CursorListener(const CursorListener&) = delete;
117- CursorListener& operator=(const CursorListener&) = delete;
118+ CursorListener(CursorListener const&) = delete;
119+ CursorListener& operator=(CursorListener const&) = delete;
120 };
121
122 }
123
124=== renamed file 'src/include/server/mir/input/touch_visualizer.h' => 'include/server/mir/input/touch_visualizer.h'
125--- src/include/server/mir/input/touch_visualizer.h 2014-09-10 12:50:53 +0000
126+++ include/server/mir/input/touch_visualizer.h 2014-09-18 16:04:44 +0000
127@@ -39,11 +39,15 @@
128 {
129 geometry::Point touch_location;
130
131- // If pressure is non-zero, it indicates a press at the spot, as
132- // opposed to a hover.
133+ // If pressure is zero, the touch-point can be interpreted as a hover.
134 float pressure;
135 };
136
137+ // Toggle visualization of touches
138+ virtual void enable() = 0;
139+ virtual void disable() = 0;
140+
141+ // Visualize a given set of touches statelessly.
142 virtual void visualize_touches(std::vector<Spot> const& touches) = 0;
143
144 protected:
145
146=== modified file 'platform-ABI-sha1sums'
147--- platform-ABI-sha1sums 2014-09-12 09:03:19 +0000
148+++ platform-ABI-sha1sums 2014-09-18 16:04:44 +0000
149@@ -31,9 +31,9 @@
150 979d2c1ac723ccef538d9a378228a02b0f173bd7 include/platform/mir/graphics/graphic_buffer_allocator.h
151 f90a35371e236a6cfec8e9a8474dbb3305c7621e include/platform/mir/graphics/internal_client.h
152 c9730cac4a3a101f9706ec6f444958abe047fd88 include/platform/mir/graphics/internal_surface.h
153-656a7e1ae3b246930431a6174526fbdc2c76649e include/platform/mir/graphics/platform.h
154+c775727ea15fd8affa5b4dc9cd226d782e436001 include/platform/mir/graphics/platform.h
155 15f201741a465de33e55ffc1ea775b507a5be950 include/platform/mir/graphics/renderable.h
156-b0014e8c4f44f831c9d178f995efb172417aaee4 include/platform/mir/options/configuration.h
157+f5746dab3336266cfd410ce4e4d01333df6e5b99 include/platform/mir/options/configuration.h
158 47007c783c174f8e94d332c4b13c6b01358b48fb include/platform/mir/options/default_configuration.h
159 b45f14082c4f8b29efaa1b13de795dcb29deb738 include/platform/mir/options/option.h
160 3c37cc31e8b290b89c311d82f02e07d342766451 include/platform/mir/options/program_option.h
161
162=== modified file 'playground/demo-shell/demo_compositor.cpp'
163--- playground/demo-shell/demo_compositor.cpp 2014-09-10 12:50:53 +0000
164+++ playground/demo-shell/demo_compositor.cpp 2014-09-18 16:04:44 +0000
165@@ -66,6 +66,8 @@
166 //the elements should be notified if they are rendered or not
167 bool nonrenderlist_elements{false};
168 mg::RenderableList renderable_list;
169+ std::unordered_set<mg::Renderable::ID> decoration_skip_list;
170+
171 auto elements = scene->scene_elements_for(this);
172 for(auto const& it : elements)
173 {
174@@ -73,6 +75,9 @@
175 auto const& view_area = display_buffer.view_area();
176 auto embellished = renderer.would_embellish(*renderable, view_area);
177 auto any_part_drawn = (view_area.overlaps(renderable->screen_position()) || embellished);
178+
179+ if (!it->is_a_surface())
180+ decoration_skip_list.insert(renderable->id());
181 if (renderable->visible() && any_part_drawn)
182 {
183 renderable_list.push_back(renderable);
184@@ -96,7 +101,7 @@
185 display_buffer.make_current();
186
187 renderer.set_rotation(display_buffer.orientation());
188- renderer.begin();
189+ renderer.begin(std::move(decoration_skip_list));
190 renderer.render(renderable_list);
191 display_buffer.post_update();
192 renderer.end();
193
194=== modified file 'playground/demo-shell/demo_renderer.cpp'
195--- playground/demo-shell/demo_renderer.cpp 2014-09-10 12:50:53 +0000
196+++ playground/demo-shell/demo_renderer.cpp 2014-09-18 16:04:44 +0000
197@@ -171,7 +171,7 @@
198 glDeleteTextures(1, &titlebar_corner_tex);
199 }
200
201-void DemoRenderer::begin() const
202+void DemoRenderer::begin(std::unordered_set<graphics::Renderable::ID> decoration_skip_list_) const
203 {
204 bool const opaque = destination_alpha() == compositor::DestinationAlpha::opaque;
205 if (opaque)
206@@ -184,14 +184,19 @@
207
208 if (opaque)
209 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
210+
211+ decoration_skip_list = decoration_skip_list_;
212 }
213
214 void DemoRenderer::tessellate(std::vector<graphics::GLPrimitive>& primitives,
215 graphics::Renderable const& renderable) const
216 {
217 GLRenderer::tessellate(primitives, renderable);
218- tessellate_shadow(primitives, renderable, shadow_radius);
219- tessellate_frame(primitives, renderable, titlebar_height);
220+ if (decoration_skip_list.find(renderable.id()) == decoration_skip_list.end())
221+ {
222+ tessellate_shadow(primitives, renderable, shadow_radius);
223+ tessellate_frame(primitives, renderable, titlebar_height);
224+ }
225 }
226
227 void DemoRenderer::tessellate_shadow(std::vector<graphics::GLPrimitive>& primitives,
228
229=== modified file 'playground/demo-shell/demo_renderer.h'
230--- playground/demo-shell/demo_renderer.h 2014-09-10 12:50:53 +0000
231+++ playground/demo-shell/demo_renderer.h 2014-09-18 16:04:44 +0000
232@@ -21,6 +21,8 @@
233
234 #include "mir/compositor/gl_renderer.h"
235
236+#include <unordered_set>
237+
238 namespace mir
239 {
240 namespace examples
241@@ -37,7 +39,9 @@
242 float const shadow_radius);
243 ~DemoRenderer();
244
245- void begin() const override;
246+ void begin() const override { GLRenderer::begin(); }
247+ void begin(std::unordered_set<graphics::Renderable::ID> renderables_not_to_decorate) const;
248+
249 void tessellate(
250 std::vector<graphics::GLPrimitive>& primitives,
251 graphics::Renderable const& renderable) const override;
252@@ -59,6 +63,8 @@
253 float const corner_radius;
254 GLuint shadow_corner_tex;
255 GLuint titlebar_corner_tex;
256+
257+ mutable std::unordered_set<graphics::Renderable::ID> decoration_skip_list;
258 };
259
260 } // namespace examples
261
262=== modified file 'server-ABI-sha1sums'
263--- server-ABI-sha1sums 2014-09-12 09:03:19 +0000
264+++ server-ABI-sha1sums 2014-09-18 16:04:44 +0000
265@@ -31,14 +31,14 @@
266 979d2c1ac723ccef538d9a378228a02b0f173bd7 include/platform/mir/graphics/graphic_buffer_allocator.h
267 f90a35371e236a6cfec8e9a8474dbb3305c7621e include/platform/mir/graphics/internal_client.h
268 c9730cac4a3a101f9706ec6f444958abe047fd88 include/platform/mir/graphics/internal_surface.h
269-656a7e1ae3b246930431a6174526fbdc2c76649e include/platform/mir/graphics/platform.h
270+c775727ea15fd8affa5b4dc9cd226d782e436001 include/platform/mir/graphics/platform.h
271 15f201741a465de33e55ffc1ea775b507a5be950 include/platform/mir/graphics/renderable.h
272-b0014e8c4f44f831c9d178f995efb172417aaee4 include/platform/mir/options/configuration.h
273+f5746dab3336266cfd410ce4e4d01333df6e5b99 include/platform/mir/options/configuration.h
274 47007c783c174f8e94d332c4b13c6b01358b48fb include/platform/mir/options/default_configuration.h
275 b45f14082c4f8b29efaa1b13de795dcb29deb738 include/platform/mir/options/option.h
276 3c37cc31e8b290b89c311d82f02e07d342766451 include/platform/mir/options/program_option.h
277 f4030e400baf8baa9c38e7c6ec6b4a5ad7134aeb include/server/mir/compositor/compositor.h
278-f102d38fd8afd63b636d76005f9b80f3adda0858 include/server/mir/default_server_configuration.h
279+ef0b6f26fb40a72e4a4744e4d9c4bd044142de47 include/server/mir/default_server_configuration.h
280 af1ff0714be973ac76d56006a2e5991f68cd1dec include/server/mir/display_server.h
281 65db331f1c0e956eced5c9fc73a2b2122dbc8dc7 include/server/mir/frontend/connection_creator.h
282 e6e92642301fc9bb85e1d38087a5dd84e5d30fd7 include/server/mir/frontend/connections.h
283@@ -55,12 +55,13 @@
284 618b43a84cce0ad671ed68fe2ba796fbc7b79e31 include/server/mir/frontend/surface_id.h
285 5aa4c4db5468d9b9fe8e98a64444538aadd6e17b include/server/mir/frontend/template_protobuf_message_processor.h
286 f95c2bddf13d15993ef5d6a0ad7b9106ae550b87 include/server/mir/input/composite_event_filter.h
287-c1e96c372d7856d59947f3145d273b1285b569bc include/server/mir/input/cursor_listener.h
288+cef18b7215fbe00550d18c0aa0f79b641cff494e include/server/mir/input/cursor_listener.h
289 2331fc402686e862809bf24714a8746cdde97cb1 include/server/mir/input/event_filter.h
290 78862dda41d56c6b937a1ed197982e5fa37f50df include/server/mir/input/input_channel.h
291 6f1d9cf83bbb1256f0b4d1ba1d94d95af98c52f0 include/server/mir/input/input_dispatcher.h
292 b2ec497c6bec1b3a67c991f31cc7b7c51050ecbb include/server/mir/input/input_reception_mode.h
293 15119bf95b4512c8b91df7c20edf56a3c0734957 include/server/mir/input/surface.h
294+036f3967757873751fcacaa768ca11a52001c225 include/server/mir/input/touch_visualizer.h
295 964069b241f1e8211386bb8735ee0f752b666949 include/server/mir/main_loop.h
296 edd5a0a6be0be57ef64c5af89fc5a65dc558648c include/server/mir/report_exception.h
297 8192727cf5fa0b2b5798b2211c2c8a4ad65c9f60 include/server/mir/run_mir.h
298
299=== added file 'src/include/platform/mir/graphics/buffer_writer.h'
300--- src/include/platform/mir/graphics/buffer_writer.h 1970-01-01 00:00:00 +0000
301+++ src/include/platform/mir/graphics/buffer_writer.h 2014-09-18 16:04:44 +0000
302@@ -0,0 +1,44 @@
303+/*
304+ * Copyright © 2014 Canonical Ltd.
305+ *
306+ * This program is free software: you can redistribute it and/or modify it
307+ * under the terms of the GNU Lesser General Public License version 3,
308+ * as published by the Free Software Foundation.
309+ *
310+ * This program is distributed in the hope that it will be useful,
311+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
312+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
313+ * GNU Lesser General Public License for more details.
314+ *
315+ * You should have received a copy of the GNU Lesser General Public License
316+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
317+ *
318+ * Authored by: Robert Carr <robert.carr@canonical.com>
319+ */
320+
321+#include <cstddef>
322+
323+namespace mir
324+{
325+namespace graphics
326+{
327+class Buffer;
328+
329+/// An interface provided by the graphics platform allowing for writing untiled pixel data into buffers.
330+class BufferWriter
331+{
332+public:
333+ virtual ~BufferWriter() = default;
334+
335+ // Expects data to be an unstrided array containing (buffer.width * buffer.height) pixels. Likewise
336+ // it is expected that buffer and data match in pixel format.
337+ virtual void write(Buffer& buffer, unsigned char const* data, size_t size) = 0;
338+
339+protected:
340+ BufferWriter() = default;
341+ BufferWriter(BufferWriter const&) = delete;
342+ BufferWriter& operator=(BufferWriter const&) = delete;
343+};
344+
345+}
346+}
347
348=== modified file 'src/include/platform/mir/graphics/native_platform.h'
349--- src/include/platform/mir/graphics/native_platform.h 2014-09-10 12:50:53 +0000
350+++ src/include/platform/mir/graphics/native_platform.h 2014-09-18 16:04:44 +0000
351@@ -36,6 +36,7 @@
352 class InternalClient;
353 class BufferIPCPacker;
354 class Buffer;
355+class BufferWriter;
356 class DisplayReport;
357 class NestedContext;
358
359@@ -58,6 +59,8 @@
360 Buffer const* buffer,
361 BufferIpcMsgType msg_type) const = 0;
362
363+ virtual std::shared_ptr<BufferWriter> make_buffer_writer() = 0;
364+
365 virtual ~NativePlatform() = default;
366 NativePlatform(NativePlatform const&) = delete;
367 NativePlatform& operator=(NativePlatform const&) = delete;
368
369=== modified file 'src/include/server/mir/compositor/scene_element.h'
370--- src/include/server/mir/compositor/scene_element.h 2014-09-10 12:50:53 +0000
371+++ src/include/server/mir/compositor/scene_element.h 2014-09-18 16:04:44 +0000
372@@ -39,6 +39,10 @@
373 virtual std::shared_ptr<graphics::Renderable> renderable() const = 0;
374 virtual void rendered_in(CompositorID cid) = 0;
375 virtual void occluded_in(CompositorID cid) = 0;
376+
377+ // Query whether the SceneElement represents a window-surface, which at the discretion of the compositor
378+ // may be eligible for window decoration.
379+ virtual bool is_a_surface() const = 0;
380
381 protected:
382 SceneElement() = default;
383
384=== renamed file 'src/include/server/mir/input/input_targets.h' => 'src/include/server/mir/input/scene.h'
385--- src/include/server/mir/input/input_targets.h 2014-09-10 12:50:53 +0000
386+++ src/include/server/mir/input/scene.h 2014-09-18 16:04:44 +0000
387@@ -17,8 +17,8 @@
388 * Daniel d'Andradra <daniel.dandrada@canonical.com>
389 */
390
391-#ifndef MIR_INPUT_INPUT_TARGETS_H_
392-#define MIR_INPUT_INPUT_TARGETS_H_
393+#ifndef MIR_INPUT_INPUT_SCENE_H_
394+#define MIR_INPUT_INPUT_SCENE_H_
395
396 #include "mir/input/input_channel_factory.h"
397
398@@ -30,28 +30,43 @@
399 {
400 class Observer;
401 }
402+namespace graphics
403+{
404+class Renderable;
405+}
406
407 namespace input
408 {
409 class Surface;
410
411-class InputTargets
412+class Scene
413 {
414 public:
415- virtual ~InputTargets() = default;
416+ virtual ~Scene() = default;
417
418 virtual void for_each(std::function<void(std::shared_ptr<input::Surface> const&)> const& callback) = 0;
419
420 virtual void add_observer(std::shared_ptr<scene::Observer> const& observer) = 0;
421 virtual void remove_observer(std::weak_ptr<scene::Observer> const& observer) = 0;
422
423+ // An interface which the input stack can use to add certain non interactive input visualizations
424+ // in to the scene (i.e. cursors, touchspots). Overlay renderables will be rendered above all surfaces.
425+ // Within the set of overlay renderables, rendering order is undefined.
426+ virtual void add_input_visualization(std::shared_ptr<graphics::Renderable> const& overlay) = 0;
427+ virtual void remove_input_visualization(std::weak_ptr<graphics::Renderable> const& overlay) = 0;
428+
429+ // As input visualizations added through the overlay system will not use the standard SurfaceObserver
430+ // mechanism, we require this method to trigger recomposition.
431+ // TODO: How can something like SurfaceObserver be adapted to work with non surface renderables?
432+ virtual void emit_scene_changed() = 0;
433+
434 protected:
435- InputTargets() = default;
436- InputTargets(InputTargets const&) = delete;
437- InputTargets& operator=(InputTargets const&) = delete;
438+ Scene() = default;
439+ Scene(Scene const&) = delete;
440+ Scene& operator=(Scene const&) = delete;
441 };
442
443 }
444 }
445
446-#endif // MIR_INPUT_INPUT_TARGETS
447+#endif // MIR_INPUT_INPUT_SCENE
448
449=== modified file 'src/include/server/mir/scene/legacy_scene_change_notification.h'
450--- src/include/server/mir/scene/legacy_scene_change_notification.h 2014-09-10 12:50:53 +0000
451+++ src/include/server/mir/scene/legacy_scene_change_notification.h 2014-09-18 16:04:44 +0000
452@@ -45,6 +45,8 @@
453 void surface_added(Surface* surface) override;
454 void surface_removed(Surface* surface) override;
455 void surfaces_reordered() override;
456+
457+ void scene_changed() override;
458
459 void surface_exists(Surface* surface) override;
460 void end_observation() override;
461
462=== modified file 'src/include/server/mir/scene/observer.h'
463--- src/include/server/mir/scene/observer.h 2014-09-10 12:50:53 +0000
464+++ src/include/server/mir/scene/observer.h 2014-09-18 16:04:44 +0000
465@@ -36,6 +36,10 @@
466 virtual void surface_added(Surface* surface) = 0;
467 virtual void surface_removed(Surface* surface) = 0;
468 virtual void surfaces_reordered() = 0;
469+
470+ // Used to indicate the scene has changed in some way beyond the present surfaces
471+ // and will require full recomposition.
472+ virtual void scene_changed() = 0;
473
474 // Called at observer registration to notify of already existing surfaces.
475 virtual void surface_exists(Surface* surface) = 0;
476
477=== modified file 'src/platform/CMakeLists.txt'
478--- src/platform/CMakeLists.txt 2014-09-10 13:27:58 +0000
479+++ src/platform/CMakeLists.txt 2014-09-18 16:04:44 +0000
480@@ -3,7 +3,7 @@
481 ${PROJECT_SOURCE_DIR}/src/include/platform
482 )
483
484-set(MIRPLATFORM_ABI 2)
485+set(MIRPLATFORM_ABI 3)
486
487 set(symbol_map ${CMAKE_CURRENT_SOURCE_DIR}/symbols.map)
488
489
490=== modified file 'src/platform/graphics/android/CMakeLists.txt'
491--- src/platform/graphics/android/CMakeLists.txt 2014-09-10 12:50:53 +0000
492+++ src/platform/graphics/android/CMakeLists.txt 2014-09-18 16:04:44 +0000
493@@ -35,6 +35,7 @@
494 device_quirks.cpp
495 real_hwc_wrapper.cpp
496 hwc_fallback_gl_renderer.cpp
497+ android_buffer_writer.cpp
498 )
499 add_library(mirplatformgraphicsandroid SHARED
500 $<TARGET_OBJECTS:mirplatformgraphicsandroidobjects>
501
502=== added file 'src/platform/graphics/android/android_buffer_writer.cpp'
503--- src/platform/graphics/android/android_buffer_writer.cpp 1970-01-01 00:00:00 +0000
504+++ src/platform/graphics/android/android_buffer_writer.cpp 2014-09-18 16:04:44 +0000
505@@ -0,0 +1,70 @@
506+/*
507+ * Copyright © 2014 Canonical Ltd.
508+ *
509+ * This program is free software: you can redistribute it and/or modify it
510+ * under the terms of the GNU Lesser General Public License version 3,
511+ * as published by the Free Software Foundation.
512+ *
513+ * This program is distributed in the hope that it will be useful,
514+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
515+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
516+ * GNU Lesser General Public License for more details.
517+ *
518+ * You should have received a copy of the GNU Lesser General Public License
519+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
520+ *
521+ * Authored by:
522+ * Robert Carr <robert.carr@canonical.com>
523+ */
524+
525+#include "android_buffer_writer.h"
526+#include "buffer.h"
527+
528+#include "mir/graphics/android/android_native_buffer.h"
529+
530+#include <hardware/hardware.h>
531+
532+#include <boost/throw_exception.hpp>
533+#include <stdexcept>
534+
535+#include <string.h>
536+
537+namespace mg = mir::graphics;
538+namespace mga = mg::android;
539+
540+mga::BufferWriter::BufferWriter()
541+{
542+ auto err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (hw_module_t const **)(&hw_module));
543+ if (err < 0)
544+ BOOST_THROW_EXCEPTION(std::runtime_error("Could not open hardware module"));
545+}
546+
547+void mga::BufferWriter::write(mg::Buffer& buffer, unsigned char const* data, size_t size)
548+{
549+ auto buffer_size = buffer.size();
550+ auto bpp = MIR_BYTES_PER_PIXEL(buffer.pixel_format());
551+ if (bpp * buffer_size.width.as_uint32_t() * buffer_size.height.as_uint32_t() != size)
552+ BOOST_THROW_EXCEPTION(std::logic_error("Size of pixels is not equal to size of buffer"));
553+
554+ auto const& handle = buffer.native_buffer_handle();
555+
556+ char* vaddr;
557+ int usage = GRALLOC_USAGE_SW_WRITE_OFTEN;
558+ int width = buffer.size().width.as_uint32_t();
559+ int height = buffer.size().height.as_uint32_t();
560+ int top = 0;
561+ int left = 0;
562+ if ( hw_module->lock(hw_module, handle->handle(),
563+ usage, top, left, width, height, reinterpret_cast<void**>(&vaddr)) )
564+ BOOST_THROW_EXCEPTION(std::runtime_error("error securing buffer for client cpu use"));
565+
566+ // Copy line by line in case of stride != width*bpp
567+ for (int i = 0; i < height; i++)
568+ {
569+ int line_offset_in_buffer = buffer.stride().as_uint32_t()*i;
570+ int line_offset_in_source = bpp*width*i;
571+ memcpy(vaddr + line_offset_in_buffer, data + line_offset_in_source, width * bpp);
572+ }
573+
574+ hw_module->unlock(hw_module, handle->handle());
575+}
576
577=== added file 'src/platform/graphics/android/android_buffer_writer.h'
578--- src/platform/graphics/android/android_buffer_writer.h 1970-01-01 00:00:00 +0000
579+++ src/platform/graphics/android/android_buffer_writer.h 2014-09-18 16:04:44 +0000
580@@ -0,0 +1,50 @@
581+/*
582+ * Copyright © 2014 Canonical Ltd.
583+ *
584+ * This program is free software: you can redistribute it and/or modify it
585+ * under the terms of the GNU Lesser General Public License version 3,
586+ * as published by the Free Software Foundation.
587+ *
588+ * This program is distributed in the hope that it will be useful,
589+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
590+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
591+ * GNU Lesser General Public License for more details.
592+ *
593+ * You should have received a copy of the GNU Lesser General Public License
594+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
595+ *
596+ * Authored by:
597+ * Robert Carr <robert.carr@canonical.com>
598+ */
599+
600+#ifndef MIR_PLATFORM_ANDROID_ANDROID_BUFFER_WRITER_H_
601+#define MIR_PLATFORM_ANDROID_ANDROID_BUFFER_WRITER_H_
602+
603+#include "mir/graphics/buffer_writer.h"
604+
605+#include <hardware/gralloc.h>
606+
607+#include <memory>
608+
609+namespace mir
610+{
611+namespace graphics
612+{
613+namespace android
614+{
615+
616+class BufferWriter : public graphics::BufferWriter
617+{
618+public:
619+ BufferWriter();
620+
621+ void write(graphics::Buffer& buffer, unsigned char const* pixels, size_t size) override;
622+private:
623+ gralloc_module_t const* hw_module;
624+};
625+
626+}
627+}
628+}
629+
630+#endif /* MIR_PLATFORM_ANDROID_ANDROID_BUFFER_WRITER_H_ */
631
632=== modified file 'src/platform/graphics/android/android_display.cpp'
633--- src/platform/graphics/android/android_display.cpp 2014-09-10 12:50:53 +0000
634+++ src/platform/graphics/android/android_display.cpp 2014-09-18 16:04:44 +0000
635@@ -103,7 +103,7 @@
636
637 auto mga::AndroidDisplay::create_hardware_cursor(std::shared_ptr<mg::CursorImage> const& /* initial_image */) -> std::shared_ptr<Cursor>
638 {
639- return std::shared_ptr<Cursor>();
640+ return nullptr;
641 }
642
643 std::unique_ptr<mg::GLContext> mga::AndroidDisplay::create_gl_context()
644
645=== modified file 'src/platform/graphics/android/android_platform.cpp'
646--- src/platform/graphics/android/android_platform.cpp 2014-09-15 18:58:24 +0000
647+++ src/platform/graphics/android/android_platform.cpp 2014-09-18 16:04:44 +0000
648@@ -24,6 +24,7 @@
649 #include "android_display.h"
650 #include "internal_client.h"
651 #include "output_builder.h"
652+#include "android_buffer_writer.h"
653 #include "hwc_loggers.h"
654 #include "mir/graphics/platform_ipc_package.h"
655 #include "mir/graphics/android/native_buffer.h"
656@@ -153,6 +154,11 @@
657 return std::make_shared<mga::InternalClient>();
658 }
659
660+std::shared_ptr<mg::BufferWriter> mga::AndroidPlatform::make_buffer_writer()
661+{
662+ return std::make_shared<mga::BufferWriter>();
663+}
664+
665 extern "C" std::shared_ptr<mg::Platform> mg::create_platform(
666 std::shared_ptr<mo::Option> const& options,
667 std::shared_ptr<mir::EmergencyCleanupRegistry> const& /*emergency_cleanup_registry*/,
668
669=== modified file 'src/platform/graphics/android/android_platform.h'
670--- src/platform/graphics/android/android_platform.h 2014-09-10 12:50:53 +0000
671+++ src/platform/graphics/android/android_platform.h 2014-09-18 16:04:44 +0000
672@@ -49,6 +49,7 @@
673 std::shared_ptr<graphics::GLConfig> const& /*gl_config*/);
674 std::shared_ptr<PlatformIPCPackage> get_ipc_package();
675 std::shared_ptr<InternalClient> create_internal_client();
676+ std::shared_ptr<graphics::BufferWriter> make_buffer_writer() override;
677 void fill_buffer_package(
678 BufferIPCPacker* packer, graphics::Buffer const* buffer, BufferIpcMsgType msg_type) const;
679 EGLNativeDisplayType egl_native_display() const;
680
681=== modified file 'src/platform/graphics/mesa/CMakeLists.txt'
682--- src/platform/graphics/mesa/CMakeLists.txt 2014-09-10 12:50:53 +0000
683+++ src/platform/graphics/mesa/CMakeLists.txt 2014-09-18 16:04:44 +0000
684@@ -33,6 +33,7 @@
685 anonymous_shm_file.cpp
686 shm_buffer.cpp
687 bypass.cpp
688+ buffer_writer.cpp
689 )
690
691 add_library(mirplatformgraphicsmesa SHARED
692
693=== modified file 'src/platform/graphics/mesa/buffer_allocator.cpp'
694--- src/platform/graphics/mesa/buffer_allocator.cpp 2014-09-10 12:50:53 +0000
695+++ src/platform/graphics/mesa/buffer_allocator.cpp 2014-09-18 16:04:44 +0000
696@@ -39,7 +39,7 @@
697 #include <cassert>
698
699 namespace mg = mir::graphics;
700-namespace mgm = mir::graphics::mesa;
701+namespace mgm = mg::mesa;
702 namespace geom = mir::geometry;
703
704 namespace
705
706=== added file 'src/platform/graphics/mesa/buffer_writer.cpp'
707--- src/platform/graphics/mesa/buffer_writer.cpp 1970-01-01 00:00:00 +0000
708+++ src/platform/graphics/mesa/buffer_writer.cpp 2014-09-18 16:04:44 +0000
709@@ -0,0 +1,40 @@
710+/*
711+ * Copyright © 2014 Canonical Ltd.
712+ *
713+ * This program is free software: you can redistribute it and/or modify it
714+ * under the terms of the GNU Lesser General Public License version 3,
715+ * as published by the Free Software Foundation.
716+ *
717+ * This program is distributed in the hope that it will be useful,
718+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
719+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
720+ * GNU Lesser General Public License for more details.
721+ *
722+ * You should have received a copy of the GNU Lesser General Public License
723+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
724+ *
725+ * Authored by: Robert Carr <robert.carr@canonical.com>
726+ */
727+
728+#include "buffer_writer.h"
729+
730+#include "shm_buffer.h"
731+
732+#include <boost/throw_exception.hpp>
733+#include <stdexcept>
734+
735+namespace mg = mir::graphics;
736+namespace mgm = mir::graphics::mesa;
737+
738+mgm::BufferWriter::BufferWriter()
739+{
740+}
741+
742+void mgm::BufferWriter::write(mg::Buffer& buffer, unsigned char const* data, size_t size)
743+{
744+ auto shm_buffer = dynamic_cast<mgm::ShmBuffer*>(&buffer);
745+ if (!shm_buffer)
746+ BOOST_THROW_EXCEPTION(std::logic_error("Direct CPU write is only supported to software allocated buffers on mesa platform"));
747+
748+ shm_buffer->write(data, size);
749+}
750
751=== added file 'src/platform/graphics/mesa/buffer_writer.h'
752--- src/platform/graphics/mesa/buffer_writer.h 1970-01-01 00:00:00 +0000
753+++ src/platform/graphics/mesa/buffer_writer.h 2014-09-18 16:04:44 +0000
754@@ -0,0 +1,43 @@
755+/*
756+ * Copyright © 2014 Canonical Ltd.
757+ *
758+ * This program is free software: you can redistribute it and/or modify it
759+ * under the terms of the GNU Lesser General Public License version 3,
760+ * as published by the Free Software Foundation.
761+ *
762+ * This program is distributed in the hope that it will be useful,
763+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
764+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
765+ * GNU Lesser General Public License for more details.
766+ *
767+ * You should have received a copy of the GNU Lesser General Public License
768+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
769+ *
770+ * Authored by: Robert Carr <robert.carr@canonical.com>
771+ */
772+
773+#ifndef MIR_GRAPHICS_MESA_BUFFER_WRITER_H_
774+#define MIR_GRAPHICS_MESA_BUFFER_WRITER_H_
775+
776+#include "mir/graphics/buffer_writer.h"
777+
778+namespace mir
779+{
780+namespace graphics
781+{
782+class Buffer;
783+
784+namespace mesa
785+{
786+class BufferWriter : public graphics::BufferWriter
787+{
788+public:
789+ BufferWriter();
790+
791+ void write(graphics::Buffer& buffer, unsigned char const* data, size_t size) override;
792+};
793+}
794+}
795+}
796+
797+#endif // MIR_GRAPHICS_MESA_BUFFER_WRITER_H_
798
799=== modified file 'src/platform/graphics/mesa/native_platform.cpp'
800--- src/platform/graphics/mesa/native_platform.cpp 2014-09-10 12:50:53 +0000
801+++ src/platform/graphics/mesa/native_platform.cpp 2014-09-18 16:04:44 +0000
802@@ -21,6 +21,7 @@
803 #include "native_platform.h"
804
805 #include "buffer_allocator.h"
806+#include "buffer_writer.h"
807 #include "mir/graphics/buffer_ipc_packer.h"
808 #include "mir/graphics/platform_ipc_package.h"
809 #include "mir/graphics/nested_context.h"
810@@ -157,3 +158,7 @@
811 native_display.reset();
812 }
813
814+std::shared_ptr<mg::BufferWriter> mgm::NativePlatform::make_buffer_writer()
815+{
816+ return std::make_shared<mgm::BufferWriter>();
817+}
818
819=== modified file 'src/platform/graphics/mesa/native_platform.h'
820--- src/platform/graphics/mesa/native_platform.h 2014-09-10 12:50:53 +0000
821+++ src/platform/graphics/mesa/native_platform.h 2014-09-18 16:04:44 +0000
822@@ -44,6 +44,7 @@
823 std::shared_ptr<InternalClient> create_internal_client() override;
824 void fill_buffer_package(
825 BufferIPCPacker* packer, Buffer const* buffer, BufferIpcMsgType msg_type) const override;
826+ std::shared_ptr<graphics::BufferWriter> make_buffer_writer() override;
827
828 static std::shared_ptr<InternalNativeDisplay> internal_native_display();
829 static bool internal_native_display_in_use();
830
831=== modified file 'src/platform/graphics/mesa/platform.cpp'
832--- src/platform/graphics/mesa/platform.cpp 2014-09-10 12:50:53 +0000
833+++ src/platform/graphics/mesa/platform.cpp 2014-09-18 16:04:44 +0000
834@@ -23,6 +23,7 @@
835 #include "internal_client.h"
836 #include "internal_native_display.h"
837 #include "linux_virtual_terminal.h"
838+#include "buffer_writer.h"
839 #include "mir/graphics/platform_ipc_package.h"
840 #include "mir/graphics/buffer_ipc_packer.h"
841 #include "mir/options/option.h"
842@@ -216,6 +217,11 @@
843 return std::make_shared<mgm::InternalClient>(internal_native_display);
844 }
845
846+std::shared_ptr<mg::BufferWriter> mgm::Platform::make_buffer_writer()
847+{
848+ return std::make_shared<mgm::BufferWriter>();
849+}
850+
851 EGLNativeDisplayType mgm::Platform::egl_native_display() const
852 {
853 return gbm.device;
854
855=== modified file 'src/platform/graphics/mesa/platform.h'
856--- src/platform/graphics/mesa/platform.h 2014-09-10 12:50:53 +0000
857+++ src/platform/graphics/mesa/platform.h 2014-09-18 16:04:44 +0000
858@@ -54,6 +54,7 @@
859 /* From Platform */
860 std::shared_ptr<graphics::GraphicBufferAllocator> create_buffer_allocator(
861 const std::shared_ptr<BufferInitializer>& buffer_initializer);
862+ std::shared_ptr<graphics::BufferWriter> make_buffer_writer();
863 std::shared_ptr<graphics::Display> create_display(
864 std::shared_ptr<DisplayConfigurationPolicy> const& initial_conf_policy,
865 std::shared_ptr<GLProgramFactory> const& program_factory,
866
867=== modified file 'src/platform/graphics/mesa/shm_buffer.cpp'
868--- src/platform/graphics/mesa/shm_buffer.cpp 2014-09-10 12:50:53 +0000
869+++ src/platform/graphics/mesa/shm_buffer.cpp 2014-09-18 16:04:44 +0000
870@@ -23,6 +23,12 @@
871 #include <GLES2/gl2.h>
872 #include <GLES2/gl2ext.h>
873
874+#include <boost/throw_exception.hpp>
875+
876+#include <stdexcept>
877+
878+#include <string.h>
879+
880 namespace mgm = mir::graphics::mesa;
881 namespace geom = mir::geometry;
882
883@@ -85,3 +91,10 @@
884 {
885 return false;
886 }
887+
888+void mgm::ShmBuffer::write(unsigned char const* data, size_t data_size)
889+{
890+ if (data_size != stride_.as_uint32_t()*size().height.as_uint32_t())
891+ BOOST_THROW_EXCEPTION(std::logic_error("Size is not equal to number of pixels in buffer"));
892+ memcpy(pixels, data, data_size);
893+}
894
895=== modified file 'src/platform/graphics/mesa/shm_buffer.h'
896--- src/platform/graphics/mesa/shm_buffer.h 2014-09-10 12:50:53 +0000
897+++ src/platform/graphics/mesa/shm_buffer.h 2014-09-18 16:04:44 +0000
898@@ -49,6 +49,8 @@
899 void gl_bind_to_texture() override;
900 bool can_bypass() const;
901
902+ void write(unsigned char const* data, size_t size);
903+
904 private:
905 ShmBuffer(ShmBuffer const&) = delete;
906 ShmBuffer& operator=(ShmBuffer const&) = delete;
907
908=== modified file 'src/platform/options/default_configuration.cpp'
909--- src/platform/options/default_configuration.cpp 2014-09-10 12:50:53 +0000
910+++ src/platform/options/default_configuration.cpp 2014-09-18 16:04:44 +0000
911@@ -43,9 +43,9 @@
912 char const* const mo::frontend_threads_opt = "ipc-thread-pool";
913 char const* const mo::name_opt = "name";
914 char const* const mo::offscreen_opt = "offscreen";
915+char const* const mo::touchspots_opt = "enable-touchspots";
916 char const* const mo::fatal_abort_opt = "on-fatal-error-abort";
917
918-
919 char const* const mo::glog = "glog";
920 char const* const mo::glog_stderrthreshold = "glog-stderrthreshold";
921 char const* const mo::glog_minloglevel = "glog-minloglevel";
922@@ -161,6 +161,8 @@
923 "When nested, the name Mir uses when registering with the host.")
924 (offscreen_opt,
925 "Render to offscreen buffers instead of the real outputs.")
926+ (touchspots_opt,
927+ "Display visualization of touchspots (e.g. for screencasting).")
928 (fatal_abort_opt, "On \"fatal error\" conditions [e.g. drivers behaving "
929 "in unexpected ways] abort (to get a core dump)");
930
931
932=== modified file 'src/platform/symbols.map'
933--- src/platform/symbols.map 2014-09-10 12:50:53 +0000
934+++ src/platform/symbols.map 2014-09-18 16:04:44 +0000
935@@ -1,4 +1,4 @@
936-MIRPLATFORM_2 {
937+MIRPLATFORM_3 {
938 global:
939 extern "C++" {
940 # The following symbols come from running a script over the generated docs. Vis:
941@@ -252,6 +252,7 @@
942 mir::options::scene_report_opt*;
943 mir::options::server_socket_opt*;
944 mir::options::session_mediator_report_opt*;
945+ mir::options::touchspots_opt*;
946 typeinfo?for?mir::AbnormalExit;
947 typeinfo?for?mir::EmergencyCleanupRegistry;
948 typeinfo?for?mir::FatalErrorStrategy;
949
950=== modified file 'src/server/graphics/default_configuration.cpp'
951--- src/server/graphics/default_configuration.cpp 2014-09-10 12:50:53 +0000
952+++ src/server/graphics/default_configuration.cpp 2014-09-18 16:04:44 +0000
953@@ -106,6 +106,16 @@
954 });
955 }
956
957+std::shared_ptr<mg::BufferWriter>
958+mir::DefaultServerConfiguration::the_buffer_writer()
959+{
960+ return buffer_writer(
961+ [&]()
962+ {
963+ return the_graphics_platform()->make_buffer_writer();
964+ });
965+}
966+
967 std::shared_ptr<mg::Display>
968 mir::DefaultServerConfiguration::the_display()
969 {
970
971=== modified file 'src/server/graphics/nested/nested_platform.cpp'
972--- src/server/graphics/nested/nested_platform.cpp 2014-09-10 12:50:53 +0000
973+++ src/server/graphics/nested/nested_platform.cpp 2014-09-18 16:04:44 +0000
974@@ -80,6 +80,11 @@
975 return native_platform->create_buffer_allocator(buffer_initializer);
976 }
977
978+std::shared_ptr<mg::BufferWriter> mgn::NestedPlatform::make_buffer_writer()
979+{
980+ return native_platform->make_buffer_writer();
981+}
982+
983 std::shared_ptr<mg::Display> mgn::NestedPlatform::create_display(
984 std::shared_ptr<mg::DisplayConfigurationPolicy> const& conf_policy,
985 std::shared_ptr<mg::GLProgramFactory> const&,
986
987=== modified file 'src/server/graphics/nested/nested_platform.h'
988--- src/server/graphics/nested/nested_platform.h 2014-09-10 12:50:53 +0000
989+++ src/server/graphics/nested/nested_platform.h 2014-09-18 16:04:44 +0000
990@@ -49,6 +49,7 @@
991 std::shared_ptr<GLConfig> const& gl_config);
992 std::shared_ptr<PlatformIPCPackage> get_ipc_package() override;
993 std::shared_ptr<InternalClient> create_internal_client() override;
994+ std::shared_ptr<BufferWriter> make_buffer_writer() override;
995 void fill_buffer_package(
996 BufferIPCPacker* packer, Buffer const* Buffer, BufferIpcMsgType msg_type) const override;
997 EGLNativeDisplayType egl_native_display() const;
998
999=== modified file 'src/server/input/CMakeLists.txt'
1000--- src/server/input/CMakeLists.txt 2014-09-10 12:50:53 +0000
1001+++ src/server/input/CMakeLists.txt 2014-09-18 16:04:44 +0000
1002@@ -16,6 +16,7 @@
1003 default_configuration.cpp
1004 xcursor_loader.cpp
1005 builtin_cursor_images.cpp
1006+ touchspot_controller.cpp
1007 )
1008
1009 add_subdirectory(android)
1010
1011=== modified file 'src/server/input/android/android_input_registrar.cpp'
1012--- src/server/input/android/android_input_registrar.cpp 2014-09-10 12:50:53 +0000
1013+++ src/server/input/android/android_input_registrar.cpp 2014-09-18 16:04:44 +0000
1014@@ -123,3 +123,7 @@
1015 {
1016 remove(surface);
1017 }
1018+
1019+void mia::InputRegistrar::SceneObserver::scene_changed()
1020+{
1021+}
1022
1023=== modified file 'src/server/input/android/android_input_registrar.h'
1024--- src/server/input/android/android_input_registrar.h 2014-09-10 12:50:53 +0000
1025+++ src/server/input/android/android_input_registrar.h 2014-09-18 16:04:44 +0000
1026@@ -73,6 +73,7 @@
1027 void surface_added(scene::Surface* surface) override;
1028 void surface_removed(scene::Surface* surface) override;
1029 void surface_exists(scene::Surface* surface) override;
1030+ void scene_changed() override;
1031
1032 SurfaceCallback add, remove;
1033 };
1034
1035=== modified file 'src/server/input/android/android_input_target_enumerator.cpp'
1036--- src/server/input/android/android_input_target_enumerator.cpp 2014-09-10 12:50:53 +0000
1037+++ src/server/input/android/android_input_target_enumerator.cpp 2014-09-18 16:04:44 +0000
1038@@ -20,7 +20,7 @@
1039
1040 #include "android_window_handle_repository.h"
1041
1042-#include "mir/input/input_targets.h"
1043+#include "mir/input/scene.h"
1044 #include "mir/input/surface.h"
1045
1046 #include <InputWindow.h>
1047@@ -28,9 +28,9 @@
1048 namespace mi = mir::input;
1049 namespace mia = mi::android;
1050
1051-mia::InputTargetEnumerator::InputTargetEnumerator(std::shared_ptr<mi::InputTargets> const& targets,
1052+mia::InputTargetEnumerator::InputTargetEnumerator(std::shared_ptr<mi::Scene> const& scene,
1053 std::shared_ptr<mia::WindowHandleRepository> const& repository)
1054- : targets(targets),
1055+ : scene(scene),
1056 repository(repository)
1057 {
1058 }
1059@@ -41,7 +41,7 @@
1060
1061 void mia::InputTargetEnumerator::for_each(std::function<void(droidinput::sp<droidinput::InputWindowHandle> const&)> const& callback)
1062 {
1063- targets->for_each(
1064+ scene->for_each(
1065 [&callback, this](std::shared_ptr<mi::Surface> const& target)
1066 {
1067 auto handle = repository->handle_for_channel(target->input_channel());
1068
1069=== modified file 'src/server/input/android/android_input_target_enumerator.h'
1070--- src/server/input/android/android_input_target_enumerator.h 2014-09-10 12:50:53 +0000
1071+++ src/server/input/android/android_input_target_enumerator.h 2014-09-18 16:04:44 +0000
1072@@ -41,7 +41,7 @@
1073 }
1074 namespace input
1075 {
1076-class InputTargets;
1077+class Scene;
1078 namespace android
1079 {
1080 class WindowHandleRepository;
1081@@ -49,14 +49,14 @@
1082 class InputTargetEnumerator : public droidinput::InputEnumerator
1083 {
1084 public:
1085- explicit InputTargetEnumerator(std::shared_ptr<input::InputTargets> const& targets,
1086+ explicit InputTargetEnumerator(std::shared_ptr<input::Scene> const& scene,
1087 std::shared_ptr<WindowHandleRepository> const& repository);
1088 virtual ~InputTargetEnumerator() noexcept(true);
1089
1090 void for_each(std::function<void(droidinput::sp<droidinput::InputWindowHandle> const&)> const& callback);
1091
1092 private:
1093- std::shared_ptr<input::InputTargets> const targets;
1094+ std::shared_ptr<input::Scene> const scene;
1095 std::shared_ptr<input::android::WindowHandleRepository> const repository;
1096 };
1097
1098
1099=== modified file 'src/server/input/android/input_sender.cpp'
1100--- src/server/input/android/input_sender.cpp 2014-09-10 12:50:53 +0000
1101+++ src/server/input/android/input_sender.cpp 2014-09-18 16:04:44 +0000
1102@@ -83,8 +83,12 @@
1103 surface_added(surface);
1104 }
1105
1106-
1107-void mia::InputSender::SceneObserver::remove_transfer_for(mir::input::Surface * surface)
1108+void mia::InputSender::SceneObserver::scene_changed()
1109+{
1110+}
1111+
1112+
1113+void mia::InputSender::SceneObserver::remove_transfer_for(mi::Surface * surface)
1114 {
1115 std::shared_ptr<InputChannel> closed_channel = surface->input_channel();
1116
1117@@ -96,7 +100,7 @@
1118 }
1119
1120 mia::InputSender::InputSenderState::InputSenderState(std::shared_ptr<mir::MainLoop> const& main_loop,
1121- std::shared_ptr<mir::input::InputSendObserver> const& observer,
1122+ std::shared_ptr<mi::InputSendObserver> const& observer,
1123 std::shared_ptr<InputReport> const& report)
1124 : main_loop{main_loop}, report{report}, observer{observer}, seq{}
1125 {
1126@@ -131,7 +135,7 @@
1127 transfer->send(std::move(entry));
1128 }
1129
1130-void mia::InputSender::InputSenderState::add_transfer(int fd, mir::input::Surface * surface)
1131+void mia::InputSender::InputSenderState::add_transfer(int fd, mi::Surface * surface)
1132 {
1133 std::lock_guard<std::mutex> lock(sender_mutex);
1134 std::shared_ptr<ActiveTransfer> transfer{get_transfer(fd)};
1135@@ -163,7 +167,7 @@
1136 return seq;
1137 }
1138
1139-mia::InputSender::ActiveTransfer::ActiveTransfer(InputSenderState & state, int server_fd, mir::input::Surface* surface) :
1140+mia::InputSender::ActiveTransfer::ActiveTransfer(InputSenderState & state, int server_fd, mi::Surface* surface) :
1141 state(state),
1142 publisher{droidinput::sp<droidinput::InputChannel>(
1143 new droidinput::InputChannel(droidinput::String8(surface->name()), server_fd))},
1144
1145=== modified file 'src/server/input/android/input_sender.h'
1146--- src/server/input/android/input_sender.h 2014-09-10 12:50:53 +0000
1147+++ src/server/input/android/input_sender.h 2014-09-18 16:04:44 +0000
1148@@ -76,6 +76,7 @@
1149 void surface_added(scene::Surface* surface) override;
1150 void surface_removed(scene::Surface* surface) override;
1151 void surface_exists(scene::Surface* surface) override;
1152+ void scene_changed() override;
1153
1154 void remove_transfer_for(input::Surface* surface);
1155 InputSenderState & state;
1156
1157=== modified file 'src/server/input/cursor_controller.cpp'
1158--- src/server/input/cursor_controller.cpp 2014-06-23 02:57:39 +0000
1159+++ src/server/input/cursor_controller.cpp 2014-09-18 16:04:44 +0000
1160@@ -18,7 +18,7 @@
1161
1162 #include "cursor_controller.h"
1163
1164-#include "mir/input/input_targets.h"
1165+#include "mir/input/scene.h"
1166 #include "mir/input/surface.h"
1167 #include "mir/graphics/cursor.h"
1168 #include "mir/scene/observer.h"
1169@@ -130,6 +130,11 @@
1170 {
1171 cursor_controller->update_cursor_image();
1172 }
1173+
1174+ void scene_changed()
1175+ {
1176+ cursor_controller->update_cursor_image();
1177+ }
1178
1179 void surface_exists(ms::Surface *surface)
1180 {
1181@@ -157,7 +162,7 @@
1182 };
1183
1184 std::shared_ptr<mi::Surface> topmost_surface_containing_point(
1185- std::shared_ptr<mi::InputTargets> const& targets, geom::Point const& point)
1186+ std::shared_ptr<mi::Scene> const& targets, geom::Point const& point)
1187 {
1188 std::shared_ptr<mi::Surface> top_surface_at_point;
1189 targets->for_each([&top_surface_at_point, &point]
1190@@ -171,7 +176,7 @@
1191
1192 }
1193
1194-mi::CursorController::CursorController(std::shared_ptr<mi::InputTargets> const& input_targets,
1195+mi::CursorController::CursorController(std::shared_ptr<mi::Scene> const& input_targets,
1196 std::shared_ptr<mg::Cursor> const& cursor,
1197 std::shared_ptr<mg::CursorImage> const& default_cursor_image) :
1198 input_targets(input_targets),
1199
1200=== modified file 'src/server/input/cursor_controller.h'
1201--- src/server/input/cursor_controller.h 2014-06-11 17:42:49 +0000
1202+++ src/server/input/cursor_controller.h 2014-09-18 16:04:44 +0000
1203@@ -39,12 +39,12 @@
1204
1205 namespace input
1206 {
1207-class InputTargets;
1208+class Scene;
1209
1210 class CursorController : public CursorListener
1211 {
1212 public:
1213- CursorController(std::shared_ptr<InputTargets> const& input_targets,
1214+ CursorController(std::shared_ptr<Scene> const& input_targets,
1215 std::shared_ptr<graphics::Cursor> const& cursor,
1216 std::shared_ptr<graphics::CursorImage> const& default_cursor_image);
1217 virtual ~CursorController();
1218@@ -56,7 +56,7 @@
1219 void update_cursor_image();
1220
1221 private:
1222- std::shared_ptr<InputTargets> const input_targets;
1223+ std::shared_ptr<Scene> const input_targets;
1224 std::shared_ptr<graphics::Cursor> const cursor;
1225 std::shared_ptr<graphics::CursorImage> const default_cursor_image;
1226
1227
1228=== modified file 'src/server/input/default_configuration.cpp'
1229--- src/server/input/default_configuration.cpp 2014-09-10 12:50:53 +0000
1230+++ src/server/input/default_configuration.cpp 2014-09-18 16:04:44 +0000
1231@@ -30,6 +30,7 @@
1232 #include "event_filter_chain.h"
1233 #include "null_input_configuration.h"
1234 #include "cursor_controller.h"
1235+#include "touchspot_controller.h"
1236 #include "null_input_dispatcher.h"
1237 #include "null_input_targeter.h"
1238 #include "xcursor_loader.h"
1239@@ -114,7 +115,7 @@
1240 auto dispatcher = std::make_shared<droidinput::InputDispatcher>(
1241 the_dispatcher_policy(),
1242 the_input_report(),
1243- std::make_shared<mia::InputTargetEnumerator>(the_input_targets(), registrar));
1244+ std::make_shared<mia::InputTargetEnumerator>(the_input_scene(), registrar));
1245 registrar->set_dispatcher(dispatcher);
1246 return dispatcher;
1247 });
1248@@ -234,7 +235,7 @@
1249 return cursor_listener(
1250 [this]() -> std::shared_ptr<mi::CursorListener>
1251 {
1252- return std::make_shared<mi::CursorController>(the_input_targets(),
1253+ return std::make_shared<mi::CursorController>(the_input_scene(),
1254 the_cursor(), the_default_cursor_image());
1255 });
1256
1257@@ -243,16 +244,21 @@
1258 std::shared_ptr<mi::TouchVisualizer>
1259 mir::DefaultServerConfiguration::the_touch_visualizer()
1260 {
1261- struct NullTouchVisualizer : public mi::TouchVisualizer
1262- {
1263- void visualize_touches(std::vector<Spot> const& /* touches */) override
1264- {
1265- }
1266- };
1267 return touch_visualizer(
1268- [this]()
1269+ [this]() -> std::shared_ptr<mi::TouchVisualizer>
1270 {
1271- return std::make_shared<NullTouchVisualizer>();
1272+ auto visualizer = std::make_shared<mi::TouchspotController>(the_buffer_allocator(), the_buffer_writer(),
1273+ the_input_scene());
1274+
1275+ // The visualizer is disabled by default and can be enabled statically via
1276+ // the MIR_SERVER_ENABLE_TOUCHSPOTS option. In the USC/unity8/autopilot case
1277+ // it will be toggled at runtime via com.canonical.Unity.Screen DBus interface
1278+ if (the_options()->is_set(options::touchspots_opt))
1279+ {
1280+ visualizer->enable();
1281+ }
1282+
1283+ return visualizer;
1284 });
1285 }
1286
1287
1288=== added file 'src/server/input/touchspot_controller.cpp'
1289--- src/server/input/touchspot_controller.cpp 1970-01-01 00:00:00 +0000
1290+++ src/server/input/touchspot_controller.cpp 2014-09-18 16:04:44 +0000
1291@@ -0,0 +1,166 @@
1292+/*
1293+ * Copyright © 2014 Canonical Ltd.
1294+ *
1295+ * This program is free software: you can redistribute it and/or modify it
1296+ * under the terms of the GNU General Public License version 3,
1297+ * as published by the Free Software Foundation.
1298+ *
1299+ * This program is distributed in the hope that it will be useful,
1300+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1301+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1302+ * GNU General Public License for more details.
1303+ *
1304+ * You should have received a copy of the GNU General Public License
1305+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1306+ *
1307+ * Authored by: Robert Carr <robert.carr@canonical.com>
1308+ */
1309+
1310+#include "touchspot_controller.h"
1311+#include "touchspot_image.c"
1312+
1313+#include "mir/graphics/graphic_buffer_allocator.h"
1314+#include "mir/graphics/buffer_properties.h"
1315+#include "mir/graphics/buffer.h"
1316+#include "mir/graphics/buffer_writer.h"
1317+#include "mir/graphics/renderable.h"
1318+#include "mir/geometry/dimensions.h"
1319+#include "mir/input/scene.h"
1320+
1321+namespace mi = mir::input;
1322+namespace mg = mir::graphics;
1323+namespace geom = mir::geometry;
1324+
1325+namespace
1326+{
1327+geom::Size const touchspot_size = {touchspot_image.width, touchspot_image.height};
1328+MirPixelFormat const touchspot_pixel_format = mir_pixel_format_argb_8888;
1329+}
1330+
1331+class mi::TouchspotRenderable : public mg::Renderable
1332+{
1333+public:
1334+ TouchspotRenderable(std::shared_ptr<mg::Buffer> const& buffer)
1335+ : buffer_(buffer),
1336+ position({0, 0})
1337+ {
1338+ }
1339+
1340+// mg::Renderable
1341+ mg::Renderable::ID id() const override
1342+ {
1343+ return this;
1344+ }
1345+
1346+ std::shared_ptr<mg::Buffer> buffer() const override
1347+ {
1348+ return buffer_;
1349+ }
1350+
1351+ bool alpha_enabled() const override
1352+ {
1353+ return false;
1354+ }
1355+
1356+ geom::Rectangle screen_position() const
1357+ {
1358+ return {position, buffer_->size()};
1359+ }
1360+
1361+ float alpha() const
1362+ {
1363+ return 1.0;
1364+ }
1365+
1366+ glm::mat4 transformation() const
1367+ {
1368+ return glm::mat4();
1369+ }
1370+
1371+ bool visible() const
1372+ {
1373+ return true;
1374+ }
1375+
1376+ bool shaped() const
1377+ {
1378+ return true;
1379+ }
1380+
1381+ int buffers_ready_for_compositor() const
1382+ {
1383+ return 1;
1384+ }
1385+
1386+// TouchspotRenderable
1387+ void move_center_to(geom::Point pos)
1388+ {
1389+ std::lock_guard<std::mutex> lg(guard);
1390+ position = {pos.x.as_int() - touchspot_image.width/2, pos.y.as_int() - touchspot_image.height/2};
1391+ }
1392+
1393+
1394+private:
1395+ std::shared_ptr<mg::Buffer> const buffer_;
1396+
1397+ std::mutex guard;
1398+ geom::Point position;
1399+};
1400+
1401+
1402+mi::TouchspotController::TouchspotController(std::shared_ptr<mg::GraphicBufferAllocator> const& allocator,
1403+ std::shared_ptr<mg::BufferWriter> const& buffer_writer,
1404+ std::shared_ptr<mi::Scene> const& scene)
1405+ : touchspot_buffer(allocator->alloc_buffer({touchspot_size, touchspot_pixel_format, mg::BufferUsage::software})),
1406+ scene(scene),
1407+ enabled(false),
1408+ renderables_in_use(0)
1409+{
1410+ unsigned int const pixels_size = touchspot_size.width.as_uint32_t()*touchspot_size.height.as_uint32_t() *
1411+ MIR_BYTES_PER_PIXEL(touchspot_pixel_format);
1412+
1413+ buffer_writer->write(*touchspot_buffer, touchspot_image.pixel_data, pixels_size);
1414+}
1415+
1416+void mi::TouchspotController::visualize_touches(std::vector<Spot> const& touches)
1417+{
1418+ {
1419+ std::lock_guard<std::mutex> lg(guard);
1420+
1421+ unsigned int const num_touches = enabled ? touches.size() : 0;
1422+
1423+ while (touchspot_renderables.size() < num_touches)
1424+ touchspot_renderables.push_back(std::make_shared<TouchspotRenderable>(touchspot_buffer));
1425+
1426+ for (unsigned int i = 0; i < num_touches; i++)
1427+ {
1428+ auto const& renderable = touchspot_renderables[i];
1429+
1430+ renderable->move_center_to(touches[i].touch_location);
1431+ if (i >= renderables_in_use)
1432+ scene->add_input_visualization(renderable);
1433+ }
1434+
1435+ for (unsigned int i = num_touches; i < renderables_in_use; i++)
1436+ scene->remove_input_visualization(touchspot_renderables[i]);
1437+
1438+ renderables_in_use = num_touches;
1439+ } // release mutex
1440+
1441+ // TODO (hackish): We may have just moved renderables which with the current
1442+ // architecture of surface observers will not trigger a propagation to the
1443+ // compositor damage callback we need this "emit_scene_changed".
1444+ scene->emit_scene_changed();
1445+}
1446+
1447+void mi::TouchspotController::enable()
1448+{
1449+ std::lock_guard<std::mutex> lg(guard);
1450+ enabled = true;
1451+}
1452+
1453+void mi::TouchspotController::disable()
1454+{
1455+ std::lock_guard<std::mutex> lg(guard);
1456+ enabled = false;
1457+}
1458
1459=== added file 'src/server/input/touchspot_controller.h'
1460--- src/server/input/touchspot_controller.h 1970-01-01 00:00:00 +0000
1461+++ src/server/input/touchspot_controller.h 2014-09-18 16:04:44 +0000
1462@@ -0,0 +1,77 @@
1463+/*
1464+ * Copyright © 2014 Canonical Ltd.
1465+ *
1466+ * This program is free software: you can redistribute it and/or modify it
1467+ * under the terms of the GNU General Public License version 3,
1468+ * as published by the Free Software Foundation.
1469+ *
1470+ * This program is distributed in the hope that it will be useful,
1471+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1472+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1473+ * GNU General Public License for more details.
1474+ *
1475+ * You should have received a copy of the GNU General Public License
1476+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1477+ *
1478+ * Authored by: Robert Carr <robert.carr@canonical.com>
1479+ */
1480+
1481+#ifndef MIR_INPUT_TOUCHSPOT_CONTROLLER_H_
1482+#define MIR_INPUT_TOUCHSPOT_CONTROLLER_H_
1483+
1484+#include "mir/input/touch_visualizer.h"
1485+
1486+#include <memory>
1487+#include <mutex>
1488+
1489+namespace mir
1490+{
1491+namespace graphics
1492+{
1493+class GraphicBufferAllocator;
1494+class Buffer;
1495+class BufferWriter;
1496+class Renderable;
1497+}
1498+namespace input
1499+{
1500+class Scene;
1501+class TouchspotRenderable;
1502+
1503+/// Receives touchspot events out of the input stack and manages appearance
1504+/// of touchspot renderables for visualization. Touchspot visualization is
1505+/// disabled by default and must be enabled through a call to ::enable.
1506+class TouchspotController : public TouchVisualizer
1507+{
1508+public:
1509+ TouchspotController(std::shared_ptr<graphics::GraphicBufferAllocator> const& allocator,
1510+ std::shared_ptr<graphics::BufferWriter> const& writer,
1511+ std::shared_ptr<input::Scene> const& scene);
1512+
1513+ virtual ~TouchspotController() = default;
1514+
1515+ void enable() override;
1516+ void disable() override;
1517+
1518+ void visualize_touches(std::vector<Spot> const& touches) override;
1519+
1520+protected:
1521+ TouchspotController(TouchspotController const&) = delete;
1522+ TouchspotController& operator=(TouchspotController const&) = delete;
1523+
1524+private:
1525+ std::shared_ptr<graphics::Buffer> touchspot_buffer;
1526+ std::shared_ptr<Scene> scene;
1527+
1528+ std::mutex guard;
1529+
1530+ bool enabled;
1531+
1532+ unsigned int renderables_in_use;
1533+ std::vector<std::shared_ptr<TouchspotRenderable>> touchspot_renderables;
1534+};
1535+
1536+}
1537+}
1538+
1539+#endif // MIR_INPUT_TOUCHSPOT_CONTROLLER_H_
1540
1541=== added file 'src/server/input/touchspot_image.c'
1542--- src/server/input/touchspot_image.c 1970-01-01 00:00:00 +0000
1543+++ src/server/input/touchspot_image.c 2014-09-18 16:04:44 +0000
1544@@ -0,0 +1,1034 @@
1545+/* GIMP RGBA C-Source image dump (spot.c) */
1546+
1547+static const struct {
1548+ unsigned int width;
1549+ unsigned int height;
1550+ unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */
1551+ unsigned char pixel_data[64 * 64 * 4 + 1];
1552+} touchspot_image = {
1553+ 64, 64, 4,
1554+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1555+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1556+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1557+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1558+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1559+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1560+0,0,0,5,0,0,0,65,0,0,0,104,0,0,0,129,
1561+0,0,0,154,0,0,0,179,0,0,0,204,0,0,0,230,
1562+0,0,0,230,0,0,0,204,0,0,0,179,0,0,0,154,
1563+0,0,0,129,0,0,0,104,0,0,0,65,0,0,0,5,
1564+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1565+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1566+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1567+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1568+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1569+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1570+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1571+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1572+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1573+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1574+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1575+0,0,0,0,0,0,0,15,0,0,0,88,0,0,0,166,
1576+0,0,0,240,0,0,0,255,0,0,0,255,0,0,0,255,
1577+0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,
1578+0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,
1579+0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,240,
1580+0,0,0,166,0,0,0,88,0,0,0,15,0,0,0,0,
1581+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1582+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1583+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1584+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1585+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1586+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1587+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1588+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1589+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1590+0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,95,
1591+0,0,0,187,0,0,0,250,0,0,0,255,0,0,0,255,
1592+0,0,0,255,0,15,28,255,0,45,82,255,0,60,108,255,
1593+0,75,135,255,0,89,161,255,0,104,188,255,0,119,215,255,
1594+0,119,215,255,0,104,188,255,0,89,161,255,0,75,135,255,
1595+0,60,108,255,0,45,82,255,0,15,28,255,0,0,0,255,
1596+0,0,0,255,0,0,0,255,0,0,0,250,0,0,0,187,
1597+0,0,0,95,0,0,0,3,0,0,0,0,0,0,0,0,
1598+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1599+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1600+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1601+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1602+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1603+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1604+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1605+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1606+0,0,0,0,0,0,0,83,0,0,0,215,0,0,0,255,
1607+0,0,0,255,0,0,0,255,0,27,49,255,0,70,126,255,
1608+0,112,203,255,0,139,251,255,0,139,251,255,0,139,251,255,
1609+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1610+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1611+0,139,251,255,0,139,251,255,0,139,251,255,0,112,203,255,
1612+0,70,126,255,0,27,49,255,0,0,0,255,0,0,0,255,
1613+0,0,0,255,0,0,0,215,0,0,0,83,0,0,0,0,
1614+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1615+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1616+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1617+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1618+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1619+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1620+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1621+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,
1622+0,0,0,203,0,0,0,255,0,0,0,255,0,12,22,255,
1623+0,77,139,255,0,124,223,255,0,139,251,255,0,139,251,255,
1624+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1625+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1626+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1627+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1628+0,139,251,255,0,139,251,255,0,124,223,255,0,77,139,255,
1629+0,13,23,255,0,0,0,255,0,0,0,255,0,0,0,203,
1630+0,0,0,69,0,0,0,0,0,0,0,0,0,0,0,0,
1631+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1632+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1633+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1634+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1635+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1636+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1637+0,0,0,0,0,0,0,24,0,0,0,187,0,0,0,255,
1638+0,0,0,255,0,8,14,255,0,71,128,255,0,133,240,255,
1639+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1640+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1641+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1642+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1643+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1644+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1645+0,133,240,255,0,72,130,255,0,8,15,255,0,0,0,255,
1646+0,0,0,255,0,0,0,187,0,0,0,24,0,0,0,0,
1647+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1648+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1649+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1650+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1651+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1652+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1653+0,0,0,53,0,0,0,228,0,0,0,255,0,4,7,255,
1654+0,62,112,255,0,129,232,255,0,139,251,255,0,139,251,255,
1655+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1656+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1657+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1658+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1659+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1660+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1661+0,139,251,255,0,139,251,255,0,129,233,255,0,63,114,255,
1662+0,4,8,255,0,0,0,255,0,0,0,228,0,0,0,53,
1663+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1664+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1665+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1666+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1667+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1668+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,
1669+0,0,0,247,0,0,0,255,0,28,51,255,0,122,220,255,
1670+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1671+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1672+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1673+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1674+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1675+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1676+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1677+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1678+0,123,221,255,0,28,50,255,0,0,0,255,0,0,0,247,
1679+0,0,0,92,0,0,0,0,0,0,0,0,0,0,0,0,
1680+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1681+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1682+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1683+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1684+0,0,0,0,0,0,0,3,0,0,0,140,0,0,0,255,
1685+0,0,0,255,0,49,89,255,0,134,242,255,0,139,251,255,
1686+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1687+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1688+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1689+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1690+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1691+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1692+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1693+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1694+0,139,251,255,0,134,242,255,0,47,86,255,0,0,0,255,
1695+0,0,0,255,0,0,0,140,0,0,0,3,0,0,0,0,
1696+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1697+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1698+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1699+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1700+0,0,0,5,0,0,0,181,0,0,0,255,0,1,2,255,
1701+0,74,133,255,0,139,251,255,0,139,251,255,0,139,251,255,
1702+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1703+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1704+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1705+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1706+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1707+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1708+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1709+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1710+0,139,251,255,0,139,251,255,0,139,251,255,0,71,129,255,
1711+0,1,1,255,0,0,0,255,0,0,0,178,0,0,0,3,
1712+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1713+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1714+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1715+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1716+0,0,0,151,0,0,0,255,0,7,14,255,0,98,177,255,
1717+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1718+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1719+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1720+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1721+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1722+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1723+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1724+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1725+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1726+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1727+0,95,172,255,0,6,12,255,0,0,0,255,0,0,0,143,
1728+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1729+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1730+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1731+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,
1732+0,0,0,255,0,2,4,255,0,105,189,255,0,139,251,255,
1733+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1734+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1735+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1736+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1737+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1738+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1739+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1740+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1741+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1742+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1743+0,139,251,255,0,101,182,255,0,2,3,255,0,0,0,255,
1744+0,0,0,95,0,0,0,0,0,0,0,0,0,0,0,0,
1745+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1746+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1747+0,0,0,0,0,0,0,0,0,0,0,61,0,0,0,250,
1748+0,0,0,255,0,81,147,255,0,139,251,255,0,139,251,255,
1749+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1750+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1751+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1752+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1753+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1754+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1755+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1756+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1757+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1758+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1759+0,139,251,255,0,139,251,255,0,76,138,255,0,0,0,255,
1760+0,0,0,248,0,0,0,55,0,0,0,0,0,0,0,0,
1761+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1762+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1763+0,0,0,0,0,0,0,30,0,0,0,234,0,0,0,255,
1764+0,56,100,255,0,139,251,255,0,139,251,255,0,139,251,255,
1765+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1766+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1767+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1768+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1769+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1770+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1771+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1772+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1773+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1774+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1775+0,139,251,255,0,139,251,255,0,139,251,255,0,51,92,255,
1776+0,0,0,255,0,0,0,230,0,0,0,26,0,0,0,0,
1777+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1778+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1779+0,0,0,0,0,0,0,195,0,0,0,255,0,33,59,255,
1780+0,136,246,255,0,139,251,255,0,139,251,255,0,139,251,255,
1781+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1782+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1783+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1784+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1785+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1786+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1787+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1788+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1789+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1790+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1791+0,139,251,255,0,139,251,255,0,139,251,255,0,135,243,255,
1792+0,29,52,255,0,0,0,255,0,0,0,193,0,0,0,0,
1793+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1794+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1795+0,0,0,79,0,0,0,255,0,8,14,255,0,126,228,255,
1796+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1797+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1798+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1799+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1800+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1801+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1802+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1803+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1804+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1805+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1806+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1807+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1808+0,124,224,255,0,8,15,255,0,0,0,255,0,0,0,77,
1809+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1810+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,
1811+0,0,0,213,0,0,0,255,0,71,129,255,0,139,251,255,
1812+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1813+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1814+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1815+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1816+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1817+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1818+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1819+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1820+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1821+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1822+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1823+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1824+0,139,251,255,0,72,130,255,0,0,0,255,0,0,0,211,
1825+0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,
1826+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,98,
1827+0,0,0,255,0,14,25,255,0,134,241,255,0,139,251,255,
1828+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1829+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1830+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1831+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1832+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1833+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1834+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1835+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1836+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1837+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1838+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1839+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1840+0,139,251,255,0,133,240,255,0,13,24,255,0,0,0,255,
1841+0,0,0,93,0,0,0,0,0,0,0,0,0,0,0,0,
1842+0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,227,
1843+0,0,0,255,0,83,150,255,0,139,251,255,0,139,251,255,
1844+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1845+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1846+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1847+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1848+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1849+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1850+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1851+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1852+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1853+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1854+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1855+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1856+0,139,251,255,0,139,251,255,0,81,147,255,0,0,0,255,
1857+0,0,0,223,0,0,0,6,0,0,0,0,0,0,0,0,
1858+0,0,0,0,0,0,0,0,0,0,0,115,0,0,0,255,
1859+0,21,37,255,0,137,247,255,0,139,251,255,0,139,251,255,
1860+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1861+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1862+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1863+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1864+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1865+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1866+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1867+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1868+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1869+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1870+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1871+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1872+0,139,251,255,0,139,251,255,0,136,246,255,0,19,34,255,
1873+0,0,0,255,0,0,0,110,0,0,0,0,0,0,0,0,
1874+0,0,0,0,0,0,0,0,0,0,0,209,0,0,0,255,
1875+0,88,159,255,0,139,251,255,0,139,251,255,0,139,251,255,
1876+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1877+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1878+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1879+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1880+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1881+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1882+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1883+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1884+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1885+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1886+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1887+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1888+0,139,251,255,0,139,251,255,0,139,251,255,0,88,158,255,
1889+0,0,0,255,0,0,0,209,0,0,0,0,0,0,0,0,
1890+0,0,0,0,0,0,0,32,0,0,0,255,0,3,6,255,
1891+0,131,237,255,0,139,251,255,0,139,251,255,0,139,251,255,
1892+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1893+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1894+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1895+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1896+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1897+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1898+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1899+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1900+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1901+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1902+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1903+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1904+0,139,251,255,0,139,251,255,0,139,251,255,0,132,239,255,
1905+0,4,7,255,0,0,0,255,0,0,0,32,0,0,0,0,
1906+0,0,0,0,0,0,0,111,0,0,0,255,0,38,69,255,
1907+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1908+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1909+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1910+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1911+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1912+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1913+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1914+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1915+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1916+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1917+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1918+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1919+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1920+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1921+0,39,71,255,0,0,0,255,0,0,0,111,0,0,0,0,
1922+0,0,0,0,0,0,0,189,0,0,0,255,0,81,147,255,
1923+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1924+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1925+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1926+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1927+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1928+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1929+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1930+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1931+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1932+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1933+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1934+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1935+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1936+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1937+0,82,149,255,0,0,0,255,0,0,0,189,0,0,0,0,
1938+0,0,0,17,0,0,0,251,0,1,1,255,0,124,224,255,
1939+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1940+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1941+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1942+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1943+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1944+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1945+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1946+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1947+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1948+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1949+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1950+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1951+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1952+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1953+0,124,224,255,0,1,1,255,0,0,0,251,0,0,0,17,
1954+0,0,0,89,0,0,0,255,0,28,51,255,0,139,251,255,
1955+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1956+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1957+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1958+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1959+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1960+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1961+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1962+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1963+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1964+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1965+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1966+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1967+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1968+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1969+0,139,251,255,0,28,50,255,0,0,0,255,0,0,0,89,
1970+0,0,0,128,0,0,0,255,0,63,114,255,0,139,251,255,
1971+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1972+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1973+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1974+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1975+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1976+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1977+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1978+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1979+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1980+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1981+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1982+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1983+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1984+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1985+0,139,251,255,0,58,104,255,0,0,0,255,0,0,0,128,
1986+0,0,0,155,0,0,0,255,0,77,140,255,0,139,251,255,
1987+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1988+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1989+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1990+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1991+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1992+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1993+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1994+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1995+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1996+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1997+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1998+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
1999+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2000+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2001+0,139,251,255,0,73,132,255,0,0,0,255,0,0,0,155,
2002+0,0,0,181,0,0,0,255,0,91,164,255,0,139,251,255,
2003+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2004+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2005+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2006+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2007+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2008+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2009+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2010+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2011+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2012+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2013+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2014+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2015+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2016+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2017+0,139,251,255,0,88,158,255,0,0,0,255,0,0,0,181,
2018+0,0,0,208,0,0,0,255,0,105,190,255,0,139,251,255,
2019+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2020+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2021+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2022+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2023+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2024+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2025+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2026+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2027+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2028+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2029+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2030+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2031+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2032+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2033+0,139,251,255,0,102,185,255,0,0,0,255,0,0,0,208,
2034+0,0,0,234,0,0,0,255,0,119,215,255,0,139,251,255,
2035+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2036+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2037+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2038+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2039+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2040+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2041+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2042+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2043+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2044+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2045+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2046+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2047+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2048+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2049+0,139,251,255,0,117,212,255,0,0,0,255,0,0,0,234,
2050+0,0,0,254,0,0,0,255,0,132,239,255,0,139,251,255,
2051+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2052+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2053+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2054+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2055+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2056+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2057+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2058+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2059+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2060+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2061+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2062+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2063+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2064+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2065+0,139,251,255,0,132,238,255,0,0,0,255,0,0,0,254,
2066+0,0,0,254,0,0,0,255,0,132,239,255,0,139,251,255,
2067+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2068+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2069+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2070+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2071+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2072+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2073+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2074+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2075+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2076+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2077+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2078+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2079+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2080+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2081+0,139,251,255,0,132,238,255,0,0,0,255,0,0,0,254,
2082+0,0,0,234,0,0,0,255,0,119,215,255,0,139,251,255,
2083+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2084+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2085+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2086+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2087+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2088+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2089+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2090+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2091+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2092+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2093+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2094+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2095+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2096+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2097+0,139,251,255,0,117,212,255,0,0,0,255,0,0,0,234,
2098+0,0,0,208,0,0,0,255,0,105,190,255,0,139,251,255,
2099+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2100+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2101+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2102+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2103+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2104+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2105+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2106+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2107+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2108+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2109+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2110+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2111+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2112+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2113+0,139,251,255,0,102,185,255,0,0,0,255,0,0,0,208,
2114+0,0,0,181,0,0,0,255,0,91,164,255,0,139,251,255,
2115+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2116+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2117+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2118+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2119+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2120+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2121+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2122+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2123+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2124+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2125+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2126+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2127+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2128+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2129+0,139,251,255,0,88,158,255,0,0,0,255,0,0,0,181,
2130+0,0,0,155,0,0,0,255,0,77,140,255,0,139,251,255,
2131+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2132+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2133+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2134+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2135+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2136+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2137+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2138+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2139+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2140+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2141+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2142+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2143+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2144+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2145+0,139,251,255,0,73,132,255,0,0,0,255,0,0,0,155,
2146+0,0,0,128,0,0,0,255,0,63,114,255,0,139,251,255,
2147+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2148+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2149+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2150+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2151+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2152+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2153+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2154+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2155+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2156+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2157+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2158+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2159+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2160+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2161+0,139,251,255,0,58,104,255,0,0,0,255,0,0,0,128,
2162+0,0,0,89,0,0,0,255,0,28,51,255,0,139,251,255,
2163+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2164+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2165+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2166+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2167+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2168+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2169+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2170+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2171+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2172+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2173+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2174+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2175+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2176+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2177+0,139,251,255,0,28,50,255,0,0,0,255,0,0,0,89,
2178+0,0,0,17,0,0,0,251,0,1,1,255,0,124,224,255,
2179+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2180+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2181+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2182+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2183+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2184+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2185+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2186+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2187+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2188+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2189+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2190+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2191+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2192+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2193+0,124,224,255,0,1,1,255,0,0,0,251,0,0,0,17,
2194+0,0,0,0,0,0,0,189,0,0,0,255,0,81,147,255,
2195+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2196+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2197+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2198+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2199+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2200+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2201+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2202+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2203+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2204+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2205+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2206+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2207+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2208+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2209+0,82,149,255,0,0,0,255,0,0,0,189,0,0,0,0,
2210+0,0,0,0,0,0,0,111,0,0,0,255,0,38,69,255,
2211+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2212+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2213+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2214+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2215+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2216+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2217+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2218+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2219+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2220+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2221+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2222+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2223+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2224+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2225+0,39,71,255,0,0,0,255,0,0,0,111,0,0,0,0,
2226+0,0,0,0,0,0,0,32,0,0,0,255,0,3,6,255,
2227+0,131,237,255,0,139,251,255,0,139,251,255,0,139,251,255,
2228+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2229+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2230+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2231+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2232+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2233+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2234+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2235+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2236+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2237+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2238+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2239+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2240+0,139,251,255,0,139,251,255,0,139,251,255,0,132,239,255,
2241+0,4,7,255,0,0,0,255,0,0,0,32,0,0,0,0,
2242+0,0,0,0,0,0,0,0,0,0,0,209,0,0,0,255,
2243+0,88,159,255,0,139,251,255,0,139,251,255,0,139,251,255,
2244+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2245+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2246+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2247+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2248+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2249+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2250+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2251+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2252+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2253+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2254+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2255+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2256+0,139,251,255,0,139,251,255,0,139,251,255,0,88,158,255,
2257+0,0,0,255,0,0,0,209,0,0,0,0,0,0,0,0,
2258+0,0,0,0,0,0,0,0,0,0,0,115,0,0,0,255,
2259+0,21,37,255,0,137,247,255,0,139,251,255,0,139,251,255,
2260+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2261+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2262+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2263+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2264+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2265+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2266+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2267+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2268+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2269+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2270+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2271+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2272+0,139,251,255,0,139,251,255,0,136,246,255,0,19,34,255,
2273+0,0,0,255,0,0,0,110,0,0,0,0,0,0,0,0,
2274+0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,227,
2275+0,0,0,255,0,83,150,255,0,139,251,255,0,139,251,255,
2276+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2277+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2278+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2279+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2280+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2281+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2282+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2283+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2284+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2285+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2286+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2287+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2288+0,139,251,255,0,139,251,255,0,81,147,255,0,0,0,255,
2289+0,0,0,223,0,0,0,6,0,0,0,0,0,0,0,0,
2290+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,98,
2291+0,0,0,255,0,14,25,255,0,134,241,255,0,139,251,255,
2292+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2293+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2294+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2295+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2296+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2297+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2298+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2299+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2300+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2301+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2302+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2303+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2304+0,139,251,255,0,133,240,255,0,13,24,255,0,0,0,255,
2305+0,0,0,93,0,0,0,0,0,0,0,0,0,0,0,0,
2306+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,
2307+0,0,0,213,0,0,0,255,0,71,129,255,0,139,251,255,
2308+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2309+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2310+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2311+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2312+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2313+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2314+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2315+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2316+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2317+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2318+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2319+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2320+0,139,251,255,0,72,130,255,0,0,0,255,0,0,0,211,
2321+0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,
2322+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2323+0,0,0,79,0,0,0,255,0,8,14,255,0,126,228,255,
2324+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2325+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2326+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2327+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2328+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2329+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2330+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2331+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2332+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2333+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2334+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2335+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2336+0,124,224,255,0,8,15,255,0,0,0,255,0,0,0,77,
2337+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2338+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2339+0,0,0,0,0,0,0,195,0,0,0,255,0,33,59,255,
2340+0,136,246,255,0,139,251,255,0,139,251,255,0,139,251,255,
2341+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2342+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2343+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2344+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2345+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2346+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2347+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2348+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2349+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2350+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2351+0,139,251,255,0,139,251,255,0,139,251,255,0,135,243,255,
2352+0,29,52,255,0,0,0,255,0,0,0,193,0,0,0,0,
2353+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2354+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2355+0,0,0,0,0,0,0,30,0,0,0,234,0,0,0,255,
2356+0,56,100,255,0,139,251,255,0,139,251,255,0,139,251,255,
2357+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2358+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2359+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2360+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2361+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2362+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2363+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2364+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2365+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2366+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2367+0,139,251,255,0,139,251,255,0,139,251,255,0,51,92,255,
2368+0,0,0,255,0,0,0,230,0,0,0,26,0,0,0,0,
2369+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2370+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2371+0,0,0,0,0,0,0,0,0,0,0,61,0,0,0,250,
2372+0,0,0,255,0,81,147,255,0,139,251,255,0,139,251,255,
2373+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2374+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2375+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2376+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2377+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2378+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2379+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2380+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2381+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2382+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2383+0,139,251,255,0,139,251,255,0,76,138,255,0,0,0,255,
2384+0,0,0,248,0,0,0,55,0,0,0,0,0,0,0,0,
2385+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2386+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2387+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,
2388+0,0,0,255,0,2,4,255,0,105,189,255,0,139,251,255,
2389+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2390+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2391+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2392+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2393+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2394+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2395+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2396+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2397+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2398+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2399+0,139,251,255,0,101,182,255,0,2,3,255,0,0,0,255,
2400+0,0,0,95,0,0,0,0,0,0,0,0,0,0,0,0,
2401+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2402+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2403+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2404+0,0,0,151,0,0,0,255,0,7,14,255,0,98,177,255,
2405+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2406+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2407+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2408+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2409+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2410+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2411+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2412+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2413+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2414+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2415+0,95,172,255,0,6,12,255,0,0,0,255,0,0,0,143,
2416+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2417+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2418+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2419+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2420+0,0,0,5,0,0,0,181,0,0,0,255,0,1,2,255,
2421+0,74,133,255,0,139,251,255,0,139,251,255,0,139,251,255,
2422+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2423+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2424+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2425+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2426+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2427+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2428+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2429+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2430+0,139,251,255,0,139,251,255,0,139,251,255,0,71,129,255,
2431+0,1,1,255,0,0,0,255,0,0,0,178,0,0,0,3,
2432+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2433+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2434+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2435+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2436+0,0,0,0,0,0,0,3,0,0,0,140,0,0,0,255,
2437+0,0,0,255,0,49,89,255,0,134,242,255,0,139,251,255,
2438+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2439+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2440+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2441+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2442+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2443+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2444+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2445+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2446+0,139,251,255,0,134,242,255,0,47,86,255,0,0,0,255,
2447+0,0,0,255,0,0,0,140,0,0,0,3,0,0,0,0,
2448+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2449+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2450+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2451+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2452+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,
2453+0,0,0,247,0,0,0,255,0,28,51,255,0,122,220,255,
2454+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2455+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2456+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2457+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2458+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2459+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2460+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2461+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2462+0,123,221,255,0,28,50,255,0,0,0,255,0,0,0,247,
2463+0,0,0,92,0,0,0,0,0,0,0,0,0,0,0,0,
2464+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2465+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2466+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2467+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2468+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2469+0,0,0,53,0,0,0,228,0,0,0,255,0,4,7,255,
2470+0,62,112,255,0,129,232,255,0,139,251,255,0,139,251,255,
2471+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2472+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2473+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2474+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2475+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2476+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2477+0,139,251,255,0,139,251,255,0,129,233,255,0,63,114,255,
2478+0,4,8,255,0,0,0,255,0,0,0,228,0,0,0,53,
2479+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2480+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2481+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2482+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2483+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2484+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2485+0,0,0,0,0,0,0,24,0,0,0,187,0,0,0,255,
2486+0,0,0,255,0,8,14,255,0,71,128,255,0,133,240,255,
2487+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2488+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2489+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2490+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2491+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2492+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2493+0,133,240,255,0,72,130,255,0,8,15,255,0,0,0,255,
2494+0,0,0,255,0,0,0,187,0,0,0,24,0,0,0,0,
2495+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2496+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2497+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2498+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2499+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2500+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2501+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,69,
2502+0,0,0,203,0,0,0,255,0,0,0,255,0,12,22,255,
2503+0,77,139,255,0,124,223,255,0,139,251,255,0,139,251,255,
2504+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2505+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2506+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2507+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2508+0,139,251,255,0,139,251,255,0,124,223,255,0,77,139,255,
2509+0,13,23,255,0,0,0,255,0,0,0,255,0,0,0,203,
2510+0,0,0,69,0,0,0,0,0,0,0,0,0,0,0,0,
2511+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2512+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2513+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2514+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2515+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2516+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2517+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2518+0,0,0,0,0,0,0,83,0,0,0,215,0,0,0,255,
2519+0,0,0,255,0,0,0,255,0,27,49,255,0,70,126,255,
2520+0,112,203,255,0,139,251,255,0,139,251,255,0,139,251,255,
2521+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2522+0,139,251,255,0,139,251,255,0,139,251,255,0,139,251,255,
2523+0,139,251,255,0,139,251,255,0,139,251,255,0,112,203,255,
2524+0,70,126,255,0,27,49,255,0,0,0,255,0,0,0,255,
2525+0,0,0,255,0,0,0,215,0,0,0,83,0,0,0,0,
2526+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2527+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2528+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2529+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2530+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2531+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2532+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2533+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2534+0,0,0,0,0,0,0,0,0,0,0,3,0,0,0,95,
2535+0,0,0,187,0,0,0,250,0,0,0,255,0,0,0,255,
2536+0,0,0,255,0,15,28,255,0,45,82,255,0,60,108,255,
2537+0,75,135,255,0,89,161,255,0,104,188,255,0,119,215,255,
2538+0,119,215,255,0,104,188,255,0,89,161,255,0,75,135,255,
2539+0,60,108,255,0,45,82,255,0,15,28,255,0,0,0,255,
2540+0,0,0,255,0,0,0,255,0,0,0,250,0,0,0,187,
2541+0,0,0,95,0,0,0,3,0,0,0,0,0,0,0,0,
2542+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2543+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2544+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2545+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2546+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2547+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2548+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2549+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2550+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2551+0,0,0,0,0,0,0,15,0,0,0,88,0,0,0,166,
2552+0,0,0,240,0,0,0,255,0,0,0,255,0,0,0,255,
2553+0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,
2554+0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,255,
2555+0,0,0,255,0,0,0,255,0,0,0,255,0,0,0,240,
2556+0,0,0,166,0,0,0,88,0,0,0,15,0,0,0,0,
2557+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2558+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2559+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2560+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2561+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2562+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2563+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2564+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2565+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2566+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2567+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2568+0,0,0,5,0,0,0,65,0,0,0,104,0,0,0,129,
2569+0,0,0,154,0,0,0,179,0,0,0,204,0,0,0,230,
2570+0,0,0,230,0,0,0,204,0,0,0,179,0,0,0,154,
2571+0,0,0,129,0,0,0,104,0,0,0,65,0,0,0,5,
2572+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2573+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2574+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2575+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2576+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
2577+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
2578+};
2579
2580=== modified file 'src/server/scene/basic_surface.cpp'
2581--- src/server/scene/basic_surface.cpp 2014-09-10 12:50:53 +0000
2582+++ src/server/scene/basic_surface.cpp 2014-09-18 16:04:44 +0000
2583@@ -667,7 +667,6 @@
2584
2585 mg::Renderable::ID id() const override
2586 { return id_; }
2587-
2588 private:
2589 std::shared_ptr<mc::BufferStream> const underlying_buffer_stream;
2590 std::shared_ptr<mg::Buffer> mutable compositor_buffer;
2591
2592=== modified file 'src/server/scene/default_configuration.cpp'
2593--- src/server/scene/default_configuration.cpp 2014-09-10 12:50:53 +0000
2594+++ src/server/scene/default_configuration.cpp 2014-09-18 16:04:44 +0000
2595@@ -20,7 +20,7 @@
2596
2597 #include "mir/graphics/display.h"
2598 #include "mir/graphics/gl_context.h"
2599-#include "mir/input/input_targets.h"
2600+#include "mir/input/scene.h"
2601 #include "mir/abnormal_exit.h"
2602 #include "mir/scene/session.h"
2603
2604@@ -57,7 +57,7 @@
2605 { return std::make_shared<ms::SurfaceStack>(the_scene_report()); });
2606 }
2607
2608-std::shared_ptr<mi::InputTargets> mir::DefaultServerConfiguration::the_input_targets()
2609+std::shared_ptr<mi::Scene> mir::DefaultServerConfiguration::the_input_scene()
2610 {
2611 return surface_stack([this]()
2612 { return std::make_shared<ms::SurfaceStack>(the_scene_report()); });
2613
2614=== modified file 'src/server/scene/legacy_scene_change_notification.cpp'
2615--- src/server/scene/legacy_scene_change_notification.cpp 2014-09-10 12:50:53 +0000
2616+++ src/server/scene/legacy_scene_change_notification.cpp 2014-09-18 16:04:44 +0000
2617@@ -82,6 +82,11 @@
2618 scene_notify_change();
2619 }
2620
2621+void ms::LegacySceneChangeNotification::scene_changed()
2622+{
2623+ scene_notify_change();
2624+}
2625+
2626 void ms::LegacySceneChangeNotification::end_observation()
2627 {
2628 std::unique_lock<decltype(surface_observers_guard)> lg(surface_observers_guard);
2629
2630=== modified file 'src/server/scene/surface_stack.cpp'
2631--- src/server/scene/surface_stack.cpp 2014-09-10 12:50:53 +0000
2632+++ src/server/scene/surface_stack.cpp 2014-09-18 16:04:44 +0000
2633@@ -68,11 +68,47 @@
2634 tracker->occluded_in(cid);
2635 }
2636
2637+ bool is_a_surface() const override
2638+ {
2639+ return true;
2640+ }
2641+
2642 private:
2643 std::shared_ptr<mg::Renderable> const renderable_;
2644 std::shared_ptr<ms::RenderingTracker> const tracker;
2645 };
2646
2647+class OverlaySceneElement : public mc::SceneElement
2648+{
2649+public:
2650+ OverlaySceneElement(
2651+ std::shared_ptr<mg::Renderable> renderable)
2652+ : renderable_{renderable}
2653+ {
2654+ }
2655+
2656+ std::shared_ptr<mg::Renderable> renderable() const override
2657+ {
2658+ return renderable_;
2659+ }
2660+
2661+ void rendered_in(mc::CompositorID /* cid */) override
2662+ {
2663+ }
2664+
2665+ void occluded_in(mc::CompositorID /* cid */) override
2666+ {
2667+ }
2668+
2669+ bool is_a_surface() const override
2670+ {
2671+ return false;
2672+ }
2673+
2674+private:
2675+ std::shared_ptr<mg::Renderable> const renderable_;
2676+};
2677+
2678 }
2679
2680 ms::SurfaceStack::SurfaceStack(
2681@@ -95,6 +131,10 @@
2682 elements.emplace_back(element);
2683 }
2684 }
2685+ for (auto const& renderable : overlays)
2686+ {
2687+ elements.emplace_back(std::make_shared<OverlaySceneElement>(renderable));
2688+ }
2689 return elements;
2690 }
2691
2692@@ -116,6 +156,38 @@
2693 update_rendering_tracker_compositors();
2694 }
2695
2696+void ms::SurfaceStack::add_input_visualization(
2697+ std::shared_ptr<mg::Renderable> const& overlay)
2698+{
2699+ {
2700+ std::lock_guard<decltype(guard)> lg(guard);
2701+ overlays.push_back(overlay);
2702+ }
2703+ observers.scene_changed();
2704+}
2705+
2706+void ms::SurfaceStack::remove_input_visualization(
2707+ std::weak_ptr<mg::Renderable> const& weak_overlay)
2708+{
2709+ auto overlay = weak_overlay.lock();
2710+ {
2711+ std::lock_guard<decltype(guard)> lg(guard);
2712+ auto const p = std::find(overlays.begin(), overlays.end(), overlay);
2713+ if (p == overlays.end())
2714+ {
2715+ BOOST_THROW_EXCEPTION(std::runtime_error("Attempt to remove an overlay which was never added or which has been previously removed"));
2716+ }
2717+ overlays.erase(p);
2718+ }
2719+
2720+ observers.scene_changed();
2721+}
2722+
2723+void ms::SurfaceStack::emit_scene_changed()
2724+{
2725+ observers.scene_changed();
2726+}
2727+
2728 void ms::SurfaceStack::add_surface(
2729 std::shared_ptr<Surface> const& surface,
2730 DepthId depth,
2731@@ -264,6 +336,12 @@
2732 { observer->surfaces_reordered(); });
2733 }
2734
2735+void ms::Observers::scene_changed()
2736+{
2737+ for_each([&](std::shared_ptr<Observer> const& observer)
2738+ { observer->scene_changed(); });
2739+}
2740+
2741 void ms::Observers::surface_exists(ms::Surface* surface)
2742 {
2743 for_each([&](std::shared_ptr<Observer> const& observer)
2744
2745=== modified file 'src/server/scene/surface_stack.h'
2746--- src/server/scene/surface_stack.h 2014-09-10 12:50:53 +0000
2747+++ src/server/scene/surface_stack.h 2014-09-18 16:04:44 +0000
2748@@ -24,7 +24,7 @@
2749 #include "mir/compositor/scene.h"
2750 #include "mir/scene/depth_id.h"
2751 #include "mir/scene/observer.h"
2752-#include "mir/input/input_targets.h"
2753+#include "mir/input/scene.h"
2754
2755 #include "mir/basic_observers.h"
2756
2757@@ -36,6 +36,10 @@
2758
2759 namespace mir
2760 {
2761+namespace graphics
2762+{
2763+class Renderable;
2764+}
2765 /// Management of Surface objects. Includes the model (SurfaceStack and Surface
2766 /// classes) and controller (SurfaceController) elements of an MVC design.
2767 namespace scene
2768@@ -52,6 +56,7 @@
2769 void surface_added(Surface* surface) override;
2770 void surface_removed(Surface* surface) override;
2771 void surfaces_reordered() override;
2772+ void scene_changed() override;
2773 void surface_exists(Surface* surface) override;
2774 void end_observation();
2775
2776@@ -59,7 +64,7 @@
2777 using BasicObservers<Observer>::remove;
2778 };
2779
2780-class SurfaceStack : public compositor::Scene, public input::InputTargets, public SurfaceStackModel
2781+class SurfaceStack : public compositor::Scene, public input::Scene, public SurfaceStackModel
2782 {
2783 public:
2784 explicit SurfaceStack(
2785@@ -71,7 +76,7 @@
2786 void register_compositor(compositor::CompositorID id) override;
2787 void unregister_compositor(compositor::CompositorID id) override;
2788
2789- // From InputTargets
2790+ // From Scene
2791 void for_each(std::function<void(std::shared_ptr<input::Surface> const&)> const& callback);
2792
2793 virtual void remove_surface(std::weak_ptr<Surface> const& surface) override;
2794@@ -85,6 +90,12 @@
2795
2796 void add_observer(std::shared_ptr<Observer> const& observer) override;
2797 void remove_observer(std::weak_ptr<Observer> const& observer) override;
2798+
2799+ // Intended for input overlays, as described in mir::input::Scene documentation.
2800+ void add_input_visualization(std::shared_ptr<graphics::Renderable> const& overlay);
2801+ void remove_input_visualization(std::weak_ptr<graphics::Renderable> const& overlay);
2802+
2803+ void emit_scene_changed() override;
2804
2805 private:
2806 SurfaceStack(const SurfaceStack&) = delete;
2807@@ -101,6 +112,8 @@
2808 std::map<DepthId, Layer> layers_by_depth;
2809 std::map<Surface*,std::shared_ptr<RenderingTracker>> rendering_trackers;
2810 std::set<compositor::CompositorID> registered_compositors;
2811+
2812+ std::vector<std::shared_ptr<graphics::Renderable>> overlays;
2813
2814 Observers observers;
2815 };
2816
2817=== modified file 'src/server/symbols.map'
2818--- src/server/symbols.map 2014-09-10 12:50:53 +0000
2819+++ src/server/symbols.map 2014-09-18 16:04:44 +0000
2820@@ -108,6 +108,7 @@
2821 mir::DefaultServerConfiguration::the_buffer_allocator*;
2822 mir::DefaultServerConfiguration::the_buffer_initializer*;
2823 mir::DefaultServerConfiguration::the_buffer_stream_factory*;
2824+ mir::DefaultServerConfiguration::the_buffer_writer*;
2825 mir::DefaultServerConfiguration::the_clock*;
2826 mir::DefaultServerConfiguration::the_composite_event_filter*;
2827 mir::DefaultServerConfiguration::the_compositor*;
2828@@ -149,7 +150,7 @@
2829 mir::DefaultServerConfiguration::the_input_sender*;
2830 mir::DefaultServerConfiguration::the_input_send_observer*;
2831 mir::DefaultServerConfiguration::the_input_targeter*;
2832- mir::DefaultServerConfiguration::the_input_targets*;
2833+ mir::DefaultServerConfiguration::the_input_scene*;
2834 mir::DefaultServerConfiguration::the_logger*;
2835 mir::DefaultServerConfiguration::the_main_loop*;
2836 mir::DefaultServerConfiguration::the_mediating_display_changer*;
2837@@ -407,6 +408,8 @@
2838 mir::input::TouchVisualizer::?TouchVisualizer*;
2839 mir::input::TouchVisualizer::TouchVisualizer*;
2840 mir::input::TouchVisualizer::visualize_touches*;
2841+ mir::input::TouchVisualizer::enable*;
2842+ mir::input::TouchVisualizer::disable*;
2843 mir::input::VTFilter::handle*;
2844 mir::logging::GlogLogger::GlogLogger*;
2845 mir::logging::GlogLogger::log*;
2846
2847=== modified file 'tests/acceptance-tests/test_nested_mir.cpp'
2848--- tests/acceptance-tests/test_nested_mir.cpp 2014-09-10 12:50:53 +0000
2849+++ tests/acceptance-tests/test_nested_mir.cpp 2014-09-18 16:04:44 +0000
2850@@ -132,6 +132,11 @@
2851 return adaptee->create_internal_client();
2852 }
2853
2854+ std::shared_ptr<mg::BufferWriter> make_buffer_writer() override
2855+ {
2856+ return adaptee->make_buffer_writer();
2857+ }
2858+
2859 void fill_buffer_package(
2860 mg::BufferIPCPacker* packer,
2861 mg::Buffer const* buffer,
2862@@ -139,7 +144,7 @@
2863 {
2864 return adaptee->fill_buffer_package(packer, buffer, msg_type);
2865 }
2866-
2867+
2868 std::shared_ptr<mg::Platform> const adaptee;
2869 };
2870
2871
2872=== modified file 'tests/acceptance-tests/test_touchspot_visualization.cpp'
2873--- tests/acceptance-tests/test_touchspot_visualization.cpp 2014-06-30 21:33:58 +0000
2874+++ tests/acceptance-tests/test_touchspot_visualization.cpp 2014-09-18 16:04:44 +0000
2875@@ -82,6 +82,8 @@
2876 struct MockTouchVisualizer : public mi::TouchVisualizer
2877 {
2878 MOCK_METHOD1(visualize_touches, void(std::vector<mi::TouchVisualizer::Spot> const&));
2879+ MOCK_METHOD0(enable, void());
2880+ MOCK_METHOD0(disable, void());
2881 };
2882
2883 struct ServerConfiguration : mtf::InputTestingServerConfiguration
2884
2885=== modified file 'tests/include/mir_test_doubles/null_platform.h'
2886--- tests/include/mir_test_doubles/null_platform.h 2014-09-10 12:50:53 +0000
2887+++ tests/include/mir_test_doubles/null_platform.h 2014-09-18 16:04:44 +0000
2888@@ -35,7 +35,7 @@
2889 std::shared_ptr<graphics::GraphicBufferAllocator> create_buffer_allocator(
2890 const std::shared_ptr<graphics::BufferInitializer>& /*buffer_initializer*/)
2891 {
2892- return std::shared_ptr<graphics::GraphicBufferAllocator>();
2893+ return nullptr;
2894 }
2895
2896 std::shared_ptr<graphics::Display> create_display(
2897@@ -53,7 +53,12 @@
2898
2899 std::shared_ptr<graphics::InternalClient> create_internal_client()
2900 {
2901- return std::shared_ptr<graphics::InternalClient>();
2902+ return nullptr;
2903+ }
2904+
2905+ std::shared_ptr<graphics::BufferWriter> make_buffer_writer()
2906+ {
2907+ return nullptr;
2908 }
2909
2910 void fill_buffer_package(
2911
2912=== renamed file 'tests/include/mir_test_doubles/stub_input_targets.h' => 'tests/include/mir_test_doubles/stub_input_scene.h'
2913--- tests/include/mir_test_doubles/stub_input_targets.h 2014-09-10 12:50:53 +0000
2914+++ tests/include/mir_test_doubles/stub_input_scene.h 2014-09-18 16:04:44 +0000
2915@@ -16,10 +16,10 @@
2916 * Authored by: Robert Carr <robert.carr@canonical.com>
2917 */
2918
2919-#ifndef MIR_TEST_DOUBLES_STUB_INPUT_TARGETS_H_
2920-#define MIR_TEST_DOUBLES_STUB_INPUT_TARGETS_H_
2921+#ifndef MIR_TEST_DOUBLES_STUB_INPUT_SCENE_H_
2922+#define MIR_TEST_DOUBLES_STUB_INPUT_SCENE_H_
2923
2924-#include "mir/input/input_targets.h"
2925+#include "mir/input/scene.h"
2926
2927 namespace mir
2928 {
2929@@ -28,7 +28,7 @@
2930 namespace doubles
2931 {
2932
2933-class StubInputTargets : public input::InputTargets
2934+class StubInputScene : public input::Scene
2935 {
2936 void for_each(std::function<void(std::shared_ptr<input::Surface> const&)> const& ) override
2937 {
2938@@ -39,10 +39,21 @@
2939 void remove_observer(std::weak_ptr<scene::Observer> const& /* observer */)
2940 {
2941 }
2942+
2943+ void add_input_visualization(std::shared_ptr<graphics::Renderable> const& /* overlay */)
2944+ {
2945+ }
2946+ void remove_input_visualization(std::weak_ptr<graphics::Renderable> const& /* overlay */)
2947+ {
2948+ }
2949+
2950+ void emit_scene_changed()
2951+ {
2952+ }
2953 };
2954
2955 }
2956 }
2957 } // namespace mir
2958
2959-#endif /* MIR_TEST_DOUBLES_STUB_INPUT_TARGETS_H_ */
2960+#endif /* MIR_TEST_DOUBLES_STUB_INPUT_SCENE_H_ */
2961
2962=== modified file 'tests/include/mir_test_doubles/stub_scene_element.h'
2963--- tests/include/mir_test_doubles/stub_scene_element.h 2014-06-20 17:57:16 +0000
2964+++ tests/include/mir_test_doubles/stub_scene_element.h 2014-09-18 16:04:44 +0000
2965@@ -48,6 +48,11 @@
2966 void occluded_in(compositor::CompositorID) override
2967 {
2968 }
2969+
2970+ bool is_a_surface() const override
2971+ {
2972+ return false;
2973+ }
2974
2975 private:
2976 std::shared_ptr<graphics::Renderable> const renderable_;
2977
2978=== modified file 'tests/include/mir_test_doubles/stub_touch_visualizer.h'
2979--- tests/include/mir_test_doubles/stub_touch_visualizer.h 2014-06-26 20:31:56 +0000
2980+++ tests/include/mir_test_doubles/stub_touch_visualizer.h 2014-09-18 16:04:44 +0000
2981@@ -33,6 +33,12 @@
2982 void visualize_touches(std::vector<Spot> const&) override
2983 {
2984 }
2985+ void enable() override
2986+ {
2987+ }
2988+ void disable() override
2989+ {
2990+ }
2991 };
2992
2993 }
2994
2995=== modified file 'tests/integration-tests/input/android/test_android_cursor_listener.cpp'
2996--- tests/integration-tests/input/android/test_android_cursor_listener.cpp 2014-09-10 12:50:53 +0000
2997+++ tests/integration-tests/input/android/test_android_cursor_listener.cpp 2014-09-18 16:04:44 +0000
2998@@ -26,7 +26,7 @@
2999 #include "mir/input/android/default_android_input_configuration.h"
3000 #include "mir/input/event_filter.h"
3001 #include "mir/input/cursor_listener.h"
3002-#include "mir/input/input_targets.h"
3003+#include "mir/input/scene.h"
3004 #include "mir/input/input_region.h"
3005 #include "mir/input/input_dispatcher.h"
3006 #include "mir/geometry/rectangle.h"
3007
3008=== modified file 'tests/integration-tests/input/android/test_android_input_manager.cpp'
3009--- tests/integration-tests/input/android/test_android_input_manager.cpp 2014-09-10 12:50:53 +0000
3010+++ tests/integration-tests/input/android/test_android_input_manager.cpp 2014-09-18 16:04:44 +0000
3011@@ -38,7 +38,7 @@
3012 #include "mir_test_doubles/mock_event_filter.h"
3013 #include "mir_test_doubles/stub_scene_surface.h"
3014 #include "mir_test_doubles/stub_input_channel.h"
3015-#include "mir_test_doubles/stub_input_targets.h"
3016+#include "mir_test_doubles/stub_scene.h"
3017 #include "mir_test_doubles/stub_scene.h"
3018 #include "mir_test_doubles/stub_input_enumerator.h"
3019 #include "mir_test_doubles/stub_touch_visualizer.h"
3020
3021=== modified file 'tests/integration-tests/input/test_nested_input.cpp'
3022--- tests/integration-tests/input/test_nested_input.cpp 2014-09-10 12:50:53 +0000
3023+++ tests/integration-tests/input/test_nested_input.cpp 2014-09-18 16:04:44 +0000
3024@@ -25,7 +25,7 @@
3025 #include "src/server/report/null_report_factory.h"
3026 #include "mir/raii.h"
3027
3028-#include "mir_test_doubles/stub_input_targets.h"
3029+#include "mir_test_doubles/stub_scene.h"
3030 #include "mir_test_doubles/mock_event_filter.h"
3031 #include "mir_test_doubles/stub_input_enumerator.h"
3032 #include "mir_test/fake_shared.h"
3033
3034=== modified file 'tests/mir_test_framework/stubbed_server_configuration.cpp'
3035--- tests/mir_test_framework/stubbed_server_configuration.cpp 2014-09-10 12:50:53 +0000
3036+++ tests/mir_test_framework/stubbed_server_configuration.cpp 2014-09-18 16:04:44 +0000
3037@@ -21,6 +21,7 @@
3038
3039 #include "mir/options/default_configuration.h"
3040 #include "mir/graphics/buffer_ipc_packer.h"
3041+#include "mir/graphics/buffer_writer.h"
3042 #include "mir/graphics/cursor.h"
3043 #include "mir/input/input_channel.h"
3044 #include "mir/input/input_manager.h"
3045@@ -181,6 +182,18 @@
3046 return std::make_shared<mtd::StubDisplay>(display_rects);
3047 }
3048
3049+ std::shared_ptr<mg::BufferWriter> make_buffer_writer() override
3050+ {
3051+ struct NullWriter : mg::BufferWriter
3052+ {
3053+ void write(mg::Buffer& /* buffer */,
3054+ unsigned char const* /* data */, size_t /* size */) override
3055+ {
3056+ }
3057+ };
3058+ return std::make_shared<NullWriter>();
3059+ }
3060+
3061 std::vector<geom::Rectangle> const display_rects;
3062 };
3063
3064
3065=== modified file 'tests/unit-tests/frontend/test_session_mediator.cpp'
3066--- tests/unit-tests/frontend/test_session_mediator.cpp 2014-09-12 13:26:47 +0000
3067+++ tests/unit-tests/frontend/test_session_mediator.cpp 2014-09-18 16:04:44 +0000
3068@@ -203,6 +203,7 @@
3069 MOCK_CONST_METHOD3(fill_buffer_package,
3070 void(mg::BufferIPCPacker*, mg::Buffer const*, mg::BufferIpcMsgType));
3071 MOCK_CONST_METHOD0(egl_native_display, EGLNativeDisplayType());
3072+ MOCK_METHOD0(make_buffer_writer, std::shared_ptr<mg::BufferWriter>());
3073 };
3074
3075 struct StubScreencast : mtd::NullScreencast
3076
3077=== modified file 'tests/unit-tests/graphics/mesa/test_shm_buffer.cpp'
3078--- tests/unit-tests/graphics/mesa/test_shm_buffer.cpp 2014-09-10 12:50:53 +0000
3079+++ tests/unit-tests/graphics/mesa/test_shm_buffer.cpp 2014-09-18 16:04:44 +0000
3080@@ -1,5 +1,5 @@
3081 /*
3082- * Copyright © 2013 Canonical Ltd.
3083+ * Copyright © 2014 Canonical Ltd.
3084 *
3085 * This program is free software: you can redistribute it and/or modify
3086 * it under the terms of the GNU General Public License version 3 as
3087
3088=== modified file 'tests/unit-tests/graphics/nested/test_nested_platform.cpp'
3089--- tests/unit-tests/graphics/nested/test_nested_platform.cpp 2014-09-10 12:50:53 +0000
3090+++ tests/unit-tests/graphics/nested/test_nested_platform.cpp 2014-09-18 16:04:44 +0000
3091@@ -64,6 +64,11 @@
3092 {
3093 return {};
3094 }
3095+
3096+ std::shared_ptr<mg::BufferWriter> make_buffer_writer() override
3097+ {
3098+ return {};
3099+ }
3100
3101 void fill_buffer_package(
3102 mg::BufferIPCPacker*, mg::Buffer const*, mg::BufferIpcMsgType) const override {}
3103
3104=== modified file 'tests/unit-tests/input/CMakeLists.txt'
3105--- tests/unit-tests/input/CMakeLists.txt 2014-09-10 12:50:53 +0000
3106+++ tests/unit-tests/input/CMakeLists.txt 2014-09-18 16:04:44 +0000
3107@@ -5,6 +5,7 @@
3108 ${CMAKE_CURRENT_SOURCE_DIR}/test_display_input_region.cpp
3109 ${CMAKE_CURRENT_SOURCE_DIR}/test_cursor_controller.cpp
3110 ${CMAKE_CURRENT_SOURCE_DIR}/test_xcursor_loader.cpp
3111+ ${CMAKE_CURRENT_SOURCE_DIR}/test_touchspot_controller.cpp
3112 )
3113
3114 set(
3115
3116=== modified file 'tests/unit-tests/input/android/test_android_input_target_enumerator.cpp'
3117--- tests/unit-tests/input/android/test_android_input_target_enumerator.cpp 2014-09-10 12:50:53 +0000
3118+++ tests/unit-tests/input/android/test_android_input_target_enumerator.cpp 2014-09-18 16:04:44 +0000
3119@@ -19,13 +19,14 @@
3120 #include "src/server/input/android/android_input_target_enumerator.h"
3121
3122 #include "mir/input/input_channel.h"
3123-#include "mir/input/input_targets.h"
3124+#include "mir/input/scene.h"
3125 #include "mir/input/surface.h"
3126
3127 #include "mir_test/fake_shared.h"
3128 #include "mir_test_doubles/stub_input_channel.h"
3129 #include "mir_test_doubles/stub_input_handles.h"
3130 #include "mir_test_doubles/stub_input_surface.h"
3131+#include "mir_test_doubles/stub_input_scene.h"
3132 #include "mir_test_doubles/mock_window_handle_repository.h"
3133
3134 #include <InputDispatcher.h>
3135@@ -48,9 +49,9 @@
3136 namespace
3137 {
3138
3139-struct StubInputTargets : public mi::InputTargets
3140+struct StubScene : public mtd::StubInputScene
3141 {
3142- StubInputTargets(std::initializer_list<std::shared_ptr<mi::Surface>> const& target_list)
3143+ StubScene(std::initializer_list<std::shared_ptr<mi::Surface>> const& target_list)
3144 : targets(target_list.begin(), target_list.end())
3145 {
3146 }
3147@@ -85,7 +86,7 @@
3148 mtd::MockWindowHandleRepository repository;
3149 droidinput::sp<droidinput::InputWindowHandle> stub_window_handle1 = new mtd::StubWindowHandle;
3150 droidinput::sp<droidinput::InputWindowHandle> stub_window_handle2 = new mtd::StubWindowHandle;
3151- StubInputTargets targets({target1, target2});
3152+ StubScene targets({target1, target2});
3153
3154 Sequence seq2;
3155 EXPECT_CALL(repository, handle_for_channel(
3156
3157=== modified file 'tests/unit-tests/input/test_cursor_controller.cpp'
3158--- tests/unit-tests/input/test_cursor_controller.cpp 2014-09-10 12:50:53 +0000
3159+++ tests/unit-tests/input/test_cursor_controller.cpp 2014-09-18 16:04:44 +0000
3160@@ -19,7 +19,7 @@
3161 #include "src/server/input/cursor_controller.h"
3162
3163 #include "mir/input/surface.h"
3164-#include "mir/input/input_targets.h"
3165+#include "mir/input/scene.h"
3166 #include "mir/scene/observer.h"
3167 #include "mir/scene/surface_observer.h"
3168 #include "mir/graphics/cursor_image.h"
3169@@ -29,6 +29,7 @@
3170
3171 #include "mir_test/fake_shared.h"
3172 #include "mir_test_doubles/stub_scene_surface.h"
3173+#include "mir_test_doubles/stub_input_scene.h"
3174
3175 #include <gtest/gtest.h>
3176 #include <gmock/gmock.h>
3177@@ -166,9 +167,9 @@
3178 std::vector<std::shared_ptr<ms::SurfaceObserver>> observers;
3179 };
3180
3181-struct StubInputTargets : public mi::InputTargets
3182+struct StubScene : public mtd::StubInputScene
3183 {
3184- StubInputTargets(std::initializer_list<std::shared_ptr<ms::Surface>> const& targets)
3185+ StubScene(std::initializer_list<std::shared_ptr<ms::Surface>> const& targets)
3186 : targets(targets.begin(), targets.end())
3187 {
3188 }
3189@@ -243,7 +244,7 @@
3190 {
3191 using namespace ::testing;
3192
3193- StubInputTargets targets({});
3194+ StubScene targets({});
3195
3196 mi::CursorController controller(mt::fake_shared(targets),
3197 mt::fake_shared(cursor), default_cursor_image);
3198@@ -262,7 +263,7 @@
3199
3200 StubInputSurface surface{rect_1_1_1_1,
3201 std::make_shared<NamedCursorImage>(cursor_name_1)};
3202- StubInputTargets targets({mt::fake_shared(surface)});
3203+ StubScene targets({mt::fake_shared(surface)});
3204
3205 mi::CursorController controller(mt::fake_shared(targets),
3206 mt::fake_shared(cursor), default_cursor_image);
3207@@ -279,7 +280,7 @@
3208
3209 StubInputSurface surface{rect_1_1_1_1,
3210 nullptr};
3211- StubInputTargets targets({mt::fake_shared(surface)});
3212+ StubScene targets({mt::fake_shared(surface)});
3213
3214 mi::CursorController controller(mt::fake_shared(targets),
3215 mt::fake_shared(cursor), default_cursor_image);
3216@@ -296,7 +297,7 @@
3217
3218 StubInputSurface surface_1{rect_1_1_1_1, std::make_shared<NamedCursorImage>(cursor_name_1)};
3219 StubInputSurface surface_2{rect_1_1_1_1, std::make_shared<NamedCursorImage>(cursor_name_2)};
3220- StubInputTargets targets({mt::fake_shared(surface_1), mt::fake_shared(surface_2)});
3221+ StubScene targets({mt::fake_shared(surface_1), mt::fake_shared(surface_2)});
3222
3223 mi::CursorController controller(mt::fake_shared(targets),
3224 mt::fake_shared(cursor), default_cursor_image);
3225@@ -313,7 +314,7 @@
3226
3227 StubInputSurface surface{rect_1_1_1_1,
3228 std::make_shared<NamedCursorImage>(cursor_name_1)};
3229- StubInputTargets targets({mt::fake_shared(surface)});
3230+ StubScene targets({mt::fake_shared(surface)});
3231
3232 mi::CursorController controller(mt::fake_shared(targets),
3233 mt::fake_shared(cursor), default_cursor_image);
3234@@ -336,7 +337,7 @@
3235
3236 StubInputSurface surface{rect_1_1_1_1,
3237 std::make_shared<NamedCursorImage>(cursor_name_1)};
3238- StubInputTargets targets({mt::fake_shared(surface)});
3239+ StubScene targets({mt::fake_shared(surface)});
3240
3241 mi::CursorController controller(mt::fake_shared(targets),
3242 mt::fake_shared(cursor), default_cursor_image);
3243@@ -359,7 +360,7 @@
3244 // Here we also demonstrate that the cursor begins at 0,0.
3245 StubInputSurface surface{rect_0_0_1_1,
3246 std::make_shared<NamedCursorImage>(cursor_name_1)};
3247- StubInputTargets targets({});
3248+ StubScene targets({});
3249
3250 mi::CursorController controller(mt::fake_shared(targets),
3251 mt::fake_shared(cursor), default_cursor_image);
3252@@ -379,7 +380,7 @@
3253 // Here we also demonstrate that the cursor begins at 0,0.
3254 StubInputSurface surface1{rect_0_0_1_1, image};
3255 StubInputSurface surface2{rect_0_0_1_1, image};
3256- StubInputTargets targets({});
3257+ StubScene targets({});
3258
3259 mi::CursorController controller(mt::fake_shared(targets),
3260 mt::fake_shared(cursor), default_cursor_image);
3261
3262=== added file 'tests/unit-tests/input/test_touchspot_controller.cpp'
3263--- tests/unit-tests/input/test_touchspot_controller.cpp 1970-01-01 00:00:00 +0000
3264+++ tests/unit-tests/input/test_touchspot_controller.cpp 2014-09-18 16:04:44 +0000
3265@@ -0,0 +1,199 @@
3266+/*
3267+ * Copyright © 2014 Canonical Ltd.
3268+ *
3269+ * This program is free software: you can redistribute it and/or modify
3270+ * it under the terms of the GNU General Public License version 3 as
3271+ * published by the Free Software Foundation.
3272+ *
3273+ * This program is distributed in the hope that it will be useful,
3274+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3275+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3276+ * GNU General Public License for more details.
3277+ *
3278+ * You should have received a copy of the GNU General Public License
3279+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3280+ *
3281+ * Authored by: Robert Carr <robert.carr@canonical.com>
3282+ */
3283+
3284+#include "src/server/input/touchspot_controller.h"
3285+
3286+#include "mir/graphics/graphic_buffer_allocator.h"
3287+#include "mir/graphics/renderable.h"
3288+#include "mir/graphics/buffer_writer.h"
3289+#include "mir_test/fake_shared.h"
3290+#include "mir_test_doubles/stub_buffer.h"
3291+#include "mir_test_doubles/stub_scene.h"
3292+#include "mir_test_doubles/mock_buffer.h"
3293+#include "mir_test_doubles/stub_input_scene.h"
3294+
3295+#include <gmock/gmock.h>
3296+#include <gtest/gtest.h>
3297+
3298+#include <algorithm>
3299+#include <vector>
3300+
3301+#include <assert.h>
3302+
3303+namespace mi = mir::input;
3304+namespace mg = mir::graphics;
3305+namespace mt = mir::test;
3306+namespace mtd = mt::doubles;
3307+namespace geom = mir::geometry;
3308+
3309+namespace
3310+{
3311+
3312+struct MockBufferAllocator : public mg::GraphicBufferAllocator
3313+{
3314+ MOCK_METHOD1(alloc_buffer, std::shared_ptr<mg::Buffer>(mg::BufferProperties const&));
3315+ MOCK_METHOD0(supported_pixel_formats, std::vector<MirPixelFormat>(void));
3316+};
3317+
3318+struct StubBufferWriter : public mg::BufferWriter
3319+{
3320+ void write(mg::Buffer& /* buffer */,
3321+ unsigned char const* /* data */, size_t /* size */) override
3322+ {
3323+ }
3324+};
3325+
3326+struct StubScene : public mtd::StubInputScene
3327+{
3328+ void add_input_visualization(std::shared_ptr<mg::Renderable> const& overlay) override
3329+ {
3330+ overlays.push_back(overlay);
3331+ }
3332+
3333+ void remove_input_visualization(std::weak_ptr<mg::Renderable> const& overlay) override
3334+ {
3335+ auto l = overlay.lock();
3336+ assert(l);
3337+
3338+ auto it = std::find(overlays.begin(), overlays.end(), l);
3339+ assert(it != overlays.end());
3340+
3341+ overlays.erase(it);
3342+ }
3343+
3344+ void expect_spots_centered_at(std::vector<geom::Point> spots)
3345+ {
3346+ int const touchspot_side_in_pixels = 64;
3347+ for (auto overlay : overlays)
3348+ {
3349+ auto top_left_pos = overlay->screen_position().top_left;
3350+ auto center_pos = geom::Point{top_left_pos.x.as_int() + touchspot_side_in_pixels/2,
3351+ top_left_pos.y.as_int() + touchspot_side_in_pixels/2};
3352+ auto it = std::find(spots.begin(), spots.end(), center_pos);
3353+ EXPECT_FALSE(it == spots.end());
3354+ spots.erase(it);
3355+ }
3356+ // If there are left over spots then we didn't have an overlay corresponding to one
3357+ EXPECT_EQ(0, spots.size());
3358+ }
3359+
3360+ std::vector<std::shared_ptr<mg::Renderable>> overlays;
3361+};
3362+
3363+struct TestTouchspotController : public ::testing::Test
3364+{
3365+ TestTouchspotController()
3366+ : allocator(std::make_shared<MockBufferAllocator>()),
3367+ writer(std::make_shared<StubBufferWriter>()),
3368+ scene(std::make_shared<StubScene>())
3369+ {
3370+ }
3371+ std::shared_ptr<MockBufferAllocator> const allocator;
3372+ std::shared_ptr<mg::BufferWriter> const writer;
3373+ std::shared_ptr<StubScene> const scene;
3374+};
3375+
3376+MATCHER(SoftwareBuffer, "")
3377+{
3378+ auto properties = static_cast<mg::BufferProperties const&>(arg);
3379+ if (properties.usage != mg::BufferUsage::software)
3380+ return false;
3381+ return true;
3382+}
3383+
3384+}
3385+
3386+TEST_F(TestTouchspotController, allocates_software_buffer_for_touchspots)
3387+{
3388+ using namespace ::testing;
3389+
3390+ EXPECT_CALL(*allocator, alloc_buffer(SoftwareBuffer())).Times(1)
3391+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3392+ mi::TouchspotController controller(allocator, writer, scene);
3393+}
3394+
3395+TEST_F(TestTouchspotController, touches_result_in_renderables_in_stack)
3396+{
3397+ using namespace ::testing;
3398+
3399+ EXPECT_CALL(*allocator, alloc_buffer(SoftwareBuffer())).Times(1)
3400+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3401+ mi::TouchspotController controller(allocator, writer, scene);
3402+ controller.enable();
3403+
3404+ controller.visualize_touches({ {{0,0}, 1} });
3405+
3406+ scene->expect_spots_centered_at({{0, 0}});
3407+}
3408+
3409+TEST_F(TestTouchspotController, spots_move)
3410+{
3411+ using namespace ::testing;
3412+
3413+ EXPECT_CALL(*allocator, alloc_buffer(SoftwareBuffer())).Times(1)
3414+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3415+ mi::TouchspotController controller(allocator, writer, scene);
3416+ controller.enable();
3417+
3418+ controller.visualize_touches({ {{0,0}, 1} });
3419+ scene->expect_spots_centered_at({{0, 0}});
3420+ controller.visualize_touches({ {{1,1}, 1} });
3421+ scene->expect_spots_centered_at({{1, 1}});
3422+}
3423+
3424+TEST_F(TestTouchspotController, multiple_spots)
3425+{
3426+ using namespace ::testing;
3427+
3428+ EXPECT_CALL(*allocator, alloc_buffer(SoftwareBuffer())).Times(1)
3429+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3430+ mi::TouchspotController controller(allocator, writer, scene);
3431+ controller.enable();
3432+
3433+ controller.visualize_touches({ {{0,0}, 1}, {{1, 1}, 1}, {{3, 3}, 1} });
3434+ scene->expect_spots_centered_at({{0, 0}, {1, 1}, {3, 3}});
3435+ controller.visualize_touches({ {{0,0}, 1}, {{1, 1}, 1}, {{3, 3}, 1}, {{5, 5}, 1} });
3436+ scene->expect_spots_centered_at({{0, 0}, {1, 1}, {3, 3}, {5, 5}});
3437+ controller.visualize_touches({ {{1,1}, 1} });
3438+ scene->expect_spots_centered_at({{1, 1}});
3439+ controller.visualize_touches({});
3440+ scene->expect_spots_centered_at({});
3441+}
3442+
3443+// This leaves some semantics undefined, i,e. if the touchspot controller is enabled/disabled
3444+// during a gesture do the spots appear/dissapear? I've been unable to develop a strong opinion
3445+// on this semantic, so I am leaving it unspecified ~racarr
3446+TEST_F(TestTouchspotController, touches_do_not_result_in_renderables_in_stack_when_disabled)
3447+{
3448+ using namespace ::testing;
3449+
3450+ EXPECT_CALL(*allocator, alloc_buffer(SoftwareBuffer())).Times(1)
3451+ .WillOnce(Return(std::make_shared<mtd::StubBuffer>()));
3452+ mi::TouchspotController controller(allocator, writer, scene);
3453+ controller.enable();
3454+
3455+ controller.disable();
3456+ controller.visualize_touches({ {{0,0}, 1} });
3457+
3458+ scene->expect_spots_centered_at({});
3459+
3460+ controller.enable();
3461+ controller.visualize_touches({ {{0,0}, 1} });
3462+
3463+ scene->expect_spots_centered_at({{0, 0}});
3464+}
3465
3466=== modified file 'tests/unit-tests/scene/test_surface_stack.cpp'
3467--- tests/unit-tests/scene/test_surface_stack.cpp 2014-09-10 12:50:53 +0000
3468+++ tests/unit-tests/scene/test_surface_stack.cpp 2014-09-18 16:04:44 +0000
3469@@ -28,6 +28,7 @@
3470 #include "mir_test_doubles/stub_input_channel.h"
3471 #include "mir_test/fake_shared.h"
3472 #include "mir_test_doubles/stub_buffer_stream.h"
3473+#include "mir_test_doubles/stub_renderable.h"
3474 #include "mir_test_doubles/mock_buffer_stream.h"
3475 #include "mir_test_doubles/null_surface_configurator.h"
3476
3477@@ -103,6 +104,7 @@
3478 MOCK_METHOD1(surface_added, void(ms::Surface*));
3479 MOCK_METHOD1(surface_removed, void(ms::Surface*));
3480 MOCK_METHOD0(surfaces_reordered, void());
3481+ MOCK_METHOD0(scene_changed, void());
3482
3483 MOCK_METHOD1(surface_exists, void(ms::Surface*));
3484 MOCK_METHOD0(end_observation, void());
3485@@ -673,6 +675,100 @@
3486 stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
3487 }
3488
3489+TEST_F(SurfaceStack, scene_observer_notified_of_add_and_remove_input_visualization)
3490+{
3491+ using namespace ::testing;
3492+
3493+ MockSceneObserver observer;
3494+ mtd::StubRenderable r;
3495+
3496+ InSequence seq;
3497+ EXPECT_CALL(observer, scene_changed()).Times(2);
3498+
3499+ stack.add_observer(mt::fake_shared(observer));
3500+
3501+ stack.add_input_visualization(mt::fake_shared(r));
3502+ stack.remove_input_visualization(mt::fake_shared(r));
3503+}
3504+
3505+TEST_F(SurfaceStack, overlays_do_not_appear_in_input_enumeration)
3506+{
3507+ mtd::StubRenderable r;
3508+
3509+ stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
3510+ stack.add_surface(stub_surface2, default_params.depth, default_params.input_mode);
3511+
3512+ // Configure surface1 and surface2 to appear in input enumeration.
3513+ stub_surface1->configure(mir_surface_attrib_visibility, MirSurfaceVisibility::mir_surface_visibility_exposed);
3514+ stub_surface2->configure(mir_surface_attrib_visibility, MirSurfaceVisibility::mir_surface_visibility_exposed);
3515+
3516+ stack.add_input_visualization(mt::fake_shared(r));
3517+
3518+ unsigned int observed_input_targets = 0;
3519+ stack.for_each([&observed_input_targets](std::shared_ptr<mi::Surface> const&)
3520+ {
3521+ observed_input_targets++;
3522+ });
3523+ EXPECT_EQ(2, observed_input_targets);
3524+}
3525+
3526+TEST_F(SurfaceStack, overlays_appear_at_top_of_renderlist)
3527+{
3528+ using namespace ::testing;
3529+
3530+ mtd::StubRenderable r;
3531+
3532+ stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
3533+ stack.add_input_visualization(mt::fake_shared(r));
3534+ stack.add_surface(stub_surface2, default_params.depth, default_params.input_mode);
3535+
3536+ EXPECT_THAT(
3537+ stack.scene_elements_for(compositor_id),
3538+ ElementsAre(
3539+ SceneElementFor(stub_surface1),
3540+ SceneElementFor(stub_surface2),
3541+ SceneElementFor(mt::fake_shared(r))));
3542+}
3543+
3544+TEST_F(SurfaceStack, removed_overlays_are_removed)
3545+{
3546+ using namespace ::testing;
3547+
3548+ mtd::StubRenderable r;
3549+
3550+ stack.add_surface(stub_surface1, default_params.depth, default_params.input_mode);
3551+ stack.add_input_visualization(mt::fake_shared(r));
3552+ stack.add_surface(stub_surface2, default_params.depth, default_params.input_mode);
3553+
3554+ EXPECT_THAT(
3555+ stack.scene_elements_for(compositor_id),
3556+ ElementsAre(
3557+ SceneElementFor(stub_surface1),
3558+ SceneElementFor(stub_surface2),
3559+ SceneElementFor(mt::fake_shared(r))));
3560+
3561+ stack.remove_input_visualization(mt::fake_shared(r));
3562+
3563+ EXPECT_THAT(
3564+ stack.scene_elements_for(compositor_id),
3565+ ElementsAre(
3566+ SceneElementFor(stub_surface1),
3567+ SceneElementFor(stub_surface2)));
3568+}
3569+
3570+TEST_F(SurfaceStack, scene_observers_notified_of_generic_scene_change)
3571+{
3572+ MockSceneObserver o1, o2;
3573+
3574+ EXPECT_CALL(o1, scene_changed()).Times(1);
3575+ EXPECT_CALL(o2, scene_changed()).Times(1);
3576+
3577+ stack.add_observer(mt::fake_shared(o1));
3578+ stack.add_observer(mt::fake_shared(o2));
3579+
3580+ stack.emit_scene_changed();
3581+}
3582+
3583 TEST_F(SurfaceStack, only_enumerates_exposed_input_surfaces)
3584 {
3585 using namespace ::testing;

Subscribers

People subscribed via source and target branches