summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarius Vlad <marius.vlad@collabora.com>2020-09-15 18:12:24 +0300
committerJan-Simon Moeller <jsmoeller@linuxfoundation.org>2020-09-30 13:43:12 +0000
commit991714fc7f92aea3d07c7225247a821e3461027e (patch)
tree9054e78451203614aaf190c1a9a30e3d2bc49be1
parent1f888f2050ac50ec8c1750ff4f0e2c485936d7ed (diff)
screenshooter: Add agl-screenshooter protocol
Just like weston, we add a private protocol. Underneath we make use of the weston renderer to get a hold of the pixels and transfer them to a user-supplied buffer. This only brings up the server side implementation of the protocol. Bug-AGL: SPEC-3580 Signed-off-by: Marius Vlad <marius.vlad@collabora.com> Change-Id: I02a07ad5eb492ef2ecad74efb34d1453ebcbedc0
-rw-r--r--meson.build5
-rw-r--r--protocol/agl-screenshooter.xml84
-rw-r--r--src/ivi-compositor.h2
-rw-r--r--src/main.c1
-rw-r--r--src/screenshooter.c137
5 files changed, 229 insertions, 0 deletions
diff --git a/meson.build b/meson.build
index 9dd9673..4299d58 100644
--- a/meson.build
+++ b/meson.build
@@ -65,11 +65,13 @@ endforeach
agl_shell_xml = files('protocol/agl-shell.xml')
agl_shell_desktop_xml = files('protocol/agl-shell-desktop.xml')
+agl_screenshooter = files('protocol/agl-screenshooter.xml')
xdg_shell_xml = join_paths(dir_wp_base, 'stable', 'xdg-shell', 'xdg-shell.xml')
protocols = [
{ 'name': 'agl-shell', 'source': 'internal' },
{ 'name': 'agl-shell-desktop', 'source': 'internal' },
+ { 'name': 'agl-screenshooter', 'source': 'internal' },
{ 'name': 'xdg-shell', 'source': 'wp-stable' },
]
@@ -140,12 +142,15 @@ srcs_agl_compositor = [
'src/layout.c',
'src/policy.c',
'src/shell.c',
+ 'src/screenshooter.c',
'shared/option-parser.c',
'shared/os-compatibility.c',
agl_shell_server_protocol_h,
agl_shell_desktop_server_protocol_h,
+ agl_screenshooter_server_protocol_h,
agl_shell_protocol_c,
agl_shell_desktop_protocol_c,
+ agl_screenshooter_protocol_c,
xdg_shell_protocol_c,
]
diff --git a/protocol/agl-screenshooter.xml b/protocol/agl-screenshooter.xml
new file mode 100644
index 0000000..6ed1457
--- /dev/null
+++ b/protocol/agl-screenshooter.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="agl_screenshooter">
+
+ <copyright>
+ Copyright © 2020 Collabora. Ltd,
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice (including the next
+ paragraph) shall be included in all copies or substantial portions of the
+ Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+ </copyright>
+
+ <interface name="agl_screenshooter" version="1">
+ <description summary="agl screenshooter">
+ agl compositor extension that performs a screenshot of the output, which
+ is represented by a 'wl_output' object.
+
+ A client would call 'take_shot' request and wait until the compositor
+ finishes to write the data to a wayland buffer, moment in which signals
+ back the client with the help of the 'done' event. Clients should wait
+ until the 'done' event is received, if they want to take another
+ screenshot, or take another screnshot of a different output.
+
+ The client must provide a wl_shm-based wl_buffer of the correct size when
+ taking a shot. The compositor will write the shot into the wl_buffer and then
+ send the 'done' event that signals completion of writing the data.
+
+ Once the compositor has finished to transfer the data back into the supplied
+ wayland buffer, the client should be able to transfer it to a popular
+ file format on the disk.
+ </description>
+
+ <enum name="done_status">
+ <entry name="success" value="0"/>
+ <entry name="no_memory" value="1"/>
+ <entry name="bad_buffer" value="2"/>
+ </enum>
+
+ <request name="take_shot">
+ <description summary="performs a screenshot">
+ Takes a screenshot of the wayland output represented by a 'wl_output'
+ object. Clients should first retrieve it using global registry, as well
+ as the 'wl_shm' object in order to create a wayland buffer type of
+ object ('wl_buffer').
+
+ Clients can derive the stride and size from the 'wl_output' object, and
+ later on use those when creating shm-based 'wl_buffer', as well as supplying
+ the pixel format.
+ </description>
+
+ <arg name="output" type="object" interface="wl_output"/>
+ <arg name="buffer" type="object" interface="wl_buffer"/>
+ </request>
+
+ <event name="done">
+ <description summary="sent when 'take_shot' finished">
+ Even sent back to nofify client 'take_shot' request has completed.
+ </description>
+ <arg name="status" type="uint" enum="done_status" />
+ </event>
+
+ <request name="destroy" type="destructor">
+ <description summary="destroy main object">
+ Destroys the 'weston_screenshooter' interface.
+ </description>
+ </request>
+
+ </interface>
+
+</protocol>
diff --git a/src/ivi-compositor.h b/src/ivi-compositor.h
index 6969a7d..4506a5a 100644
--- a/src/ivi-compositor.h
+++ b/src/ivi-compositor.h
@@ -377,5 +377,7 @@ ivi_layout_find_with_app_id(const char *app_id, struct ivi_compositor *ivi);
void
shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
const char *data, uint32_t app_state);
+void
+ivi_screenshooter_create(struct ivi_compositor *ivi);
#endif
diff --git a/src/main.c b/src/main.c
index 99512d5..164b45b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1493,6 +1493,7 @@ int main(int argc, char *argv[])
ivi_shell_create_global(&ivi);
ivi_launch_shell_client(&ivi);
+ ivi_screenshooter_create(&ivi);
ivi_agl_systemd_notify(&ivi);
wl_display_run(display);
diff --git a/src/screenshooter.c b/src/screenshooter.c
new file mode 100644
index 0000000..ef3d32e
--- /dev/null
+++ b/src/screenshooter.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright © 2020 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "ivi-compositor.h"
+#include "shared/helpers.h"
+
+#include <libweston/libweston.h>
+#include "agl-screenshooter-server-protocol.h"
+#include <libweston/weston-log.h>
+
+struct screenshooter {
+ struct ivi_compositor *ivi;
+ struct wl_global *global;
+ struct wl_client *client;
+ struct wl_listener destroy_listener;
+};
+
+static void
+screenshooter_done(void *data, enum weston_screenshooter_outcome outcome)
+{
+ struct wl_resource *resource = data;
+
+ if (outcome == WESTON_SCREENSHOOTER_NO_MEMORY) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ agl_screenshooter_send_done(resource, outcome);
+}
+
+static void
+screenshooter_shoot(struct wl_client *client,
+ struct wl_resource *resource,
+ struct wl_resource *output_resource,
+ struct wl_resource *buffer_resource)
+{
+ struct weston_output *output =
+ weston_head_from_resource(output_resource)->output;
+ struct weston_buffer *buffer =
+ weston_buffer_from_resource(buffer_resource);
+
+ if (buffer == NULL) {
+ wl_resource_post_no_memory(resource);
+ return;
+ }
+
+ weston_screenshooter_shoot(output, buffer, screenshooter_done, resource);
+}
+
+static void
+screenshooter_destructor_destroy(struct wl_client *client,
+ struct wl_resource *global_resource)
+{
+ wl_resource_destroy(global_resource);
+}
+
+struct agl_screenshooter_interface screenshooter_implementation = {
+ screenshooter_shoot,
+ screenshooter_destructor_destroy
+};
+
+static void
+bind_shooter(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id)
+{
+ struct screenshooter *shooter = data;
+ struct wl_resource *resource;
+ bool debug_enabled = true;
+
+ resource = wl_resource_create(client,
+ &agl_screenshooter_interface, 1, id);
+
+ if (!debug_enabled && !shooter->client) {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "screenshooter failed: permission denied. "\
+ "Debug must be enabled");
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &screenshooter_implementation,
+ data, NULL);
+}
+
+static void
+screenshooter_destroy(struct wl_listener *listener, void *data)
+{
+ struct screenshooter *shooter =
+ container_of(listener, struct screenshooter, destroy_listener);
+
+ wl_list_remove(&shooter->destroy_listener.link);
+
+ wl_global_destroy(shooter->global);
+ free(shooter);
+}
+
+void
+ivi_screenshooter_create(struct ivi_compositor *ivi)
+{
+ struct weston_compositor *ec = ivi->compositor;
+ struct screenshooter *shooter;
+
+ shooter = zalloc(sizeof(*shooter));
+ if (shooter == NULL)
+ return;
+
+ shooter->ivi = ivi;
+ shooter->global = wl_global_create(ec->wl_display,
+ &agl_screenshooter_interface, 1,
+ shooter, bind_shooter);
+
+ shooter->destroy_listener.notify = screenshooter_destroy;
+ wl_signal_add(&ec->destroy_signal, &shooter->destroy_listener);
+
+ weston_log("Screenshooter interface created\n");
+}