diff options
author | ToshikazuOhiwa <toshikazu_ohiwa@mail.toyota.co.jp> | 2020-03-30 09:24:26 +0900 |
---|---|---|
committer | ToshikazuOhiwa <toshikazu_ohiwa@mail.toyota.co.jp> | 2020-03-30 09:24:26 +0900 |
commit | 5b80bfd7bffd4c20d80b7c70a7130529e9a755dd (patch) | |
tree | b4bb18dcd1487dbf1ea8127e5671b7bb2eded033 /bsp/meta-synopsys/recipes-graphics/wayland | |
parent | 706ad73eb02caf8532deaf5d38995bd258725cb8 (diff) |
agl-basesystem
Diffstat (limited to 'bsp/meta-synopsys/recipes-graphics/wayland')
15 files changed, 3294 insertions, 0 deletions
diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/files/dvi-i-1-270.cfg b/bsp/meta-synopsys/recipes-graphics/wayland/files/dvi-i-1-270.cfg new file mode 100644 index 00000000..fafa41a4 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/files/dvi-i-1-270.cfg @@ -0,0 +1,7 @@ +# A display is connected to DVI-I-1 and needs to be rotated 270 degrees +# to have a proper orientation of the homescreen. For example the various sizes +# of the GeChic display or the Dell display. +[output] +name=DVI-I-1 +transform=270 +mode=preferred diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston-ini-conf.bbappend b/bsp/meta-synopsys/recipes-graphics/wayland/weston-ini-conf.bbappend new file mode 100644 index 00000000..b44b6095 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston-ini-conf.bbappend @@ -0,0 +1,5 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" +SRC_URI_append += "\ + file://dvi-i-1-270.cfg \ +" + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1001-os-compatibility-define-CLOCK_BOOTTIME-when-not-avai.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1001-os-compatibility-define-CLOCK_BOOTTIME-when-not-avai.patch new file mode 100644 index 00000000..a7f2a34a --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1001-os-compatibility-define-CLOCK_BOOTTIME-when-not-avai.patch @@ -0,0 +1,41 @@ +From 66b71951f8ce66f02040f8814e1d89db34c34a87 Mon Sep 17 00:00:00 2001 +From: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +Date: Sun, 22 Feb 2015 12:36:00 +0100 +Subject: [PATCH] os-compatibility: define CLOCK_BOOTTIME when not available + +CLOCK_BOOTTIME is supposed to be provided by the C library headers, +but uClibc 0.9.33.2 does not provide it. Instead of depending on an +uClibc patch, let's make Weston define it to the right value when not +already defined by the C library. + +Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com> +--- + shared/os-compatibility.h | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/shared/os-compatibility.h b/shared/os-compatibility.h +index 172bb7e..e369899 100644 +--- a/shared/os-compatibility.h ++++ b/shared/os-compatibility.h +@@ -26,6 +26,7 @@ + #include "config.h" + + #include <sys/types.h> ++#include <time.h> + + #ifdef HAVE_EXECINFO_H + #include <execinfo.h> +@@ -37,6 +38,10 @@ backtrace(void **buffer, int size) + } + #endif + ++#ifndef CLOCK_BOOTTIME ++#define CLOCK_BOOTTIME 7 ++#endif ++ + int + os_socketpair_cloexec(int domain, int type, int protocol, int *sv); + +-- +2.1.0 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1005-protocol-add-weston-debug.xml.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1005-protocol-add-weston-debug.xml.patch new file mode 100644 index 00000000..4ca79b72 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1005-protocol-add-weston-debug.xml.patch @@ -0,0 +1,242 @@ +From 4fc1ee8d5b5c2a66fcc1a5bafad3eb95c3759bac Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen <pq@iki.fi> +Date: Thu, 12 Oct 2017 13:13:41 +0200 +Subject: [PATCH 05/46] protocol: add weston-debug.xml + +This is a new debugging extension for non-production environments. The +aim is to replace all build-time choosable debug prints in the +compositor with runtime subscribable debug streams. + +Signed-off-by: Pekka Paalanen <pq@iki.fi> + +Added new libweston-$MAJOR-protocols.pc file and install that +for external projects to find the XML files installed by libweston. + +Signed-off-by: Maniraj Devadoss <Maniraj.Devadoss@in.bosch.com> + +Use noarch_pkgconfig_DATA instead, add ${pc_sysrootdir}, drop +unnecessary EXTRA_DIST of weston-debug.xml. + +Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> + +Add explicit advertisement of available debug interfaces. + +Signed-off-by: Daniel Stone <daniels@collabora.com> +Reviewed-by: Emre Ucan <eucan@de.adit-jv.com> +--- + Makefile.am | 10 +++ + configure.ac | 1 + + libweston/libweston-protocols.pc.in | 7 ++ + protocol/weston-debug.xml | 139 ++++++++++++++++++++++++++++++++++++ + 4 files changed, 157 insertions(+) + create mode 100644 libweston/libweston-protocols.pc.in + create mode 100644 protocol/weston-debug.xml + +diff --git a/Makefile.am b/Makefile.am +index 83546b7c..e38ac009 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -104,6 +104,10 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ + shared/platform.h \ + shared/weston-egl-ext.h + ++libweston_@LIBWESTON_MAJOR@_datadir = $(datadir)/weston/protocols ++dist_libweston_@LIBWESTON_MAJOR@_data_DATA = \ ++ protocol/weston-debug.xml ++ + lib_LTLIBRARIES += libweston-desktop-@LIBWESTON_MAJOR@.la + libweston_desktop_@LIBWESTON_MAJOR@_la_CPPFLAGS = $(AM_CPPFLAGS) -DIN_WESTON + libweston_desktop_@LIBWESTON_MAJOR@_la_CFLAGS = $(AM_CFLAGS) $(COMPOSITOR_CFLAGS) +@@ -150,6 +154,8 @@ endif + nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ + protocol/weston-screenshooter-protocol.c \ + protocol/weston-screenshooter-server-protocol.h \ ++ protocol/weston-debug-protocol.c \ ++ protocol/weston-debug-server-protocol.h \ + protocol/text-cursor-position-protocol.c \ + protocol/text-cursor-position-server-protocol.h \ + protocol/text-input-unstable-v1-protocol.c \ +@@ -274,6 +280,10 @@ pkgconfig_DATA = \ + libweston-desktop/libweston-desktop-${LIBWESTON_MAJOR}.pc \ + compositor/weston.pc + ++noarch_pkgconfigdir = $(datadir)/pkgconfig ++noarch_pkgconfig_DATA = \ ++ libweston/libweston-${LIBWESTON_MAJOR}-protocols.pc ++ + wayland_sessiondir = $(datadir)/wayland-sessions + dist_wayland_session_DATA = compositor/weston.desktop + +diff --git a/configure.ac b/configure.ac +index ab9ff7c7..cb62a386 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -695,6 +695,7 @@ AC_CONFIG_FILES([Makefile libweston/version.h compositor/weston.pc]) + # libweston_abi_version here, and outside [] because of m4 quoting rules + AC_CONFIG_FILES([libweston/libweston-]libweston_major_version[.pc:libweston/libweston.pc.in]) + AC_CONFIG_FILES([libweston/libweston-]libweston_major_version[-uninstalled.pc:libweston/libweston-uninstalled.pc.in]) ++AC_CONFIG_FILES([libweston/libweston-]libweston_major_version[-protocols.pc:libweston/libweston-protocols.pc.in]) + AC_CONFIG_FILES([libweston-desktop/libweston-desktop-]libweston_major_version[.pc:libweston-desktop/libweston-desktop.pc.in]) + AC_CONFIG_FILES([libweston-desktop/libweston-desktop-]libweston_major_version[-uninstalled.pc:libweston-desktop/libweston-desktop-uninstalled.pc.in]) + +diff --git a/libweston/libweston-protocols.pc.in b/libweston/libweston-protocols.pc.in +new file mode 100644 +index 00000000..6547a0d5 +--- /dev/null ++++ b/libweston/libweston-protocols.pc.in +@@ -0,0 +1,7 @@ ++prefix=@prefix@ ++datarootdir=@datarootdir@ ++pkgdatadir=${pc_sysrootdir}@datadir@/@PACKAGE@/protocols ++ ++Name: libWeston Protocols ++Description: libWeston protocol files ++Version: @WESTON_VERSION@ +diff --git a/protocol/weston-debug.xml b/protocol/weston-debug.xml +new file mode 100644 +index 00000000..effa1a19 +--- /dev/null ++++ b/protocol/weston-debug.xml +@@ -0,0 +1,139 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<protocol name="weston_debug"> ++ ++ <copyright> ++ Copyright © 2017 Pekka Paalanen pq@iki.fi ++ Copyright © 2018 Zodiac Inflight Innovations ++ ++ 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="weston_debug_v1" version="1"> ++ <description summary="weston internal debugging"> ++ This is a generic debugging interface for Weston internals, the global ++ object advertized through wl_registry. ++ ++ WARNING: This interface by design allows a denial-of-service attack. It ++ should not be offered in production, or proper authorization mechnisms ++ must be enforced. ++ ++ The idea is for a client to provide a file descriptor that the server ++ uses for printing debug information. The server uses the file ++ descriptor in blocking writes mode, which exposes the denial-of-service ++ risk. The blocking mode is necessary to ensure all debug messages can ++ be easily printed in place. It also ensures message ordering if a ++ client subcribes to more than one debug stream. ++ ++ The available debugging features depend on the server. ++ ++ A debug stream can be one-shot where the server prints the requested ++ information and then closes it, or continuous where server keeps on ++ printing until the client stops it. Or anything in between. ++ </description> ++ ++ <request name="destroy" type="destructor"> ++ <description summary="destroy factory object"> ++ Destroys the factory object, but does not affect any other objects. ++ </description> ++ </request> ++ ++ <event name="available"> ++ <description summary="advertise available debug scope"> ++ Advertises an available debug scope which the client may be able to ++ bind to. No information is provided by the server about the content ++ contained within the debug streams provided by the scope, once a ++ client has subscribed. ++ </description> ++ ++ <arg name="name" type="string" allow-null="false" ++ summary="debug stream name"/> ++ <arg name="description" type="string" allow-null="true" ++ summary="human-readable description of the debug scope"/> ++ </event> ++ ++ <request name="subscribe"> ++ <description summary="subscribe to a debug stream"> ++ Subscribe to a named debug stream. The server will start printing ++ to the given file descriptor. ++ ++ If the named debug stream is a one-shot dump, the server will send ++ weston_debug_stream_v1.complete event once all requested data has ++ been printed. Otherwise, the server will continue streaming debug ++ prints until the subscription object is destroyed. ++ ++ If the debug stream name is unknown to the server, the server will ++ immediately respond with weston_debug_stream_v1.failure event. ++ </description> ++ ++ <arg name="name" type="string" allow-null="false" ++ summary="debug stream name"/> ++ <arg name="streamfd" type="fd" summary="write stream file descriptor"/> ++ <arg name="stream" type="new_id" interface="weston_debug_stream_v1" ++ summary="created debug stream object"/> ++ </request> ++ </interface> ++ ++ <interface name="weston_debug_stream_v1" version="1"> ++ <description summary="A subscribed debug stream"> ++ Represents one subscribed debug stream, created with ++ weston_debug_v1.subscribe. When the object is created, it is associated ++ with a given file descriptor. The server will continue writing to the ++ file descriptor until the object is destroyed or the server sends an ++ event through the object. ++ </description> ++ ++ <request name="destroy" type="destructor"> ++ <description summary="close a debug stream"> ++ Destroys the object, which causes the server to stop writing into ++ and closes the associated file descriptor if it was not closed ++ already. ++ ++ Use a wl_display.sync if the clients needs to guarantee the file ++ descriptor is closed before continuing. ++ </description> ++ </request> ++ ++ <event name="complete"> ++ <description summary="server completed the debug stream"> ++ The server has successfully finished writing to and has closed the ++ associated file descriptor. ++ ++ This event is delivered only for one-shot debug streams where the ++ server dumps some data and stop. This is never delivered for ++ continuous debbug streams because they by definition never complete. ++ </description> ++ </event> ++ ++ <event name="failure"> ++ <description summary="server cannot continue the debug stream"> ++ The server has stopped writing to and has closed the ++ associated file descriptor. The data already written to the file ++ descriptor is correct, but it may be truncated. ++ ++ This event may be delivered at any time and for any kind of debug ++ stream. It may be due to a failure in or shutdown of the server. ++ The message argument may provide a hint of the reason. ++ </description> ++ ++ <arg name="message" type="string" allow-null="true" ++ summary="human readable reason"/> ++ </event> ++ </interface> ++</protocol> +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1006-libweston-add-weston_debug-API-and-implementation.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1006-libweston-add-weston_debug-API-and-implementation.patch new file mode 100644 index 00000000..83887c66 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1006-libweston-add-weston_debug-API-and-implementation.patch @@ -0,0 +1,958 @@ +From a5630eafec4f139adf1da4a5ba54894715d7b50f Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen <pq@iki.fi> +Date: Thu, 12 Oct 2017 13:13:42 +0200 +Subject: [PATCH 06/46] libweston: add weston_debug API and implementation + +weston_debug is both a libweston API for relaying debugging messages, +and the compositor-debug wayland protocol implementation for accessing those +debug messages from a Wayland client. + +weston_debug_compositor_{create,destroy}() are private API, hence not +exported. + +Signed-off-by: Pekka Paalanen <pq@iki.fi> + +append the debug scope name along with the timestamp in +weston_debug_scope_timestamp API + +Signed-off-by: Maniraj Devadoss <Maniraj.Devadoss@in.bosch.com> +Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> + +Add explicit advertisement of debug scope names. + +Signed-off-by: Daniel Stone <daniels@collabora.com> +Reviewed-by: Emre Ucan <eucan@de.adit-jv.com> +--- + Makefile.am | 2 + + libweston/compositor.c | 5 + + libweston/compositor.h | 9 + + libweston/weston-debug.c | 732 +++++++++++++++++++++++++++++++++++++++++++++++ + libweston/weston-debug.h | 107 +++++++ + 5 files changed, 855 insertions(+) + create mode 100644 libweston/weston-debug.c + create mode 100644 libweston/weston-debug.h + +diff --git a/Makefile.am b/Makefile.am +index e38ac009..d5ed3e58 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -96,6 +96,8 @@ libweston_@LIBWESTON_MAJOR@_la_SOURCES = \ + libweston/linux-dmabuf.h \ + libweston/pixel-formats.c \ + libweston/pixel-formats.h \ ++ libweston/weston-debug.c \ ++ libweston/weston-debug.h \ + shared/helpers.h \ + shared/matrix.c \ + shared/matrix.h \ +diff --git a/libweston/compositor.c b/libweston/compositor.c +index 9deb7817..01616550 100644 +--- a/libweston/compositor.c ++++ b/libweston/compositor.c +@@ -6361,6 +6361,9 @@ weston_compositor_create(struct wl_display *display, void *user_data) + ec, bind_presentation)) + goto fail; + ++ if (weston_debug_compositor_create(ec) < 0) ++ goto fail; ++ + if (weston_input_init(ec) != 0) + goto fail; + +@@ -6702,6 +6705,8 @@ weston_compositor_destroy(struct weston_compositor *compositor) + if (compositor->heads_changed_source) + wl_event_source_remove(compositor->heads_changed_source); + ++ weston_debug_compositor_destroy(compositor); ++ + free(compositor); + } + +diff --git a/libweston/compositor.h b/libweston/compositor.h +index 8b7a1020..33f02b18 100644 +--- a/libweston/compositor.h ++++ b/libweston/compositor.h +@@ -1048,6 +1048,7 @@ struct weston_touch_calibrator; + + struct weston_desktop_xwayland; + struct weston_desktop_xwayland_interface; ++struct weston_debug_compositor; + + struct weston_compositor { + struct wl_signal destroy_signal; +@@ -1160,6 +1161,8 @@ struct weston_compositor { + weston_touch_calibration_save_func touch_calibration_save; + struct weston_layer calibrator_layer; + struct weston_touch_calibrator *touch_calibrator; ++ ++ struct weston_debug_compositor *weston_debug; + }; + + struct weston_buffer { +@@ -2318,6 +2321,12 @@ int + weston_compositor_enable_touch_calibrator(struct weston_compositor *compositor, + weston_touch_calibration_save_func save); + ++int ++weston_debug_compositor_create(struct weston_compositor *compositor); ++ ++void ++weston_debug_compositor_destroy(struct weston_compositor *compositor); ++ + #ifdef __cplusplus + } + #endif +diff --git a/libweston/weston-debug.c b/libweston/weston-debug.c +new file mode 100644 +index 00000000..04895ad5 +--- /dev/null ++++ b/libweston/weston-debug.c +@@ -0,0 +1,732 @@ ++/* ++ * Copyright © 2017 Pekka Paalanen <pq@iki.fi> ++ * Copyright © 2018 Zodiac Inflight Innovations ++ * ++ * 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 "config.h" ++ ++#include "weston-debug.h" ++#include "helpers.h" ++#include "compositor.h" ++ ++#include "weston-debug-server-protocol.h" ++ ++#include <assert.h> ++#include <unistd.h> ++#include <stdarg.h> ++#include <string.h> ++#include <errno.h> ++#include <sys/time.h> ++ ++/** Main weston-debug context ++ * ++ * One per weston_compositor. ++ * ++ * \internal ++ */ ++struct weston_debug_compositor { ++ struct weston_compositor *compositor; ++ struct wl_listener compositor_destroy_listener; ++ struct wl_global *global; ++ struct wl_list scope_list; /**< weston_debug_scope::compositor_link */ ++}; ++ ++/** weston-debug message scope ++ * ++ * This is used for scoping debugging messages. Clients can subscribe to ++ * only the scopes they are interested in. A scope is identified by its name ++ * (also referred to as debug stream name). ++ */ ++struct weston_debug_scope { ++ char *name; ++ char *desc; ++ weston_debug_scope_cb begin_cb; ++ void *user_data; ++ struct wl_list stream_list; /**< weston_debug_stream::scope_link */ ++ struct wl_list compositor_link; ++}; ++ ++/** A debug stream created by a client ++ * ++ * A client provides a file descriptor for the server to write debug ++ * messages into. A weston_debug_stream is associated to one ++ * weston_debug_scope via the scope name, and the scope provides the messages. ++ * There can be several streams for the same scope, all streams getting the ++ * same messages. ++ */ ++struct weston_debug_stream { ++ int fd; /**< client provided fd */ ++ struct wl_resource *resource; /**< weston_debug_stream_v1 object */ ++ struct wl_list scope_link; ++}; ++ ++static struct weston_debug_scope * ++get_scope(struct weston_debug_compositor *wdc, const char *name) ++{ ++ struct weston_debug_scope *scope; ++ ++ wl_list_for_each(scope, &wdc->scope_list, compositor_link) ++ if (strcmp(name, scope->name) == 0) ++ return scope; ++ ++ return NULL; ++} ++ ++static void ++stream_close_unlink(struct weston_debug_stream *stream) ++{ ++ if (stream->fd != -1) ++ close(stream->fd); ++ stream->fd = -1; ++ ++ wl_list_remove(&stream->scope_link); ++ wl_list_init(&stream->scope_link); ++} ++ ++static void WL_PRINTF(2, 3) ++stream_close_on_failure(struct weston_debug_stream *stream, ++ const char *fmt, ...) ++{ ++ char *msg; ++ va_list ap; ++ int ret; ++ ++ stream_close_unlink(stream); ++ ++ va_start(ap, fmt); ++ ret = vasprintf(&msg, fmt, ap); ++ va_end(ap); ++ ++ if (ret > 0) { ++ weston_debug_stream_v1_send_failure(stream->resource, msg); ++ free(msg); ++ } else { ++ weston_debug_stream_v1_send_failure(stream->resource, ++ "MEMFAIL"); ++ } ++} ++ ++static struct weston_debug_stream * ++stream_create(struct weston_debug_compositor *wdc, const char *name, ++ int32_t streamfd, struct wl_resource *stream_resource) ++{ ++ struct weston_debug_stream *stream; ++ struct weston_debug_scope *scope; ++ ++ stream = zalloc(sizeof *stream); ++ if (!stream) ++ return NULL; ++ ++ stream->fd = streamfd; ++ stream->resource = stream_resource; ++ ++ scope = get_scope(wdc, name); ++ if (scope) { ++ wl_list_insert(&scope->stream_list, &stream->scope_link); ++ ++ if (scope->begin_cb) ++ scope->begin_cb(stream, scope->user_data); ++ } else { ++ wl_list_init(&stream->scope_link); ++ stream_close_on_failure(stream, ++ "Debug stream name '%s' is unknown.", ++ name); ++ } ++ ++ return stream; ++} ++ ++static void ++stream_destroy(struct wl_resource *stream_resource) ++{ ++ struct weston_debug_stream *stream; ++ ++ stream = wl_resource_get_user_data(stream_resource); ++ ++ if (stream->fd != -1) ++ close(stream->fd); ++ wl_list_remove(&stream->scope_link); ++ free(stream); ++} ++ ++static void ++weston_debug_stream_destroy(struct wl_client *client, ++ struct wl_resource *stream_resource) ++{ ++ wl_resource_destroy(stream_resource); ++} ++ ++static const struct weston_debug_stream_v1_interface ++ weston_debug_stream_impl = { ++ weston_debug_stream_destroy ++}; ++ ++static void ++weston_debug_destroy(struct wl_client *client, ++ struct wl_resource *global_resource) ++{ ++ wl_resource_destroy(global_resource); ++} ++ ++static void ++weston_debug_subscribe(struct wl_client *client, ++ struct wl_resource *global_resource, ++ const char *name, ++ int32_t streamfd, ++ uint32_t new_stream_id) ++{ ++ struct weston_debug_compositor *wdc; ++ struct wl_resource *stream_resource; ++ uint32_t version; ++ struct weston_debug_stream *stream; ++ ++ wdc = wl_resource_get_user_data(global_resource); ++ version = wl_resource_get_version(global_resource); ++ ++ stream_resource = wl_resource_create(client, ++ &weston_debug_stream_v1_interface, ++ version, new_stream_id); ++ if (!stream_resource) ++ goto fail; ++ ++ stream = stream_create(wdc, name, streamfd, stream_resource); ++ if (!stream) ++ goto fail; ++ ++ wl_resource_set_implementation(stream_resource, ++ &weston_debug_stream_impl, ++ stream, stream_destroy); ++ return; ++ ++fail: ++ close(streamfd); ++ wl_client_post_no_memory(client); ++} ++ ++static const struct weston_debug_v1_interface weston_debug_impl = { ++ weston_debug_destroy, ++ weston_debug_subscribe ++}; ++ ++static void ++bind_weston_debug(struct wl_client *client, ++ void *data, uint32_t version, uint32_t id) ++{ ++ struct weston_debug_compositor *wdc = data; ++ struct weston_debug_scope *scope; ++ struct wl_resource *resource; ++ ++ resource = wl_resource_create(client, ++ &weston_debug_v1_interface, ++ version, id); ++ if (!resource) { ++ wl_client_post_no_memory(client); ++ return; ++ } ++ wl_resource_set_implementation(resource, &weston_debug_impl, ++ wdc, NULL); ++ ++ wl_list_for_each(scope, &wdc->scope_list, compositor_link) { ++ weston_debug_v1_send_available(resource, scope->name, ++ scope->desc); ++ } ++} ++ ++/** Initialize weston-debug structure ++ * ++ * \param compositor The libweston compositor. ++ * \return 0 on success, -1 on failure. ++ * ++ * weston_debug_compositor is a singleton for each weston_compositor. ++ * ++ * Sets weston_compositor::weston_debug. ++ * ++ * \internal ++ */ ++int ++weston_debug_compositor_create(struct weston_compositor *compositor) ++{ ++ struct weston_debug_compositor *wdc; ++ ++ if (compositor->weston_debug) ++ return -1; ++ ++ wdc = zalloc(sizeof *wdc); ++ if (!wdc) ++ return -1; ++ ++ wdc->compositor = compositor; ++ wl_list_init(&wdc->scope_list); ++ ++ compositor->weston_debug = wdc; ++ ++ return 0; ++} ++ ++/** Destroy weston_debug_compositor structure ++ * ++ * \param compositor The libweston compositor whose weston-debug to tear down. ++ * ++ * Clears weston_compositor::weston_debug. ++ * ++ * \internal ++ */ ++void ++weston_debug_compositor_destroy(struct weston_compositor *compositor) ++{ ++ struct weston_debug_compositor *wdc = compositor->weston_debug; ++ struct weston_debug_scope *scope; ++ ++ if (wdc->global) ++ wl_global_destroy(wdc->global); ++ ++ wl_list_for_each(scope, &wdc->scope_list, compositor_link) ++ weston_log("Internal warning: debug scope '%s' has not been destroyed.\n", ++ scope->name); ++ ++ /* Remove head to not crash if scope removed later. */ ++ wl_list_remove(&wdc->scope_list); ++ ++ free(wdc); ++ ++ compositor->weston_debug = NULL; ++} ++ ++/** Enable weston-debug protocol extension ++ * ++ * \param compositor The libweston compositor where to enable. ++ * ++ * This enables the weston_debug_v1 Wayland protocol extension which any client ++ * can use to get debug messsages from the compositor. ++ * ++ * WARNING: This feature should not be used in production. If a client ++ * provides a file descriptor that blocks writes, it will block the whole ++ * compositor indefinitely. ++ * ++ * There is no control on which client is allowed to subscribe to debug ++ * messages. Any and all clients are allowed. ++ * ++ * The debug extension is disabled by default, and once enabled, cannot be ++ * disabled again. ++ */ ++WL_EXPORT void ++weston_compositor_enable_debug_protocol(struct weston_compositor *compositor) ++{ ++ struct weston_debug_compositor *wdc = compositor->weston_debug; ++ ++ assert(wdc); ++ if (wdc->global) ++ return; ++ ++ wdc->global = wl_global_create(compositor->wl_display, ++ &weston_debug_v1_interface, 1, ++ wdc, bind_weston_debug); ++ if (!wdc->global) ++ return; ++ ++ weston_log("WARNING: debug protocol has been enabled. " ++ "This is a potential denial-of-service attack vector and " ++ "information leak.\n"); ++} ++ ++/** Register a new debug stream name, creating a debug scope ++ * ++ * \param compositor The libweston compositor where to add. ++ * \param name The debug stream/scope name; must not be NULL. ++ * \param desc The debug scope description for humans; must not be NULL. ++ * \param begin_cb Optional callback when a client subscribes to this scope. ++ * \param user_data Optional user data pointer for the callback. ++ * \return A valid pointer on success, NULL on failure. ++ * ++ * This function is used to create a debug scope. All debug message printing ++ * happens for a scope, which allows clients to subscribe to the kind of ++ * debug messages they want by \c name. ++ * ++ * \c name must be unique in the \c weston_compositor instance. \c name and ++ * \c description must both be provided. The description is printed when a ++ * client asks for a list of supported debug scopes. ++ * ++ * \c begin_cb, if not NULL, is called when a client subscribes to the ++ * debug scope creating a debug stream. This is for debug scopes that need ++ * to print messages as a response to a client appearing, e.g. printing a ++ * list of windows on demand or a static preamble. The argument \c user_data ++ * is passed in to the callback and is otherwise unused. ++ * ++ * For one-shot debug streams, \c begin_cb should finally call ++ * weston_debug_stream_complete() to close the stream and tell the client ++ * the printing is complete. Otherwise the client expects more to be written ++ * to its file descriptor. ++ * ++ * The debug scope must be destroyed before destroying the ++ * \c weston_compositor. ++ * ++ * \memberof weston_debug_scope ++ * \sa weston_debug_stream, weston_debug_scope_cb ++ */ ++WL_EXPORT struct weston_debug_scope * ++weston_compositor_add_debug_scope(struct weston_compositor *compositor, ++ const char *name, ++ const char *description, ++ weston_debug_scope_cb begin_cb, ++ void *user_data) ++{ ++ struct weston_debug_compositor *wdc; ++ struct weston_debug_scope *scope; ++ ++ if (!compositor || !name || !description) { ++ weston_log("Error: cannot add a debug scope without name or description.\n"); ++ return NULL; ++ } ++ ++ wdc = compositor->weston_debug; ++ if (!wdc) { ++ weston_log("Error: cannot add debug scope '%s', infra not initialized.\n", ++ name); ++ return NULL; ++ } ++ ++ if (get_scope(wdc, name)){ ++ weston_log("Error: debug scope named '%s' is already registered.\n", ++ name); ++ return NULL; ++ } ++ ++ scope = zalloc(sizeof *scope); ++ if (!scope) { ++ weston_log("Error adding debug scope '%s': out of memory.\n", ++ name); ++ return NULL; ++ } ++ ++ scope->name = strdup(name); ++ scope->desc = strdup(description); ++ scope->begin_cb = begin_cb; ++ scope->user_data = user_data; ++ wl_list_init(&scope->stream_list); ++ ++ if (!scope->name || !scope->desc) { ++ weston_log("Error adding debug scope '%s': out of memory.\n", ++ name); ++ free(scope->name); ++ free(scope->desc); ++ free(scope); ++ return NULL; ++ } ++ ++ wl_list_insert(wdc->scope_list.prev, &scope->compositor_link); ++ ++ return scope; ++} ++ ++/** Destroy a debug scope ++ * ++ * \param scope The debug scope to destroy; may be NULL. ++ * ++ * Destroys the debug scope, closing all open streams subscribed to it and ++ * sending them each a \c weston_debug_stream_v1.failure event. ++ * ++ * \memberof weston_debug_scope ++ */ ++WL_EXPORT void ++weston_debug_scope_destroy(struct weston_debug_scope *scope) ++{ ++ struct weston_debug_stream *stream; ++ ++ if (!scope) ++ return; ++ ++ while (!wl_list_empty(&scope->stream_list)) { ++ stream = wl_container_of(scope->stream_list.prev, ++ stream, scope_link); ++ ++ stream_close_on_failure(stream, "debug name removed"); ++ } ++ ++ wl_list_remove(&scope->compositor_link); ++ free(scope->name); ++ free(scope->desc); ++ free(scope); ++} ++ ++/** Are there any active subscriptions to the scope? ++ * ++ * \param scope The debug scope to check; may be NULL. ++ * \return True if any streams are open for this scope, false otherwise. ++ * ++ * As printing some debugging messages may be relatively expensive, one ++ * can use this function to determine if there is a need to gather the ++ * debugging information at all. If this function returns false, all ++ * printing for this scope is dropped, so gathering the information is ++ * pointless. ++ * ++ * The return value of this function should not be stored, as new clients ++ * may subscribe to the debug scope later. ++ * ++ * If the given scope is NULL, this function will always return false, ++ * making it safe to use in teardown or destroy code, provided the ++ * scope is initialized to NULL before creation and set to NULL after ++ * destruction. ++ * ++ * \memberof weston_debug_scope ++ */ ++WL_EXPORT bool ++weston_debug_scope_is_enabled(struct weston_debug_scope *scope) ++{ ++ if (!scope) ++ return false; ++ ++ return !wl_list_empty(&scope->stream_list); ++} ++ ++/** Write data into a specific debug stream ++ * ++ * \param stream The debug stream to write into; must not be NULL. ++ * \param data[in] Pointer to the data to write. ++ * \param len Number of bytes to write. ++ * ++ * Writes the given data (binary verbatim) into the debug stream. ++ * If \c len is zero or negative, the write is silently dropped. ++ * ++ * Writing is continued until all data has been written or ++ * a write fails. If the write fails due to a signal, it is re-tried. ++ * Otherwise on failure, the stream is closed and ++ * \c weston_debug_stream_v1.failure event is sent to the client. ++ * ++ * \memberof weston_debug_stream ++ */ ++WL_EXPORT void ++weston_debug_stream_write(struct weston_debug_stream *stream, ++ const char *data, size_t len) ++{ ++ ssize_t len_ = len; ++ ssize_t ret; ++ int e; ++ ++ if (stream->fd == -1) ++ return; ++ ++ while (len_ > 0) { ++ ret = write(stream->fd, data, len_); ++ e = errno; ++ if (ret < 0) { ++ if (e == EINTR) ++ continue; ++ ++ stream_close_on_failure(stream, ++ "Error writing %zd bytes: %s (%d)", ++ len_, strerror(e), e); ++ break; ++ } ++ ++ len_ -= ret; ++ data += ret; ++ } ++} ++ ++/** Write a formatted string into a specific debug stream (varargs) ++ * ++ * \param stream The debug stream to write into. ++ * \param fmt Printf-style format string. ++ * \param ap Formatting arguments. ++ * ++ * The behavioral details are the same as for weston_debug_stream_write(). ++ * ++ * \memberof weston_debug_stream ++ */ ++WL_EXPORT void ++weston_debug_stream_vprintf(struct weston_debug_stream *stream, ++ const char *fmt, va_list ap) ++{ ++ char *str; ++ int len; ++ ++ len = vasprintf(&str, fmt, ap); ++ if (len >= 0) { ++ weston_debug_stream_write(stream, str, len); ++ free(str); ++ } else { ++ stream_close_on_failure(stream, "Out of memory"); ++ } ++} ++ ++/** Write a formatted string into a specific debug stream ++ * ++ * \param stream The debug stream to write into. ++ * \param fmt Printf-style format string and arguments. ++ * ++ * The behavioral details are the same as for weston_debug_stream_write(). ++ * ++ * \memberof weston_debug_stream ++ */ ++WL_EXPORT void ++weston_debug_stream_printf(struct weston_debug_stream *stream, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, fmt); ++ weston_debug_stream_vprintf(stream, fmt, ap); ++ va_end(ap); ++} ++ ++/** Close the debug stream and send success event ++ * ++ * \param stream The debug stream to close. ++ * ++ * Closes the debug stream and sends \c weston_debug_stream_v1.complete ++ * event to the client. This tells the client the debug information dump ++ * is complete. ++ * ++ * \memberof weston_debug_stream ++ */ ++WL_EXPORT void ++weston_debug_stream_complete(struct weston_debug_stream *stream) ++{ ++ stream_close_unlink(stream); ++ weston_debug_stream_v1_send_complete(stream->resource); ++} ++ ++/** Write debug data for a scope ++ * ++ * \param scope The debug scope to write for; may be NULL, in which case ++ * nothing will be written. ++ * \param data[in] Pointer to the data to write. ++ * \param len Number of bytes to write. ++ * ++ * Writes the given data to all subscribed clients' streams. ++ * ++ * The behavioral details for each stream are the same as for ++ * weston_debug_stream_write(). ++ * ++ * \memberof weston_debug_scope ++ */ ++WL_EXPORT void ++weston_debug_scope_write(struct weston_debug_scope *scope, ++ const char *data, size_t len) ++{ ++ struct weston_debug_stream *stream; ++ ++ if (!scope) ++ return; ++ ++ wl_list_for_each(stream, &scope->stream_list, scope_link) ++ weston_debug_stream_write(stream, data, len); ++} ++ ++/** Write a formatted string for a scope (varargs) ++ * ++ * \param scope The debug scope to write for; may be NULL, in which case ++ * nothing will be written. ++ * \param fmt Printf-style format string. ++ * \param ap Formatting arguments. ++ * ++ * Writes to formatted string to all subscribed clients' streams. ++ * ++ * The behavioral details for each stream are the same as for ++ * weston_debug_stream_write(). ++ * ++ * \memberof weston_debug_scope ++ */ ++WL_EXPORT void ++weston_debug_scope_vprintf(struct weston_debug_scope *scope, ++ const char *fmt, va_list ap) ++{ ++ static const char oom[] = "Out of memory"; ++ char *str; ++ int len; ++ ++ if (!weston_debug_scope_is_enabled(scope)) ++ return; ++ ++ len = vasprintf(&str, fmt, ap); ++ if (len >= 0) { ++ weston_debug_scope_write(scope, str, len); ++ free(str); ++ } else { ++ weston_debug_scope_write(scope, oom, sizeof oom - 1); ++ } ++} ++ ++/** Write a formatted string for a scope ++ * ++ * \param scope The debug scope to write for; may be NULL, in which case ++ * nothing will be written. ++ * \param fmt Printf-style format string and arguments. ++ * ++ * Writes to formatted string to all subscribed clients' streams. ++ * ++ * The behavioral details for each stream are the same as for ++ * weston_debug_stream_write(). ++ * ++ * \memberof weston_debug_scope ++ */ ++WL_EXPORT void ++weston_debug_scope_printf(struct weston_debug_scope *scope, ++ const char *fmt, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, fmt); ++ weston_debug_scope_vprintf(scope, fmt, ap); ++ va_end(ap); ++} ++ ++/** Write debug scope name and current time into string ++ * ++ * \param scope[in] debug scope; may be NULL ++ * \param buf[out] Buffer to store the string. ++ * \param len Available size in the buffer in bytes. ++ * \return \c buf ++ * ++ * Reads the current local wall-clock time and formats it into a string. ++ * and append the debug scope name to it, if a scope is available. ++ * The string is NUL-terminated, even if truncated. ++ */ ++WL_EXPORT char * ++weston_debug_scope_timestamp(struct weston_debug_scope *scope, ++ char *buf, size_t len) ++{ ++ struct timeval tv; ++ struct tm *bdt; ++ char string[128]; ++ size_t ret = 0; ++ ++ gettimeofday(&tv, NULL); ++ ++ bdt = localtime(&tv.tv_sec); ++ if (bdt) ++ ret = strftime(string, sizeof string, ++ "%Y-%m-%d %H:%M:%S", bdt); ++ ++ if (ret > 0) { ++ snprintf(buf, len, "[%s.%03ld][%s]", string, ++ tv.tv_usec / 1000, ++ (scope) ? scope->name : "no scope"); ++ } else { ++ snprintf(buf, len, "[?][%s]", ++ (scope) ? scope->name : "no scope"); ++ } ++ ++ return buf; ++} +diff --git a/libweston/weston-debug.h b/libweston/weston-debug.h +new file mode 100644 +index 00000000..c76cec85 +--- /dev/null ++++ b/libweston/weston-debug.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright © 2017 Pekka Paalanen <pq@iki.fi> ++ * ++ * 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. ++ */ ++ ++#ifndef WESTON_DEBUG_H ++#define WESTON_DEBUG_H ++ ++#include <stdbool.h> ++#include <stdlib.h> ++#include <stdarg.h> ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++struct weston_compositor; ++ ++void ++weston_compositor_enable_debug_protocol(struct weston_compositor *); ++ ++struct weston_debug_scope; ++struct weston_debug_stream; ++ ++/** weston_debug_scope callback ++ * ++ * \param stream The debug stream. ++ * \param user_data The \c user_data argument given to ++ * weston_compositor_add_debug_scope() ++ * ++ * \memberof weston_debug_scope ++ * \sa weston_debug_stream ++ */ ++typedef void (*weston_debug_scope_cb)(struct weston_debug_stream *stream, ++ void *user_data); ++ ++struct weston_debug_scope * ++weston_compositor_add_debug_scope(struct weston_compositor *compositor, ++ const char *name, ++ const char *description, ++ weston_debug_scope_cb begin_cb, ++ void *user_data); ++ ++void ++weston_debug_scope_destroy(struct weston_debug_scope *scope); ++ ++bool ++weston_debug_scope_is_enabled(struct weston_debug_scope *scope); ++ ++void ++weston_debug_scope_write(struct weston_debug_scope *scope, ++ const char *data, size_t len); ++ ++void ++weston_debug_scope_vprintf(struct weston_debug_scope *scope, ++ const char *fmt, va_list ap); ++ ++void ++weston_debug_scope_printf(struct weston_debug_scope *scope, ++ const char *fmt, ...) ++ __attribute__ ((format (printf, 2, 3))); ++ ++void ++weston_debug_stream_write(struct weston_debug_stream *stream, ++ const char *data, size_t len); ++ ++void ++weston_debug_stream_vprintf(struct weston_debug_stream *stream, ++ const char *fmt, va_list ap); ++ ++void ++weston_debug_stream_printf(struct weston_debug_stream *stream, ++ const char *fmt, ...) ++ __attribute__ ((format (printf, 2, 3))); ++ ++void ++weston_debug_stream_complete(struct weston_debug_stream *stream); ++ ++char * ++weston_debug_scope_timestamp(struct weston_debug_scope *scope, ++ char *buf, size_t len); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* WESTON_DEBUG_H */ +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1007-compositor-add-option-to-enable-weston_debug.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1007-compositor-add-option-to-enable-weston_debug.patch new file mode 100644 index 00000000..34422850 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1007-compositor-add-option-to-enable-weston_debug.patch @@ -0,0 +1,87 @@ +From 771b7cfc11cec3638b0a4f47edeeaabe2ba46cb6 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen <pq@iki.fi> +Date: Thu, 12 Oct 2017 13:13:43 +0200 +Subject: [PATCH 07/46] compositor: add option to enable weston_debug + +Let users enable the compositor debug protocol on the compositor command +line. This allows weston-debug tool to work. + +Signed-off-by: Pekka Paalanen <pq@iki.fi> +Signed-off-by: Maniraj Devadoss <Maniraj.Devadoss@in.bosch.com> +Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> +--- + compositor/main.c | 7 +++++++ + man/weston.man | 11 +++++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/compositor/main.c b/compositor/main.c +index b5b4fc59..2f34e111 100644 +--- a/compositor/main.c ++++ b/compositor/main.c +@@ -60,6 +60,7 @@ + #include "compositor-x11.h" + #include "compositor-wayland.h" + #include "windowed-output-api.h" ++#include "weston-debug.h" + + #define WINDOW_TITLE "Weston Compositor" + +@@ -508,6 +509,7 @@ usage(int error_code) + " -c, --config=FILE\tConfig file to load, defaults to weston.ini\n" + " --no-config\t\tDo not read weston.ini\n" + " --wait-for-debugger\tRaise SIGSTOP on start-up\n" ++ " --debug\t\tEnable debug extension\n" + " -h, --help\t\tThis help message\n\n"); + + #if defined(BUILD_DRM_COMPOSITOR) +@@ -2375,6 +2377,7 @@ int main(int argc, char *argv[]) + char *socket_name = NULL; + int32_t version = 0; + int32_t noconfig = 0; ++ int32_t debug_protocol = 0; + int32_t numlock_on; + char *config_file = NULL; + struct weston_config *config = NULL; +@@ -2399,6 +2402,7 @@ int main(int argc, char *argv[]) + { WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig }, + { WESTON_OPTION_STRING, "config", 'c', &config_file }, + { WESTON_OPTION_BOOLEAN, "wait-for-debugger", 0, &wait_for_debugger }, ++ { WESTON_OPTION_BOOLEAN, "debug", 0, &debug_protocol }, + }; + + wl_list_init(&wet.layoutput_list); +@@ -2486,6 +2490,9 @@ int main(int argc, char *argv[]) + } + segv_compositor = wet.compositor; + ++ if (debug_protocol) ++ weston_compositor_enable_debug_protocol(wet.compositor); ++ + if (weston_compositor_init_config(wet.compositor, config) < 0) + goto out; + +diff --git a/man/weston.man b/man/weston.man +index 44a73fa0..c09d4c2d 100644 +--- a/man/weston.man ++++ b/man/weston.man +@@ -133,6 +133,17 @@ If also + .B --no-config + is given, no configuration file will be read. + .TP ++.BR \-\-debug ++Enable debug protocol extension ++.I weston_debug_v1 ++which any client can use to receive debugging messages from the compositor. ++ ++.B WARNING: ++This is risky for two reasons. First, a client may cause a denial-of-service ++blocking the compositor by providing an unsuitable file descriptor, and ++second, the debug messages may expose sensitive information. This option ++should not be used in production. ++.TP + .BR \-\-version + Print the program version. + .TP +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1010-xwm-dump_property-to-use-FILE-internally.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1010-xwm-dump_property-to-use-FILE-internally.patch new file mode 100644 index 00000000..e9e46002 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1010-xwm-dump_property-to-use-FILE-internally.patch @@ -0,0 +1,141 @@ +From 0a3ef9902a210ab1fa0e4ed317ad7782f0399b51 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen <pq@iki.fi> +Date: Thu, 12 Oct 2017 13:18:12 +0200 +Subject: [PATCH 10/46] xwm: dump_property() to use FILE internally + +Write the output of dump_property() out in one log call. When multiple +processes (weston and Xwayland) are writing to the same file, this will +keep the property dump uninterrupted by Xwayland debug prints. + +This is also preparation for more development in the same direction. + +Signed-off-by: Pekka Paalanen <pq@iki.fi> +Signed-off-by: Maniraj Devadoss <Maniraj.Devadoss@in.bosch.com> +Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> +Reviewed-by: Daniel Stone <daniels@collabora.com> +--- + xwayland/window-manager.c | 58 ++++++++++++++++++++++++----------------------- + 1 file changed, 30 insertions(+), 28 deletions(-) + +diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c +index 2b3defb7..3bf323a4 100644 +--- a/xwayland/window-manager.c ++++ b/xwayland/window-manager.c +@@ -410,20 +410,14 @@ dump_cardinal_array_elem(FILE *fp, unsigned format, + } + + static void +-dump_cardinal_array(xcb_get_property_reply_t *reply) ++dump_cardinal_array(FILE *fp, xcb_get_property_reply_t *reply) + { + unsigned i = 0; +- FILE *fp; + void *arr; + char *str = NULL; +- size_t size = 0; + + assert(reply->type == XCB_ATOM_CARDINAL); + +- fp = open_memstream(&str, &size); +- if (!fp) +- return; +- + arr = xcb_get_property_value(reply); + + fprintf(fp, "["); +@@ -432,10 +426,6 @@ dump_cardinal_array(xcb_get_property_reply_t *reply) + arr, reply->value_len, i); + fprintf(fp, "]"); + +- if (fclose(fp) != 0) +- return; +- +- wm_log_continue("%s\n", str); + free(str); + } + +@@ -449,22 +439,29 @@ dump_property(struct weston_wm *wm, + xcb_window_t *window_value; + int width, len; + uint32_t i; ++ FILE *fp; ++ char *logstr; ++ size_t logsize; + +- width = wm_log_continue("%s: ", get_atom_name(wm->conn, property)); +- if (reply == NULL) { +- wm_log_continue("(no reply)\n"); ++ fp = open_memstream(&logstr, &logsize); ++ if (!fp) + return; ++ ++ width = fprintf(fp, "%s: ", get_atom_name(wm->conn, property)); ++ if (reply == NULL) { ++ fprintf(fp, "(no reply)\n"); ++ goto out; + } + +- width += wm_log_continue("%s/%d, length %d (value_len %d): ", +- get_atom_name(wm->conn, reply->type), +- reply->format, +- xcb_get_property_value_length(reply), +- reply->value_len); ++ width += fprintf(fp, "%s/%d, length %d (value_len %d): ", ++ get_atom_name(wm->conn, reply->type), ++ reply->format, ++ xcb_get_property_value_length(reply), ++ reply->value_len); + + if (reply->type == wm->atom.incr) { + incr_value = xcb_get_property_value(reply); +- wm_log_continue("%d\n", *incr_value); ++ fprintf(fp, "%d\n", *incr_value); + } else if (reply->type == wm->atom.utf8_string || + reply->type == wm->atom.string) { + text_value = xcb_get_property_value(reply); +@@ -472,29 +469,34 @@ dump_property(struct weston_wm *wm, + len = 40; + else + len = reply->value_len; +- wm_log_continue("\"%.*s\"\n", len, text_value); ++ fprintf(fp, "\"%.*s\"\n", len, text_value); + } else if (reply->type == XCB_ATOM_ATOM) { + atom_value = xcb_get_property_value(reply); + for (i = 0; i < reply->value_len; i++) { + name = get_atom_name(wm->conn, atom_value[i]); + if (width + strlen(name) + 2 > 78) { +- wm_log_continue("\n "); ++ fprintf(fp, "\n "); + width = 4; + } else if (i > 0) { +- width += wm_log_continue(", "); ++ width += fprintf(fp, ", "); + } + +- width += wm_log_continue("%s", name); ++ width += fprintf(fp, "%s", name); + } +- wm_log_continue("\n"); ++ fprintf(fp, "\n"); + } else if (reply->type == XCB_ATOM_CARDINAL) { +- dump_cardinal_array(reply); ++ dump_cardinal_array(fp, reply); + } else if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) { + window_value = xcb_get_property_value(reply); +- wm_log_continue("win %u\n", *window_value); ++ fprintf(fp, "win %u\n", *window_value); + } else { +- wm_log_continue("huh?\n"); ++ fprintf(fp, "huh?\n"); + } ++ ++out: ++ if (fclose(fp) == 0) ++ wm_log_continue("%s", logstr); ++ free(logstr); + } + + static void +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1011-xwm-move-FILE-to-the-callers-of-dump_property.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1011-xwm-move-FILE-to-the-callers-of-dump_property.patch new file mode 100644 index 00000000..693bff29 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1011-xwm-move-FILE-to-the-callers-of-dump_property.patch @@ -0,0 +1,267 @@ +From b3b006559856037ab97200b93641640b88ec7db8 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen <pq@iki.fi> +Date: Thu, 12 Oct 2017 13:18:13 +0200 +Subject: [PATCH 11/46] xwm: move FILE to the callers of dump_property() + +This is preparation for using the weston-debug infrastructure for +WM_DEBUG. dump_property() may be called from different debugging +contexts and often needs to be prefixed with more information. + +An alternative to this patch would be to pass in the weston_debug_scope +as an argument to dump_property(), but then all callers would need to be +converted to weston-debug infra in a single commit. + +Therefore require the callers to provide the FILE* to print to. + +Signed-off-by: Pekka Paalanen <pq@iki.fi> +Signed-off-by: Maniraj Devadoss <Maniraj.Devadoss@in.bosch.com> +Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> +Reviewed-by: Daniel Stone <daniels@collabora.com> +--- + xwayland/selection.c | 39 ++++++++++++++++++++++++--- + xwayland/window-manager.c | 67 +++++++++++++++++++---------------------------- + xwayland/xwayland.h | 3 ++- + 3 files changed, 65 insertions(+), 44 deletions(-) + +diff --git a/xwayland/selection.c b/xwayland/selection.c +index 59702246..e0eb3ffc 100644 +--- a/xwayland/selection.c ++++ b/xwayland/selection.c +@@ -34,6 +34,12 @@ + #include "xwayland.h" + #include "shared/helpers.h" + ++#ifdef WM_DEBUG ++#define wm_log(...) weston_log(__VA_ARGS__) ++#else ++#define wm_log(...) do {} while (0) ++#endif ++ + static int + writable_callback(int fd, uint32_t mask, void *data) + { +@@ -102,6 +108,9 @@ weston_wm_get_incr_chunk(struct weston_wm *wm) + { + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; ++ FILE *fp; ++ char *logstr; ++ size_t logsize; + + cookie = xcb_get_property(wm->conn, + 0, /* delete */ +@@ -115,7 +124,13 @@ weston_wm_get_incr_chunk(struct weston_wm *wm) + if (reply == NULL) + return; + +- dump_property(wm, wm->atom.wl_selection, reply); ++ fp = open_memstream(&logstr, &logsize); ++ if (fp) { ++ dump_property(fp, wm, wm->atom.wl_selection, reply); ++ if (fclose(fp) == 0) ++ wm_log("%s", logstr); ++ free(logstr); ++ } + + if (xcb_get_property_value_length(reply) > 0) { + /* reply's ownership is transferred to wm, which is responsible +@@ -178,6 +193,9 @@ weston_wm_get_selection_targets(struct weston_wm *wm) + xcb_atom_t *value; + char **p; + uint32_t i; ++ FILE *fp; ++ char *logstr; ++ size_t logsize; + + cookie = xcb_get_property(wm->conn, + 1, /* delete */ +@@ -191,7 +209,13 @@ weston_wm_get_selection_targets(struct weston_wm *wm) + if (reply == NULL) + return; + +- dump_property(wm, wm->atom.wl_selection, reply); ++ fp = open_memstream(&logstr, &logsize); ++ if (fp) { ++ dump_property(fp, wm, wm->atom.wl_selection, reply); ++ if (fclose(fp) == 0) ++ wm_log("%s", logstr); ++ free(logstr); ++ } + + if (reply->type != XCB_ATOM_ATOM) { + free(reply); +@@ -232,6 +256,9 @@ weston_wm_get_selection_data(struct weston_wm *wm) + { + xcb_get_property_cookie_t cookie; + xcb_get_property_reply_t *reply; ++ FILE *fp; ++ char *logstr; ++ size_t logsize; + + cookie = xcb_get_property(wm->conn, + 1, /* delete */ +@@ -243,7 +270,13 @@ weston_wm_get_selection_data(struct weston_wm *wm) + + reply = xcb_get_property_reply(wm->conn, cookie, NULL); + +- dump_property(wm, wm->atom.wl_selection, reply); ++ fp = open_memstream(&logstr, &logsize); ++ if (fp) { ++ dump_property(fp, wm, wm->atom.wl_selection, reply); ++ if (fclose(fp) == 0) ++ wm_log("%s", logstr); ++ free(logstr); ++ } + + if (reply == NULL) { + return; +diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c +index 3bf323a4..4a26f6e7 100644 +--- a/xwayland/window-manager.c ++++ b/xwayland/window-manager.c +@@ -210,23 +210,6 @@ wm_log(const char *fmt, ...) + #endif + } + +-static int __attribute__ ((format (printf, 1, 2))) +-wm_log_continue(const char *fmt, ...) +-{ +-#ifdef WM_DEBUG +- int l; +- va_list argp; +- +- va_start(argp, fmt); +- l = weston_vlog_continue(fmt, argp); +- va_end(argp); +- +- return l; +-#else +- return 0; +-#endif +-} +- + static void + weston_output_weak_ref_init(struct weston_output_weak_ref *ref) + { +@@ -430,7 +413,7 @@ dump_cardinal_array(FILE *fp, xcb_get_property_reply_t *reply) + } + + void +-dump_property(struct weston_wm *wm, ++dump_property(FILE *fp, struct weston_wm *wm, + xcb_atom_t property, xcb_get_property_reply_t *reply) + { + int32_t *incr_value; +@@ -439,18 +422,11 @@ dump_property(struct weston_wm *wm, + xcb_window_t *window_value; + int width, len; + uint32_t i; +- FILE *fp; +- char *logstr; +- size_t logsize; +- +- fp = open_memstream(&logstr, &logsize); +- if (!fp) +- return; + + width = fprintf(fp, "%s: ", get_atom_name(wm->conn, property)); + if (reply == NULL) { + fprintf(fp, "(no reply)\n"); +- goto out; ++ return; + } + + width += fprintf(fp, "%s/%d, length %d (value_len %d): ", +@@ -492,15 +468,10 @@ dump_property(struct weston_wm *wm, + } else { + fprintf(fp, "huh?\n"); + } +- +-out: +- if (fclose(fp) == 0) +- wm_log_continue("%s", logstr); +- free(logstr); + } + + static void +-read_and_dump_property(struct weston_wm *wm, ++read_and_dump_property(FILE *fp, struct weston_wm *wm, + xcb_window_t window, xcb_atom_t property) + { + xcb_get_property_reply_t *reply; +@@ -510,7 +481,7 @@ read_and_dump_property(struct weston_wm *wm, + property, XCB_ATOM_ANY, 0, 2048); + reply = xcb_get_property_reply(wm->conn, cookie, NULL); + +- dump_property(wm, property, reply); ++ dump_property(fp, wm, property, reply); + + free(reply); + } +@@ -1389,19 +1360,35 @@ weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *even + xcb_property_notify_event_t *property_notify = + (xcb_property_notify_event_t *) event; + struct weston_wm_window *window; ++ FILE *fp; ++ char *logstr; ++ size_t logsize; + + if (!wm_lookup_window(wm, property_notify->window, &window)) + return; + + window->properties_dirty = 1; + +- wm_log("XCB_PROPERTY_NOTIFY: window %d, ", property_notify->window); +- if (property_notify->state == XCB_PROPERTY_DELETE) +- wm_log_continue("deleted %s\n", +- get_atom_name(wm->conn, property_notify->atom)); +- else +- read_and_dump_property(wm, property_notify->window, +- property_notify->atom); ++ fp = open_memstream(&logstr, &logsize); ++ if (fp) { ++ fprintf(fp, "XCB_PROPERTY_NOTIFY: window %d, ", property_notify->window); ++ if (property_notify->state == XCB_PROPERTY_DELETE) ++ fprintf(fp, "deleted %s\n", ++ get_atom_name(wm->conn, property_notify->atom)); ++ else ++ read_and_dump_property(fp, wm, property_notify->window, ++ property_notify->atom); ++ ++ if (fclose(fp) == 0) ++ wm_log("%s", logstr); ++ free(logstr); ++ } else { ++ /* read_and_dump_property() is a X11 roundtrip. ++ * Mimic it to maintain ordering semantics between debug ++ * and non-debug paths. ++ */ ++ get_atom_name(wm->conn, property_notify->atom); ++ } + + if (property_notify->atom == wm->atom.net_wm_name || + property_notify->atom == XCB_ATOM_WM_NAME) +diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h +index ca75f5b7..52da6786 100644 +--- a/xwayland/xwayland.h ++++ b/xwayland/xwayland.h +@@ -23,6 +23,7 @@ + * SOFTWARE. + */ + ++#include <stdio.h> + #include <wayland-server.h> + #include <xcb/xcb.h> + #include <xcb/xfixes.h> +@@ -159,7 +160,7 @@ struct weston_wm { + }; + + void +-dump_property(struct weston_wm *wm, xcb_atom_t property, ++dump_property(FILE *fp, struct weston_wm *wm, xcb_atom_t property, + xcb_get_property_reply_t *reply); + + const char * +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1012-xwm-convert-WM_DEBUG-into-a-weston-debug-scope.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1012-xwm-convert-WM_DEBUG-into-a-weston-debug-scope.patch new file mode 100644 index 00000000..cc171a58 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1012-xwm-convert-WM_DEBUG-into-a-weston-debug-scope.patch @@ -0,0 +1,423 @@ +From 9b72eb7930ef60aa44ab49c53b2aec9e7242cf1c Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen <pq@iki.fi> +Date: Thu, 12 Oct 2017 13:18:14 +0200 +Subject: [PATCH 12/46] xwm: convert WM_DEBUG into a weston-debug scope + +Instead of a compile time choice, offer the XWM debugging messages +through the weston-debug protocol and tool on demand. Users will not +need to recompile weston to get XWM debugging, and it won't flood the +weston log. + +The debug scope needs to be initialized in launcher.c for it be +available from start, before the first X11 client tries to connect and +initializes XWM. + +Signed-off-by: Pekka Paalanen <pq@iki.fi> + +pass the wm_debug scope to weston_debug_scope_printf API to append +the scopename to the timestr + +Signed-off-by: Maniraj Devadoss <Maniraj.Devadoss@in.bosch.com> +Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> +Reviewed-by: Daniel Stone <daniels@collabora.com> +--- + xwayland/launcher.c | 7 ++ + xwayland/window-manager.c | 166 +++++++++++++++++++++++++--------------------- + xwayland/xwayland.h | 3 + + 3 files changed, 99 insertions(+), 77 deletions(-) + +diff --git a/xwayland/launcher.c b/xwayland/launcher.c +index 0ecdb205..c5b99385 100644 +--- a/xwayland/launcher.c ++++ b/xwayland/launcher.c +@@ -229,6 +229,8 @@ weston_xserver_destroy(struct wl_listener *l, void *data) + if (wxs->loop) + weston_xserver_shutdown(wxs); + ++ weston_debug_scope_destroy(wxs->wm_debug); ++ + free(wxs); + } + +@@ -391,5 +393,10 @@ weston_module_init(struct weston_compositor *compositor) + wxs->destroy_listener.notify = weston_xserver_destroy; + wl_signal_add(&compositor->destroy_signal, &wxs->destroy_listener); + ++ wxs->wm_debug = weston_compositor_add_debug_scope(wxs->compositor, ++ "xwm-wm-x11", ++ "XWM's window management X11 events\n", ++ NULL, NULL); ++ + return 0; + } +diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c +index 4a26f6e7..ccdae57f 100644 +--- a/xwayland/window-manager.c ++++ b/xwayland/window-manager.c +@@ -193,23 +193,27 @@ static void + xserver_map_shell_surface(struct weston_wm_window *window, + struct weston_surface *surface); + +-static int __attribute__ ((format (printf, 1, 2))) +-wm_log(const char *fmt, ...) ++static bool ++wm_debug_is_enabled(struct weston_wm *wm) + { +-#ifdef WM_DEBUG +- int l; +- va_list argp; ++ return weston_debug_scope_is_enabled(wm->server->wm_debug); ++} + +- va_start(argp, fmt); +- l = weston_vlog(fmt, argp); +- va_end(argp); ++static void __attribute__ ((format (printf, 2, 3))) ++wm_printf(struct weston_wm *wm, const char *fmt, ...) ++{ ++ va_list ap; ++ char timestr[128]; + +- return l; +-#else +- return 0; +-#endif +-} ++ if (wm_debug_is_enabled(wm)) ++ weston_debug_scope_printf(wm->server->wm_debug, "%s ", ++ weston_debug_scope_timestamp(wm->server->wm_debug, ++ timestr, sizeof timestr)); + ++ va_start(ap, fmt); ++ weston_debug_scope_vprintf(wm->server->wm_debug, fmt, ap); ++ va_end(ap); ++} + static void + weston_output_weak_ref_init(struct weston_output_weak_ref *ref) + { +@@ -717,10 +721,10 @@ weston_wm_handle_configure_request(struct weston_wm *wm, xcb_generic_event_t *ev + uint32_t mask, values[16]; + int x, y, width, height, i = 0; + +- wm_log("XCB_CONFIGURE_REQUEST (window %d) %d,%d @ %dx%d\n", +- configure_request->window, +- configure_request->x, configure_request->y, +- configure_request->width, configure_request->height); ++ wm_printf(wm, "XCB_CONFIGURE_REQUEST (window %d) %d,%d @ %dx%d\n", ++ configure_request->window, ++ configure_request->x, configure_request->y, ++ configure_request->width, configure_request->height); + + if (!wm_lookup_window(wm, configure_request->window, &window)) + return; +@@ -786,11 +790,11 @@ weston_wm_handle_configure_notify(struct weston_wm *wm, xcb_generic_event_t *eve + wm->server->compositor->xwayland_interface; + struct weston_wm_window *window; + +- wm_log("XCB_CONFIGURE_NOTIFY (window %d) %d,%d @ %dx%d%s\n", +- configure_notify->window, +- configure_notify->x, configure_notify->y, +- configure_notify->width, configure_notify->height, +- configure_notify->override_redirect ? ", override" : ""); ++ wm_printf(wm, "XCB_CONFIGURE_NOTIFY (window %d) %d,%d @ %dx%d%s\n", ++ configure_notify->window, ++ configure_notify->x, configure_notify->y, ++ configure_notify->width, configure_notify->height, ++ configure_notify->override_redirect ? ", override" : ""); + + if (!wm_lookup_window(wm, configure_notify->window, &window)) + return; +@@ -839,7 +843,7 @@ weston_wm_create_surface(struct wl_listener *listener, void *data) + if (wl_resource_get_client(surface->resource) != wm->server->client) + return; + +- wm_log("XWM: create weston_surface %p\n", surface); ++ wm_printf(wm, "XWM: create weston_surface %p\n", surface); + + wl_list_for_each(window, &wm->unpaired_window_list, link) + if (window->surface_id == +@@ -1096,8 +1100,8 @@ weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event) + struct weston_output *output; + + if (our_resource(wm, map_request->window)) { +- wm_log("XCB_MAP_REQUEST (window %d, ours)\n", +- map_request->window); ++ wm_printf(wm, "XCB_MAP_REQUEST (window %d, ours)\n", ++ map_request->window); + return; + } + +@@ -1126,10 +1130,10 @@ weston_wm_handle_map_request(struct weston_wm *wm, xcb_generic_event_t *event) + weston_wm_window_create_frame(window); /* sets frame_id */ + assert(window->frame_id != XCB_WINDOW_NONE); + +- wm_log("XCB_MAP_REQUEST (window %d, %p, frame %d, %dx%d @ %d,%d)\n", +- window->id, window, window->frame_id, +- window->width, window->height, +- window->map_request_x, window->map_request_y); ++ wm_printf(wm, "XCB_MAP_REQUEST (window %d, %p, frame %d, %dx%d @ %d,%d)\n", ++ window->id, window, window->frame_id, ++ window->width, window->height, ++ window->map_request_x, window->map_request_y); + + weston_wm_window_set_allow_commits(window, false); + weston_wm_window_set_wm_state(window, ICCCM_NORMAL_STATE); +@@ -1157,13 +1161,13 @@ weston_wm_handle_map_notify(struct weston_wm *wm, xcb_generic_event_t *event) + xcb_map_notify_event_t *map_notify = (xcb_map_notify_event_t *) event; + + if (our_resource(wm, map_notify->window)) { +- wm_log("XCB_MAP_NOTIFY (window %d, ours)\n", +- map_notify->window); ++ wm_printf(wm, "XCB_MAP_NOTIFY (window %d, ours)\n", ++ map_notify->window); + return; + } + +- wm_log("XCB_MAP_NOTIFY (window %d%s)\n", map_notify->window, +- map_notify->override_redirect ? ", override" : ""); ++ wm_printf(wm, "XCB_MAP_NOTIFY (window %d%s)\n", map_notify->window, ++ map_notify->override_redirect ? ", override" : ""); + } + + static void +@@ -1173,10 +1177,10 @@ weston_wm_handle_unmap_notify(struct weston_wm *wm, xcb_generic_event_t *event) + (xcb_unmap_notify_event_t *) event; + struct weston_wm_window *window; + +- wm_log("XCB_UNMAP_NOTIFY (window %d, event %d%s)\n", +- unmap_notify->window, +- unmap_notify->event, +- our_resource(wm, unmap_notify->window) ? ", ours" : ""); ++ wm_printf(wm, "XCB_UNMAP_NOTIFY (window %d, event %d%s)\n", ++ unmap_notify->window, ++ unmap_notify->event, ++ our_resource(wm, unmap_notify->window) ? ", ours" : ""); + + if (our_resource(wm, unmap_notify->window)) + return; +@@ -1216,7 +1220,7 @@ weston_wm_window_draw_decoration(struct weston_wm_window *window) + cairo_t *cr; + int width, height; + +- wm_log("XWM: draw decoration, win %d\n", window->id); ++ wm_printf(window->wm, "XWM: draw decoration, win %d\n", window->id); + + weston_wm_window_get_frame_size(window, &width, &height); + +@@ -1279,8 +1283,8 @@ weston_wm_window_set_pending_state(struct weston_wm_window *window) + input_h = height; + } + +- wm_log("XWM: win %d geometry: %d,%d %dx%d\n", +- window->id, input_x, input_y, input_w, input_h); ++ wm_printf(window->wm, "XWM: win %d geometry: %d,%d %dx%d\n", ++ window->id, input_x, input_y, input_w, input_h); + + pixman_region32_fini(&window->surface->pending.input); + pixman_region32_init_rect(&window->surface->pending.input, +@@ -1347,7 +1351,7 @@ weston_wm_window_schedule_repaint(struct weston_wm_window *window) + if (window->repaint_source) + return; + +- wm_log("XWM: schedule repaint, win %d\n", window->id); ++ wm_printf(wm, "XWM: schedule repaint, win %d\n", window->id); + + window->repaint_source = + wl_event_loop_add_idle(wm->server->loop, +@@ -1360,18 +1364,24 @@ weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *even + xcb_property_notify_event_t *property_notify = + (xcb_property_notify_event_t *) event; + struct weston_wm_window *window; +- FILE *fp; ++ FILE *fp = NULL; + char *logstr; + size_t logsize; ++ char timestr[128]; + + if (!wm_lookup_window(wm, property_notify->window, &window)) + return; + + window->properties_dirty = 1; + +- fp = open_memstream(&logstr, &logsize); ++ if (wm_debug_is_enabled(wm)) ++ fp = open_memstream(&logstr, &logsize); ++ + if (fp) { +- fprintf(fp, "XCB_PROPERTY_NOTIFY: window %d, ", property_notify->window); ++ fprintf(fp, "%s XCB_PROPERTY_NOTIFY: window %d, ", ++ weston_debug_scope_timestamp(wm->server->wm_debug, ++ timestr, sizeof timestr), ++ property_notify->window); + if (property_notify->state == XCB_PROPERTY_DELETE) + fprintf(fp, "deleted %s\n", + get_atom_name(wm->conn, property_notify->atom)); +@@ -1380,7 +1390,8 @@ weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *even + property_notify->atom); + + if (fclose(fp) == 0) +- wm_log("%s", logstr); ++ weston_debug_scope_write(wm->server->wm_debug, ++ logstr, logsize); + free(logstr); + } else { + /* read_and_dump_property() is a X11 roundtrip. +@@ -1406,7 +1417,7 @@ weston_wm_window_create(struct weston_wm *wm, + + window = zalloc(sizeof *window); + if (window == NULL) { +- wm_log("failed to allocate window\n"); ++ wm_printf(wm, "failed to allocate window\n"); + return; + } + +@@ -1479,12 +1490,12 @@ weston_wm_handle_create_notify(struct weston_wm *wm, xcb_generic_event_t *event) + xcb_create_notify_event_t *create_notify = + (xcb_create_notify_event_t *) event; + +- wm_log("XCB_CREATE_NOTIFY (window %d, at (%d, %d), width %d, height %d%s%s)\n", +- create_notify->window, +- create_notify->x, create_notify->y, +- create_notify->width, create_notify->height, +- create_notify->override_redirect ? ", override" : "", +- our_resource(wm, create_notify->window) ? ", ours" : ""); ++ wm_printf(wm, "XCB_CREATE_NOTIFY (window %d, at (%d, %d), width %d, height %d%s%s)\n", ++ create_notify->window, ++ create_notify->x, create_notify->y, ++ create_notify->width, create_notify->height, ++ create_notify->override_redirect ? ", override" : "", ++ our_resource(wm, create_notify->window) ? ", ours" : ""); + + if (our_resource(wm, create_notify->window)) + return; +@@ -1502,10 +1513,10 @@ weston_wm_handle_destroy_notify(struct weston_wm *wm, xcb_generic_event_t *event + (xcb_destroy_notify_event_t *) event; + struct weston_wm_window *window; + +- wm_log("XCB_DESTROY_NOTIFY, win %d, event %d%s\n", +- destroy_notify->window, +- destroy_notify->event, +- our_resource(wm, destroy_notify->window) ? ", ours" : ""); ++ wm_printf(wm, "XCB_DESTROY_NOTIFY, win %d, event %d%s\n", ++ destroy_notify->window, ++ destroy_notify->event, ++ our_resource(wm, destroy_notify->window) ? ", ours" : ""); + + if (our_resource(wm, destroy_notify->window)) + return; +@@ -1523,11 +1534,11 @@ weston_wm_handle_reparent_notify(struct weston_wm *wm, xcb_generic_event_t *even + (xcb_reparent_notify_event_t *) event; + struct weston_wm_window *window; + +- wm_log("XCB_REPARENT_NOTIFY (window %d, parent %d, event %d%s)\n", +- reparent_notify->window, +- reparent_notify->parent, +- reparent_notify->event, +- reparent_notify->override_redirect ? ", override" : ""); ++ wm_printf(wm, "XCB_REPARENT_NOTIFY (window %d, parent %d, event %d%s)\n", ++ reparent_notify->window, ++ reparent_notify->parent, ++ reparent_notify->event, ++ reparent_notify->override_redirect ? ", override" : ""); + + if (reparent_notify->parent == wm->screen->root) { + weston_wm_window_create(wm, reparent_notify->window, 10, 10, +@@ -1734,7 +1745,7 @@ surface_destroy(struct wl_listener *listener, void *data) + container_of(listener, + struct weston_wm_window, surface_destroy_listener); + +- wm_log("surface for xid %d destroyed\n", window->id); ++ wm_printf(window->wm, "surface for xid %d destroyed\n", window->id); + + /* This should have been freed by the shell. + * Don't try to use it later. */ +@@ -1750,7 +1761,8 @@ weston_wm_window_handle_surface_id(struct weston_wm_window *window, + struct wl_resource *resource; + + if (window->surface_id != 0) { +- wm_log("already have surface id for window %d\n", window->id); ++ wm_printf(wm, "already have surface id for window %d\n", ++ window->id); + return; + } + +@@ -1782,14 +1794,14 @@ weston_wm_handle_client_message(struct weston_wm *wm, + (xcb_client_message_event_t *) event; + struct weston_wm_window *window; + +- wm_log("XCB_CLIENT_MESSAGE (%s %d %d %d %d %d win %d)\n", +- get_atom_name(wm->conn, client_message->type), +- client_message->data.data32[0], +- client_message->data.data32[1], +- client_message->data.data32[2], +- client_message->data.data32[3], +- client_message->data.data32[4], +- client_message->window); ++ wm_printf(wm, "XCB_CLIENT_MESSAGE (%s %d %d %d %d %d win %d)\n", ++ get_atom_name(wm->conn, client_message->type), ++ client_message->data.data32[0], ++ client_message->data.data32[1], ++ client_message->data.data32[2], ++ client_message->data.data32[3], ++ client_message->data.data32[4], ++ client_message->window); + + /* The window may get created and destroyed before we actually + * handle the message. If it doesn't exist, bail. +@@ -2007,9 +2019,9 @@ weston_wm_handle_button(struct weston_wm *wm, xcb_generic_event_t *event) + uint32_t button_id; + uint32_t double_click = 0; + +- wm_log("XCB_BUTTON_%s (detail %d)\n", +- button->response_type == XCB_BUTTON_PRESS ? +- "PRESS" : "RELEASE", button->detail); ++ wm_printf(wm, "XCB_BUTTON_%s (detail %d)\n", ++ button->response_type == XCB_BUTTON_PRESS ? ++ "PRESS" : "RELEASE", button->detail); + + if (!wm_lookup_window(wm, button->event, &window) || + !window->decorate) +@@ -2221,7 +2233,7 @@ weston_wm_handle_event(int fd, uint32_t mask, void *data) + weston_wm_handle_destroy_notify(wm, event); + break; + case XCB_MAPPING_NOTIFY: +- wm_log("XCB_MAPPING_NOTIFY\n"); ++ wm_printf(wm, "XCB_MAPPING_NOTIFY\n"); + break; + case XCB_PROPERTY_NOTIFY: + weston_wm_handle_property_notify(wm, event); +@@ -2837,8 +2849,8 @@ xserver_map_shell_surface(struct weston_wm_window *window, + window->surface, + &shell_client); + +- wm_log("XWM: map shell surface, win %d, weston_surface %p, xwayland surface %p\n", +- window->id, window->surface, window->shsurf); ++ wm_printf(wm, "XWM: map shell surface, win %d, weston_surface %p, xwayland surface %p\n", ++ window->id, window->surface, window->shsurf); + + if (window->name) + xwayland_interface->set_title(window->shsurf, window->name); +diff --git a/xwayland/xwayland.h b/xwayland/xwayland.h +index 52da6786..507d534d 100644 +--- a/xwayland/xwayland.h ++++ b/xwayland/xwayland.h +@@ -33,6 +33,7 @@ + #include "compositor.h" + #include "compositor/weston.h" + #include "xwayland-api.h" ++#include "weston-debug.h" + + #define SEND_EVENT_MASK (0x80) + #define EVENT_TYPE(event) ((event)->response_type & ~SEND_EVENT_MASK) +@@ -52,6 +53,8 @@ struct weston_xserver { + struct wl_listener destroy_listener; + weston_xwayland_spawn_xserver_func_t spawn_func; + void *user_data; ++ ++ struct weston_debug_scope *wm_debug; + }; + + struct weston_wm { +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1014-compositor-Add-weston_layer_mask_is_infinite.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1014-compositor-Add-weston_layer_mask_is_infinite.patch new file mode 100644 index 00000000..ee4ab191 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1014-compositor-Add-weston_layer_mask_is_infinite.patch @@ -0,0 +1,52 @@ +From 3b7756351d31a72da11ff09c56efa17960db1b20 Mon Sep 17 00:00:00 2001 +From: Daniel Stone <daniels@collabora.com> +Date: Fri, 20 Jul 2018 08:38:25 +0100 +Subject: [PATCH 14/46] compositor: Add weston_layer_mask_is_infinite + +As a counterpart to weston_layer_set_mask_infinite(), returning if the +mask is the same as what is set. + +Signed-off-by: Daniel Stone <daniels@collabora.com> +Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk> +--- + libweston/compositor.c | 9 +++++++++ + libweston/compositor.h | 3 +++ + 2 files changed, 12 insertions(+) + +diff --git a/libweston/compositor.c b/libweston/compositor.c +index 01616550..a38c4c1b 100644 +--- a/libweston/compositor.c ++++ b/libweston/compositor.c +@@ -2746,6 +2746,15 @@ weston_layer_set_mask_infinite(struct weston_layer *layer) + UINT32_MAX, UINT32_MAX); + } + ++WL_EXPORT bool ++weston_layer_mask_is_infinite(struct weston_layer *layer) ++{ ++ return layer->mask.x1 == INT32_MIN && ++ layer->mask.y1 == INT32_MIN && ++ layer->mask.x2 == INT32_MIN + UINT32_MAX && ++ layer->mask.y2 == INT32_MIN + UINT32_MAX; ++} ++ + WL_EXPORT void + weston_output_schedule_repaint(struct weston_output *output) + { +diff --git a/libweston/compositor.h b/libweston/compositor.h +index 33f02b18..069fb03d 100644 +--- a/libweston/compositor.h ++++ b/libweston/compositor.h +@@ -1685,6 +1685,9 @@ weston_layer_set_mask(struct weston_layer *layer, int x, int y, int width, int h + void + weston_layer_set_mask_infinite(struct weston_layer *layer); + ++bool ++weston_layer_mask_is_infinite(struct weston_layer *layer); ++ + void + weston_plane_init(struct weston_plane *plane, + struct weston_compositor *ec, +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1015-compositor-Add-scene-graph-debug-scope.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1015-compositor-Add-scene-graph-debug-scope.patch new file mode 100644 index 00000000..13ba4c81 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1015-compositor-Add-scene-graph-debug-scope.patch @@ -0,0 +1,297 @@ +From ce62cb3d05505777893ccdfacbf2a013c82e4ce2 Mon Sep 17 00:00:00 2001 +From: Daniel Stone <daniels@collabora.com> +Date: Fri, 20 Jul 2018 09:46:24 +0100 +Subject: [PATCH 15/46] compositor: Add scene-graph debug scope + +Add a 'scene-graph' debug scope which will dump out the current set of +outputs, layers, and views and as much information as possible about how +they are rendered and composited. + +Signed-off-by: Daniel Stone <daniels@collabora.com> +--- + libweston/compositor.c | 225 +++++++++++++++++++++++++++++++++++++++++++++++++ + libweston/compositor.h | 4 + + 2 files changed, 229 insertions(+) + +diff --git a/libweston/compositor.c b/libweston/compositor.c +index a38c4c1b..2ca3da3b 100644 +--- a/libweston/compositor.c ++++ b/libweston/compositor.c +@@ -55,6 +55,8 @@ + #include "timeline.h" + + #include "compositor.h" ++#include "weston-debug.h" ++#include "linux-dmabuf.h" + #include "viewporter-server-protocol.h" + #include "presentation-time-server-protocol.h" + #include "shared/helpers.h" +@@ -6306,6 +6308,221 @@ timeline_key_binding_handler(struct weston_keyboard *keyboard, + weston_timeline_open(compositor); + } + ++static const char * ++output_repaint_status_text(struct weston_output *output) ++{ ++ switch (output->repaint_status) { ++ case REPAINT_NOT_SCHEDULED: ++ return "no repaint"; ++ case REPAINT_BEGIN_FROM_IDLE: ++ return "start_repaint_loop scheduled"; ++ case REPAINT_SCHEDULED: ++ return "repaint scheduled"; ++ case REPAINT_AWAITING_COMPLETION: ++ return "awaiting completion"; ++ } ++ ++ assert(!"output_repaint_status_text missing enum"); ++ return NULL; ++} ++ ++static void ++debug_scene_view_print_buffer(FILE *fp, struct weston_view *view) ++{ ++ struct weston_buffer *buffer = view->surface->buffer_ref.buffer; ++ struct wl_shm_buffer *shm; ++ struct linux_dmabuf_buffer *dmabuf; ++ ++ if (!buffer) { ++ fprintf(fp, "\t\t[buffer not available]\n"); ++ return; ++ } ++ ++ shm = wl_shm_buffer_get(buffer->resource); ++ if (shm) { ++ fprintf(fp, "\t\tSHM buffer\n"); ++ fprintf(fp, "\t\t\tformat: 0x%lx\n", ++ (unsigned long) wl_shm_buffer_get_format(shm)); ++ return; ++ } ++ ++ dmabuf = linux_dmabuf_buffer_get(buffer->resource); ++ if (dmabuf) { ++ fprintf(fp, "\t\tdmabuf buffer\n"); ++ fprintf(fp, "\t\t\tformat: 0x%lx\n", ++ (unsigned long) dmabuf->attributes.format); ++ fprintf(fp, "\t\t\tmodifier: 0x%llx\n", ++ (unsigned long long) dmabuf->attributes.modifier[0]); ++ return; ++ } ++ ++ fprintf(fp, "\t\tEGL buffer"); ++} ++ ++static void ++debug_scene_view_print(FILE *fp, struct weston_view *view, int view_idx) ++{ ++ struct weston_compositor *ec = view->surface->compositor; ++ struct weston_output *output; ++ char desc[512]; ++ pixman_box32_t *box; ++ uint32_t surface_id = 0; ++ pid_t pid = 0; ++ ++ if (view->surface->resource) { ++ struct wl_resource *resource = view->surface->resource; ++ wl_client_get_credentials(wl_resource_get_client(resource), ++ &pid, NULL, NULL); ++ surface_id = wl_resource_get_id(view->surface->resource); ++ } ++ ++ if (!view->surface->get_label || ++ view->surface->get_label(view->surface, desc, sizeof(desc)) < 0) { ++ strcpy(desc, "[no description available]"); ++ } ++ fprintf(fp, "\tView %d (role %s, PID %d, surface ID %u, %s, %p):\n", ++ view_idx, view->surface->role_name, pid, surface_id, ++ desc, view); ++ ++ box = pixman_region32_extents(&view->transform.boundingbox); ++ fprintf(fp, "\t\tposition: (%d, %d) -> (%d, %d)\n", ++ box->x1, box->y1, box->x2, box->y2); ++ box = pixman_region32_extents(&view->transform.opaque); ++ ++ if (pixman_region32_equal(&view->transform.opaque, ++ &view->transform.boundingbox)) { ++ fprintf(fp, "\t\t[fully opaque]\n"); ++ } else if (!pixman_region32_not_empty(&view->transform.opaque)) { ++ fprintf(fp, "\t\t[not opaque]\n"); ++ } else { ++ fprintf(fp, "\t\t[opaque: (%d, %d) -> (%d, %d)]\n", ++ box->x1, box->y1, box->x2, box->y2); ++ } ++ ++ if (view->alpha < 1.0) ++ fprintf(fp, "\t\talpha: %f\n", view->alpha); ++ ++ if (view->output_mask != 0) { ++ bool first_output = true; ++ fprintf(fp, "\t\toutputs: "); ++ wl_list_for_each(output, &ec->output_list, link) { ++ if (!(view->output_mask & (1 << output->id))) ++ continue; ++ fprintf(fp, "%s%d (%s)%s", ++ (first_output) ? "" : ", ", ++ output->id, output->name, ++ (view->output == output) ? " (primary)" : ""); ++ first_output = false; ++ } ++ } else { ++ fprintf(fp, "\t\t[no outputs]"); ++ } ++ ++ fprintf(fp, "\n"); ++ ++ debug_scene_view_print_buffer(fp, view); ++} ++ ++/** ++ * Output information on how libweston is currently composing the scene ++ * graph. ++ */ ++WL_EXPORT char * ++weston_compositor_print_scene_graph(struct weston_compositor *ec) ++{ ++ struct weston_output *output; ++ struct weston_layer *layer; ++ struct timespec now; ++ int layer_idx = 0; ++ FILE *fp; ++ char *ret; ++ size_t len; ++ int err; ++ ++ fp = open_memstream(&ret, &len); ++ assert(fp); ++ ++ weston_compositor_read_presentation_clock(ec, &now); ++ fprintf(fp, "Weston scene graph at %ld.%09ld:\n\n", ++ now.tv_sec, now.tv_nsec); ++ ++ wl_list_for_each(output, &ec->output_list, link) { ++ struct weston_head *head; ++ int head_idx = 0; ++ ++ fprintf(fp, "Output %d (%s):\n", output->id, output->name); ++ assert(output->enabled); ++ ++ fprintf(fp, "\tposition: (%d, %d) -> (%d, %d)\n", ++ output->x, output->y, ++ output->x + output->width, ++ output->y + output->height); ++ fprintf(fp, "\tmode: %dx%d@%.3fHz\n", ++ output->current_mode->width, ++ output->current_mode->height, ++ output->current_mode->refresh / 1000.0); ++ fprintf(fp, "\tscale: %d\n", output->scale); ++ ++ fprintf(fp, "\trepaint status: %s\n", ++ output_repaint_status_text(output)); ++ if (output->repaint_status == REPAINT_SCHEDULED) ++ fprintf(fp, "\tnext repaint: %ld.%09ld\n", ++ output->next_repaint.tv_sec, ++ output->next_repaint.tv_nsec); ++ ++ wl_list_for_each(head, &output->head_list, output_link) { ++ fprintf(fp, "\tHead %d (%s): %sconnected\n", ++ head_idx++, head->name, ++ (head->connected) ? "" : "not "); ++ } ++ } ++ ++ fprintf(fp, "\n"); ++ ++ wl_list_for_each(layer, &ec->layer_list, link) { ++ struct weston_view *view; ++ int view_idx = 0; ++ ++ fprintf(fp, "Layer %d (pos 0x%lx):\n", layer_idx++, ++ (unsigned long) layer->position); ++ ++ if (!weston_layer_mask_is_infinite(layer)) { ++ fprintf(fp, "\t[mask: (%d, %d) -> (%d,%d)]\n\n", ++ layer->mask.x1, layer->mask.y1, ++ layer->mask.x2, layer->mask.y2); ++ } ++ ++ wl_list_for_each(view, &layer->view_list.link, layer_link.link) ++ debug_scene_view_print(fp, view, view_idx++); ++ ++ if (wl_list_empty(&layer->view_list.link)) ++ fprintf(fp, "\t[no views]\n"); ++ ++ fprintf(fp, "\n"); ++ } ++ ++ err = fclose(fp); ++ assert(err == 0); ++ ++ return ret; ++} ++ ++/** ++ * Called when the 'scene-graph' debug scope is bound by a client. This ++ * one-shot weston-debug scope prints the current scene graph when bound, ++ * and then terminates the stream. ++ */ ++static void ++debug_scene_graph_cb(struct weston_debug_stream *stream, void *data) ++{ ++ struct weston_compositor *ec = data; ++ char *str = weston_compositor_print_scene_graph(ec); ++ ++ weston_debug_stream_printf(stream, "%s", str); ++ free(str); ++ weston_debug_stream_complete(stream); ++} ++ + /** Create the compositor. + * + * This functions creates and initializes a compositor instance. +@@ -6415,6 +6632,12 @@ weston_compositor_create(struct wl_display *display, void *user_data) + weston_compositor_add_debug_binding(ec, KEY_T, + timeline_key_binding_handler, ec); + ++ ec->debug_scene = ++ weston_compositor_add_debug_scope(ec, "scene-graph", ++ "Scene graph details\n", ++ debug_scene_graph_cb, ++ ec); ++ + return ec; + + fail: +@@ -6714,6 +6937,8 @@ weston_compositor_destroy(struct weston_compositor *compositor) + if (compositor->heads_changed_source) + wl_event_source_remove(compositor->heads_changed_source); + ++ weston_debug_scope_destroy(compositor->debug_scene); ++ compositor->debug_scene = NULL; + weston_debug_compositor_destroy(compositor); + + free(compositor); +diff --git a/libweston/compositor.h b/libweston/compositor.h +index 069fb03d..49013e14 100644 +--- a/libweston/compositor.h ++++ b/libweston/compositor.h +@@ -1163,6 +1163,7 @@ struct weston_compositor { + struct weston_touch_calibrator *touch_calibrator; + + struct weston_debug_compositor *weston_debug; ++ struct weston_debug_scope *debug_scene; + }; + + struct weston_buffer { +@@ -1933,6 +1934,9 @@ weston_buffer_reference(struct weston_buffer_reference *ref, + void + weston_compositor_get_time(struct timespec *time); + ++char * ++weston_compositor_print_scene_graph(struct weston_compositor *ec); ++ + void + weston_compositor_destroy(struct weston_compositor *ec); + struct weston_compositor * +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1017-compositor-drm-Add-backend-pointer-to-drm_output.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1017-compositor-drm-Add-backend-pointer-to-drm_output.patch new file mode 100644 index 00000000..2dff3bd3 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1017-compositor-drm-Add-backend-pointer-to-drm_output.patch @@ -0,0 +1,37 @@ +From 64dbbee7f6570949edc8bca30e6cd026a9e70a59 Mon Sep 17 00:00:00 2001 +From: Daniel Stone <daniels@collabora.com> +Date: Fri, 20 Jul 2018 19:00:06 +0100 +Subject: [PATCH 17/46] compositor-drm: Add backend pointer to drm_output + +Add this for convenience, so it's easier to access when we add the DRM +backend debug scope. + +Signed-off-by: Daniel Stone <daniels@collabora.com> +--- + libweston/compositor-drm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c +index 94d78752..612e6a8f 100644 +--- a/libweston/compositor-drm.c ++++ b/libweston/compositor-drm.c +@@ -463,6 +463,7 @@ struct drm_head { + + struct drm_output { + struct weston_output base; ++ struct drm_backend *backend; + + uint32_t crtc_id; /* object ID to pass to DRM functions */ + int pipe; /* index of CRTC in resource array / bitmasks */ +@@ -6104,6 +6105,8 @@ drm_output_create(struct weston_compositor *compositor, const char *name) + if (output == NULL) + return NULL; + ++ output->backend = b; ++ + weston_output_init(&output->base, compositor, name); + + output->base.enable = drm_output_enable; +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1018-compositor-drm-Add-drm-backend-log-debug-scope.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1018-compositor-drm-Add-drm-backend-log-debug-scope.patch new file mode 100644 index 00000000..932859ca --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1018-compositor-drm-Add-drm-backend-log-debug-scope.patch @@ -0,0 +1,632 @@ +From 1cbe1f952de2b22539e163c0055fa3dcbb2e2d54 Mon Sep 17 00:00:00 2001 +From: Daniel Stone <daniels@collabora.com> +Date: Fri, 20 Jul 2018 10:21:28 +0100 +Subject: [PATCH 18/46] compositor-drm: Add drm-backend log debug scope + +Add a 'drm-debug' scope which prints verbose information about the DRM +backend's repaint cycle, including the decision tree on how views are +assigned (or not) to planes. + +Signed-off-by: Daniel Stone <daniels@collabora.com> +--- + libweston/compositor-drm.c | 285 ++++++++++++++++++++++++++++++++++++++++----- + 1 file changed, 258 insertions(+), 27 deletions(-) + +diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c +index 612e6a8f..b21793e5 100644 +--- a/libweston/compositor-drm.c ++++ b/libweston/compositor-drm.c +@@ -51,6 +51,7 @@ + + #include "compositor.h" + #include "compositor-drm.h" ++#include "weston-debug.h" + #include "shared/helpers.h" + #include "shared/timespec-util.h" + #include "gl-renderer.h" +@@ -73,6 +74,42 @@ + #define GBM_BO_USE_CURSOR GBM_BO_USE_CURSOR_64X64 + #endif + ++/** ++ * A small wrapper to print information into the 'drm-backend' debug scope. ++ * ++ * The following conventions are used to print variables: ++ * ++ * - fixed uint32_t values, including Weston object IDs such as weston_output ++ * IDs, DRM object IDs such as CRTCs or properties, and GBM/DRM formats: ++ * "%lu (0x%lx)" (unsigned long) value, (unsigned long) value ++ * ++ * - fixed uint64_t values, such as DRM property values (including object IDs ++ * when used as a value): ++ * "%llu (0x%llx)" (unsigned long long) value, (unsigned long long) value ++ * ++ * - non-fixed-width signed int: ++ * "%d" value ++ * ++ * - non-fixed-width unsigned int: ++ * "%u (0x%x)" value, value ++ * ++ * - non-fixed-width unsigned long: ++ * "%lu (0x%lx)" value, value ++ * ++ * Either the integer or hexadecimal forms may be omitted if it is known that ++ * one representation is not useful (e.g. width/height in hex are rarely what ++ * you want). ++ * ++ * This is to avoid implicit widening or narrowing when we use fixed-size ++ * types: uint32_t can be resolved by either unsigned int or unsigned long ++ * on a 32-bit system but only unsigned int on a 64-bit system, with uint64_t ++ * being unsigned long long on a 32-bit system and unsigned long on a 64-bit ++ * system. To avoid confusing side effects, we explicitly cast to the widest ++ * possible type and use a matching format specifier. ++ */ ++#define drm_debug(b, ...) \ ++ weston_debug_scope_printf((b)->debug, __VA_ARGS__) ++ + #define MAX_CLONED_CONNECTORS 4 + + /** +@@ -302,6 +339,8 @@ struct drm_backend { + bool shutting_down; + + bool aspect_ratio_supported; ++ ++ struct weston_debug_scope *debug; + }; + + struct drm_mode { +@@ -2357,6 +2396,10 @@ crtc_add_prop(drmModeAtomicReq *req, struct drm_output *output, + + ret = drmModeAtomicAddProperty(req, output->crtc_id, info->prop_id, + val); ++ drm_debug(output->backend, "\t\t\t[CRTC:%lu] %lu (%s) -> %llu (0x%llx)\n", ++ (unsigned long) output->crtc_id, ++ (unsigned long) info->prop_id, info->name, ++ (unsigned long long) val, (unsigned long long) val); + return (ret <= 0) ? -1 : 0; + } + +@@ -2372,6 +2415,10 @@ connector_add_prop(drmModeAtomicReq *req, struct drm_head *head, + + ret = drmModeAtomicAddProperty(req, head->connector_id, + info->prop_id, val); ++ drm_debug(head->backend, "\t\t\t[CONN:%lu] %lu (%s) -> %llu (0x%llx)\n", ++ (unsigned long) head->connector_id, ++ (unsigned long) info->prop_id, info->name, ++ (unsigned long long) val, (unsigned long long) val); + return (ret <= 0) ? -1 : 0; + } + +@@ -2387,6 +2434,10 @@ plane_add_prop(drmModeAtomicReq *req, struct drm_plane *plane, + + ret = drmModeAtomicAddProperty(req, plane->plane_id, info->prop_id, + val); ++ drm_debug(plane->backend, "\t\t\t[PLANE:%lu] %lu (%s) -> %llu (0x%llx)\n", ++ (unsigned long) plane->plane_id, ++ (unsigned long) info->prop_id, info->name, ++ (unsigned long long) val, (unsigned long long) val); + return (ret <= 0) ? -1 : 0; + } + +@@ -2405,6 +2456,9 @@ drm_mode_ensure_blob(struct drm_backend *backend, struct drm_mode *mode) + if (ret != 0) + weston_log("failed to create mode property blob: %m\n"); + ++ drm_debug(backend, "\t\t\t[atomic] created new mode blob %lu for %s", ++ (unsigned long) mode->blob_id, mode->mode_info.name); ++ + return ret; + } + +@@ -2414,17 +2468,23 @@ drm_output_apply_state_atomic(struct drm_output_state *state, + uint32_t *flags) + { + struct drm_output *output = state->output; +- struct drm_backend *backend = to_drm_backend(output->base.compositor); ++ struct drm_backend *b = to_drm_backend(output->base.compositor); + struct drm_plane_state *plane_state; + struct drm_mode *current_mode = to_drm_mode(output->base.current_mode); + struct drm_head *head; + int ret = 0; + +- if (state->dpms != output->state_cur->dpms) ++ drm_debug(b, "\t\t[atomic] %s output %lu (%s) state\n", ++ (*flags & DRM_MODE_ATOMIC_TEST_ONLY) ? "testing" : "applying", ++ (unsigned long) output->base.id, output->base.name); ++ ++ if (state->dpms != output->state_cur->dpms) { ++ drm_debug(b, "\t\t\t[atomic] DPMS state differs, modeset OK\n"); + *flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; ++ } + + if (state->dpms == WESTON_DPMS_ON) { +- ret = drm_mode_ensure_blob(backend, current_mode); ++ ret = drm_mode_ensure_blob(b, current_mode); + if (ret != 0) + return ret; + +@@ -2522,6 +2582,9 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state, + uint32_t *unused; + int err; + ++ drm_debug(b, "\t\t[atomic] previous state invalid; " ++ "starting with fresh state\n"); ++ + /* If we need to reset all our state (e.g. because we've + * just started, or just been VT-switched in), explicitly + * disable all the CRTCs and connectors we aren't using. */ +@@ -2534,9 +2597,16 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state, + + head = to_drm_head(head_base); + ++ drm_debug(b, "\t\t[atomic] disabling inactive head %s\n", ++ head_base->name); ++ + info = &head->props_conn[WDRM_CONNECTOR_CRTC_ID]; + err = drmModeAtomicAddProperty(req, head->connector_id, + info->prop_id, 0); ++ drm_debug(b, "\t\t\t[CONN:%lu] %lu (%s) -> 0\n", ++ (unsigned long) head->connector_id, ++ (unsigned long) info->prop_id, ++ info->name); + if (err <= 0) + ret = -1; + } +@@ -2573,12 +2643,21 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state, + continue; + } + ++ drm_debug(b, "\t\t[atomic] disabling unused CRTC %lu\n", ++ (unsigned long) *unused); ++ ++ drm_debug(b, "\t\t\t[CRTC:%lu] %lu (%s) -> 0\n", ++ (unsigned long) *unused, ++ (unsigned long) info->prop_id, info->name); + err = drmModeAtomicAddProperty(req, *unused, + info->prop_id, 0); + if (err <= 0) + ret = -1; + + info = &infos[WDRM_CRTC_MODE_ID]; ++ drm_debug(b, "\t\t\t[CRTC:%lu] %lu (%s) -> 0\n", ++ (unsigned long) *unused, ++ (unsigned long) info->prop_id, info->name); + err = drmModeAtomicAddProperty(req, *unused, + info->prop_id, 0); + if (err <= 0) +@@ -2590,6 +2669,8 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state, + /* Disable all the planes; planes which are being used will + * override this state in the output-state application. */ + wl_list_for_each(plane, &b->plane_list, link) { ++ drm_debug(b, "\t\t[atomic] starting with plane %lu disabled\n", ++ (unsigned long) plane->plane_id); + plane_add_prop(req, plane, WDRM_PLANE_CRTC_ID, 0); + plane_add_prop(req, plane, WDRM_PLANE_FB_ID, 0); + } +@@ -2972,6 +3053,14 @@ drm_repaint_begin(struct weston_compositor *compositor) + ret = drm_pending_state_alloc(b); + b->repaint_data = ret; + ++ if (weston_debug_scope_is_enabled(b->debug)) { ++ char *dbg = weston_compositor_print_scene_graph(compositor); ++ drm_debug(b, "[repaint] Beginning repaint; pending_state %p\n", ++ ret); ++ drm_debug(b, "%s", dbg); ++ free(dbg); ++ } ++ + return ret; + } + +@@ -2991,6 +3080,7 @@ drm_repaint_flush(struct weston_compositor *compositor, void *repaint_data) + struct drm_pending_state *pending_state = repaint_data; + + drm_pending_state_apply(pending_state); ++ drm_debug(b, "[repaint] flushed pending_state %p\n", pending_state); + b->repaint_data = NULL; + } + +@@ -3007,6 +3097,7 @@ drm_repaint_cancel(struct weston_compositor *compositor, void *repaint_data) + struct drm_pending_state *pending_state = repaint_data; + + drm_pending_state_free(pending_state); ++ drm_debug(b, "[repaint] cancel pending_state %p\n", pending_state); + b->repaint_data = NULL; + } + +@@ -3050,12 +3141,21 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, + struct drm_fb *fb; + unsigned int i; + int ret; ++ enum { ++ NO_PLANES, ++ NO_PLANES_WITH_FORMAT, ++ NO_PLANES_ACCEPTED, ++ PLACED_ON_PLANE, ++ } availability = NO_PLANES; + + assert(!b->sprites_are_broken); + + fb = drm_fb_get_from_view(output_state, ev); +- if (!fb) ++ if (!fb) { ++ drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " ++ " couldn't get fb\n", ev); + return NULL; ++ } + + wl_list_for_each(p, &b->plane_list, link) { + if (p->type != WDRM_PLANE_TYPE_OVERLAY) +@@ -3064,6 +3164,15 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, + if (!drm_plane_is_available(p, output)) + continue; + ++ state = drm_output_state_get_plane(output_state, p); ++ if (state->fb) { ++ state = NULL; ++ continue; ++ } ++ ++ if (availability == NO_PLANES) ++ availability = NO_PLANES_WITH_FORMAT; ++ + /* Check whether the format is supported */ + for (i = 0; i < p->count_formats; i++) { + unsigned int j; +@@ -3084,15 +3193,14 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, + if (i == p->count_formats) + continue; + +- state = drm_output_state_get_plane(output_state, p); +- if (state->fb) { +- state = NULL; +- continue; +- } ++ if (availability == NO_PLANES_WITH_FORMAT) ++ availability = NO_PLANES_ACCEPTED; + + state->ev = ev; + state->output = output; + if (!drm_plane_state_coords_for_view(state, ev)) { ++ drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " ++ "unsuitable transform\n", ev); + drm_plane_state_put_back(state); + state = NULL; + continue; +@@ -3100,6 +3208,8 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, + if (!b->atomic_modeset && + (state->src_w != state->dest_w << 16 || + state->src_h != state->dest_h << 16)) { ++ drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " ++ "no scaling without atomic\n", ev); + drm_plane_state_put_back(state); + state = NULL; + continue; +@@ -3113,17 +3223,48 @@ drm_output_prepare_overlay_view(struct drm_output_state *output_state, + + /* In planes-only mode, we don't have an incremental state to + * test against, so we just hope it'll work. */ +- if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) ++ if (mode == DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY) { ++ drm_debug(b, "\t\t\t\t[overlay] provisionally placing " ++ "view %p on overlay %lu in planes-only mode\n", ++ ev, (unsigned long) p->plane_id); ++ availability = PLACED_ON_PLANE; + goto out; ++ } + + ret = drm_pending_state_test(output_state->pending_state); +- if (ret == 0) ++ if (ret == 0) { ++ drm_debug(b, "\t\t\t\t[overlay] provisionally placing " ++ "view %p on overlay %d in mixed mode\n", ++ ev, p->plane_id); ++ availability = PLACED_ON_PLANE; + goto out; ++ } ++ ++ drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay %lu " ++ "in mixed mode: kernel test failed\n", ++ ev, (unsigned long) p->plane_id); + + drm_plane_state_put_back(state); + state = NULL; + } + ++ switch (availability) { ++ case NO_PLANES: ++ drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " ++ "no free overlay planes\n", ev); ++ break; ++ case NO_PLANES_WITH_FORMAT: ++ drm_debug(b, "\t\t\t\t[overlay] not placing view %p on overlay: " ++ "no free overlay planes matching format 0x%lx, " ++ "modifier 0x%llx\n", ++ ev, (unsigned long) fb->format, ++ (unsigned long long) fb->modifier); ++ break; ++ case NO_PLANES_ACCEPTED: ++ case PLACED_ON_PLANE: ++ break; ++ } ++ + out: + drm_fb_unref(fb); + return state; +@@ -3192,13 +3333,23 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, + if (b->gbm == NULL) + return NULL; + +- if (ev->surface->buffer_ref.buffer == NULL) ++ if (ev->surface->buffer_ref.buffer == NULL) { ++ drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane " ++ "(no buffer available)\n", ev); + return NULL; ++ } + shmbuf = wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource); +- if (!shmbuf) ++ if (!shmbuf) { ++ drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane " ++ "(buffer isn't SHM)\n", ev); + return NULL; +- if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB8888) ++ } ++ if (wl_shm_buffer_get_format(shmbuf) != WL_SHM_FORMAT_ARGB8888) { ++ drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane " ++ "(format 0x%lx unsuitable)\n", ++ ev, (unsigned long) wl_shm_buffer_get_format(shmbuf)); + return NULL; ++ } + + plane_state = + drm_output_state_get_plane(output_state, output->cursor_plane); +@@ -3216,8 +3367,11 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, + plane_state->src_w > (unsigned) b->cursor_width << 16 || + plane_state->src_h > (unsigned) b->cursor_height << 16 || + plane_state->src_w != plane_state->dest_w << 16 || +- plane_state->src_h != plane_state->dest_h << 16) ++ plane_state->src_h != plane_state->dest_h << 16) { ++ drm_debug(b, "\t\t\t\t[cursor] not assigning view %p to cursor plane " ++ "(positioning requires cropping or scaling)\n", ev); + goto err; ++ } + + /* Since we're setting plane state up front, we need to work out + * whether or not we need to upload a new cursor. We can't use the +@@ -3240,8 +3394,10 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, + plane_state->fb = + drm_fb_ref(output->gbm_cursor_fb[output->current_cursor]); + +- if (needs_update) ++ if (needs_update) { ++ drm_debug(b, "\t\t\t\t[cursor] copying new content to cursor BO\n"); + cursor_bo_update(plane_state, ev); ++ } + + /* The cursor API is somewhat special: in cursor_bo_update(), we upload + * a buffer which is always cursor_width x cursor_height, even if the +@@ -3252,6 +3408,9 @@ drm_output_prepare_cursor_view(struct drm_output_state *output_state, + plane_state->dest_w = b->cursor_width; + plane_state->dest_h = b->cursor_height; + ++ drm_debug(b, "\t\t\t\t[cursor] provisionally assigned view %p to cursor\n", ++ ev); ++ + return plane_state; + + err: +@@ -3347,18 +3506,32 @@ drm_output_propose_state(struct weston_output *output_base, + if (!scanout_fb || + (scanout_fb->type != BUFFER_GBM_SURFACE && + scanout_fb->type != BUFFER_PIXMAN_DUMB)) { ++ drm_debug(b, "\t\t[state] cannot propose mixed mode: " ++ "for output %s (%lu): no previous renderer " ++ "fb\n", ++ output->base.name, ++ (unsigned long) output->base.id); + drm_output_state_free(state); + return NULL; + } + + if (scanout_fb->width != output_base->current_mode->width || + scanout_fb->height != output_base->current_mode->height) { ++ drm_debug(b, "\t\t[state] cannot propose mixed mode " ++ "for output %s (%lu): previous fb has " ++ "different size\n", ++ output->base.name, ++ (unsigned long) output->base.id); + drm_output_state_free(state); + return NULL; + } + + scanout_state = drm_plane_state_duplicate(state, + plane->state_cur); ++ drm_debug(b, "\t\t[state] using renderer FB ID %lu for mixed " ++ "mode for output %s (%lu)\n", ++ (unsigned long) scanout_fb->fb_id, output->base.name, ++ (unsigned long) output->base.id); + } + + /* +@@ -3384,18 +3557,32 @@ drm_output_propose_state(struct weston_output *output_base, + bool totally_occluded = false; + bool overlay_occluded = false; + ++ drm_debug(b, "\t\t\t[view] evaluating view %p for " ++ "output %s (%lu)\n", ++ ev, output->base.name, ++ (unsigned long) output->base.id); ++ + /* If this view doesn't touch our output at all, there's no + * reason to do anything with it. */ +- if (!(ev->output_mask & (1u << output->base.id))) ++ if (!(ev->output_mask & (1u << output->base.id))) { ++ drm_debug(b, "\t\t\t\t[view] ignoring view %p " ++ "(not on our output)\n", ev); + continue; ++ } + + /* We only assign planes to views which are exclusively present + * on our output. */ +- if (ev->output_mask != (1u << output->base.id)) ++ if (ev->output_mask != (1u << output->base.id)) { ++ drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " ++ "(on multiple outputs)\n", ev); + force_renderer = true; ++ } + +- if (!ev->surface->buffer_ref.buffer) ++ if (!ev->surface->buffer_ref.buffer) { ++ drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " ++ "(no buffer available)\n", ev); + force_renderer = true; ++ } + + /* Ignore views we know to be totally occluded. */ + pixman_region32_init(&clipped_view); +@@ -3408,6 +3595,8 @@ drm_output_propose_state(struct weston_output *output_base, + &occluded_region); + totally_occluded = !pixman_region32_not_empty(&surface_overlap); + if (totally_occluded) { ++ drm_debug(b, "\t\t\t\t[view] ignoring view %p " ++ "(occluded on our output)\n", ev); + pixman_region32_fini(&surface_overlap); + pixman_region32_fini(&clipped_view); + continue; +@@ -3418,8 +3607,11 @@ drm_output_propose_state(struct weston_output *output_base, + * be part of, or occluded by, it, and cannot go on a plane. */ + pixman_region32_intersect(&surface_overlap, &renderer_region, + &clipped_view); +- if (pixman_region32_not_empty(&surface_overlap)) ++ if (pixman_region32_not_empty(&surface_overlap)) { ++ drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " ++ "(occluded by renderer views)\n", ev); + force_renderer = true; ++ } + + /* We do not control the stacking order of overlay planes; + * the scanout plane is strictly stacked bottom and the cursor +@@ -3428,8 +3620,11 @@ drm_output_propose_state(struct weston_output *output_base, + * planes overlapping each other. */ + pixman_region32_intersect(&surface_overlap, &occluded_region, + &clipped_view); +- if (pixman_region32_not_empty(&surface_overlap)) ++ if (pixman_region32_not_empty(&surface_overlap)) { ++ drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " ++ "(occluded by other overlay planes)\n", ev); + overlay_occluded = true; ++ } + pixman_region32_fini(&surface_overlap); + + /* The cursor plane is 'special' in the sense that we can still +@@ -3441,10 +3636,16 @@ drm_output_propose_state(struct weston_output *output_base, + /* If sprites are disabled or the view is not fully opaque, we + * must put the view into the renderer - unless it has already + * been placed in the cursor plane, which can handle alpha. */ +- if (!ps && !planes_ok) ++ if (!ps && !planes_ok) { ++ drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " ++ "(precluded by mode)\n", ev); + force_renderer = true; +- if (!ps && !drm_view_is_opaque(ev)) ++ } ++ if (!ps && !drm_view_is_opaque(ev)) { ++ drm_debug(b, "\t\t\t\t[view] not assigning view %p to plane " ++ "(view not fully opaque)\n", ev); + force_renderer = true; ++ } + + /* Only try to place scanout surfaces in planes-only mode; in + * mixed mode, we have already failed to place a view on the +@@ -3477,6 +3678,9 @@ drm_output_propose_state(struct weston_output *output_base, + * check if this is OK, and add ourselves to the renderer + * region if so. */ + if (!renderer_ok) { ++ drm_debug(b, "\t\t[view] failing state generation: " ++ "placing view %p to renderer not allowed\n", ++ ev); + pixman_region32_fini(&clipped_view); + goto err_region; + } +@@ -3496,8 +3700,11 @@ drm_output_propose_state(struct weston_output *output_base, + + /* Check to see if this state will actually work. */ + ret = drm_pending_state_test(state->pending_state); +- if (ret != 0) ++ if (ret != 0) { ++ drm_debug(b, "\t\t[view] failing state generation: " ++ "atomic test not OK\n"); + goto err; ++ } + + /* Counterpart to duplicating scanout state at the top of this + * function: if we have taken a renderer framebuffer and placed it in +@@ -3530,12 +3737,24 @@ drm_assign_planes(struct weston_output *output_base, void *repaint_data) + struct weston_view *ev; + struct weston_plane *primary = &output_base->compositor->primary_plane; + ++ drm_debug(b, "\t[repaint] preparing state for output %s (%lu)\n", ++ output_base->name, (unsigned long) output_base->id); ++ + if (!b->sprites_are_broken) { + state = drm_output_propose_state(output_base, pending_state, + DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY); +- if (!state) ++ if (!state) { ++ drm_debug(b, "\t[repaint] could not build planes-only " ++ "state, trying mixed\n"); + state = drm_output_propose_state(output_base, pending_state, + DRM_OUTPUT_PROPOSE_STATE_MIXED); ++ } ++ if (!state) { ++ drm_debug(b, "\t[repaint] could not build mixed-mode " ++ "state, trying renderer-only\n"); ++ } ++ } else { ++ drm_debug(b, "\t[state] no overlay plane support\n"); + } + + if (!state) +@@ -3582,10 +3801,16 @@ drm_assign_planes(struct weston_output *output_base, void *repaint_data) + } + } + +- if (target_plane) ++ if (target_plane) { ++ drm_debug(b, "\t[repaint] view %p on %s plane %lu\n", ++ ev, plane_type_enums[target_plane->type].name, ++ (unsigned long) target_plane->plane_id); + weston_view_move_to_plane(ev, &target_plane->base); +- else ++ } else { ++ drm_debug(b, "\t[repaint] view %p using renderer " ++ "composition\n", ev); + weston_view_move_to_plane(ev, primary); ++ } + + if (!target_plane || + target_plane->type == WDRM_PLANE_TYPE_CURSOR) { +@@ -6264,6 +6489,8 @@ drm_destroy(struct weston_compositor *ec) + + destroy_sprites(b); + ++ weston_debug_scope_destroy(b->debug); ++ b->debug = NULL; + weston_compositor_shutdown(ec); + + wl_list_for_each_safe(base, next, &ec->head_list, compositor_link) +@@ -6725,6 +6952,10 @@ drm_backend_create(struct weston_compositor *compositor, + b->pageflip_timeout = config->pageflip_timeout; + b->use_pixman_shadow = config->use_pixman_shadow; + ++ b->debug = weston_compositor_add_debug_scope(compositor, "drm-backend", ++ "Debug messages from DRM/KMS backend\n", ++ NULL, NULL); ++ + compositor->backend = &b->base; + + if (parse_gbm_format(config->gbm_format, GBM_FORMAT_XRGB8888, &b->gbm_format) < 0) +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston/1046-compositor-drm-Read-FB2_MODIFIERS-capability.patch b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1046-compositor-drm-Read-FB2_MODIFIERS-capability.patch new file mode 100644 index 00000000..f3a46b1a --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston/1046-compositor-drm-Read-FB2_MODIFIERS-capability.patch @@ -0,0 +1,89 @@ +From a864f58f44d701164dbb32bfcdde8c6d761f28ee Mon Sep 17 00:00:00 2001 +From: Deepak Rawat <drawat@vmware.com> +Date: Fri, 24 Aug 2018 13:16:03 -0700 +Subject: [PATCH 46/46] compositor-drm: Read FB2_MODIFIERS capability + +Not all drivers support fb2 modifiers so read the capability before +using drmModeAddFB2WithModifiers. + +Signed-off-by: Deepak Rawat <drawat@vmware.com> +--- + libweston/compositor-drm.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/libweston/compositor-drm.c b/libweston/compositor-drm.c +index e024e66f..4cf0d31f 100644 +--- a/libweston/compositor-drm.c ++++ b/libweston/compositor-drm.c +@@ -346,6 +346,8 @@ struct drm_backend { + + bool aspect_ratio_supported; + ++ bool fb_modifiers; ++ + struct weston_debug_scope *debug; + }; + +@@ -961,7 +963,7 @@ drm_fb_destroy_gbm(struct gbm_bo *bo, void *data) + } + + static int +-drm_fb_addfb(struct drm_fb *fb) ++drm_fb_addfb(struct drm_backend *b, struct drm_fb *fb) + { + int ret = -EINVAL; + #ifdef HAVE_DRM_ADDFB2_MODIFIERS +@@ -971,7 +973,7 @@ drm_fb_addfb(struct drm_fb *fb) + + /* If we have a modifier set, we must only use the WithModifiers + * entrypoint; we cannot import it through legacy ioctls. */ +- if (fb->modifier != DRM_FORMAT_MOD_INVALID) { ++ if (b->fb_modifiers && fb->modifier != DRM_FORMAT_MOD_INVALID) { + /* KMS demands that if a modifier is set, it must be the same + * for all planes. */ + #ifdef HAVE_DRM_ADDFB2_MODIFIERS +@@ -1055,7 +1057,7 @@ drm_fb_create_dumb(struct drm_backend *b, int width, int height, + fb->height = height; + fb->fd = b->drm.fd; + +- if (drm_fb_addfb(fb) != 0) { ++ if (drm_fb_addfb(b, fb) != 0) { + weston_log("failed to create kms fb: %m\n"); + goto err_bo; + } +@@ -1228,7 +1230,7 @@ drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf, + goto err_free; + } + +- if (drm_fb_addfb(fb) != 0) ++ if (drm_fb_addfb(backend, fb) != 0) + goto err_free; + + return fb; +@@ -1301,7 +1303,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_backend *backend, + goto err_free; + } + +- if (drm_fb_addfb(fb) != 0) { ++ if (drm_fb_addfb(backend, fb) != 0) { + if (type == BUFFER_GBM_SURFACE) + weston_log("failed to create kms fb: %m\n"); + goto err_free; +@@ -4062,6 +4064,14 @@ init_kms_caps(struct drm_backend *b) + weston_log("DRM: %s atomic modesetting\n", + b->atomic_modeset ? "supports" : "does not support"); + ++#ifdef HAVE_DRM_ADDFB2_MODIFIERS ++ ret = drmGetCap(b->drm.fd, DRM_CAP_ADDFB2_MODIFIERS, &cap); ++ if (ret == 0) ++ b->fb_modifiers = cap; ++ else ++#endif ++ b->fb_modifiers = 0; ++ + /* + * KMS support for hardware planes cannot properly synchronize + * without nuclear page flip. Without nuclear/atomic, hw plane +-- +2.16.2 + diff --git a/bsp/meta-synopsys/recipes-graphics/wayland/weston_5.0.0.bbappend b/bsp/meta-synopsys/recipes-graphics/wayland/weston_5.0.0.bbappend new file mode 100644 index 00000000..ac339435 --- /dev/null +++ b/bsp/meta-synopsys/recipes-graphics/wayland/weston_5.0.0.bbappend @@ -0,0 +1,16 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/weston:" +SRC_URI_append += "\ + file://1001-os-compatibility-define-CLOCK_BOOTTIME-when-not-avai.patch; \ + file://1005-protocol-add-weston-debug.xml.patch; \ + file://1006-libweston-add-weston_debug-API-and-implementation.patch; \ + file://1007-compositor-add-option-to-enable-weston_debug.patch; \ + file://1010-xwm-dump_property-to-use-FILE-internally.patch; \ + file://1011-xwm-move-FILE-to-the-callers-of-dump_property.patch; \ + file://1012-xwm-convert-WM_DEBUG-into-a-weston-debug-scope.patch; \ + file://1014-compositor-Add-weston_layer_mask_is_infinite.patch; \ + file://1015-compositor-Add-scene-graph-debug-scope.patch; \ + file://1017-compositor-drm-Add-backend-pointer-to-drm_output.patch; \ + file://1018-compositor-drm-Add-drm-backend-log-debug-scope.patch; \ + file://1046-compositor-drm-Read-FB2_MODIFIERS-capability.patch; \ +" + |