-----BEGIN PGP SIGNATURE-----
 
 iQJOBAABCAA4FiEEcDKHej6x6uPk3J379jQS5glH1u8FAmTKfCgaHG1hcml1cy52
 bGFkQGNvbGxhYm9yYS5jb20ACgkQ9jQS5glH1u+ihA//e09DRmit8rw2Gglk5N5G
 P/O4m0BukEcXZy4dEo9WEkhrJ/hGTyZ3iqUMtfdbWouEpEMR25ck8n3jTEtUj2QN
 T4Gm/Ljcr8zzmtljbjEBDfBOaE07tISa7aX+IPTg+imf/t54kg80WwuKrW4FbNz2
 azr2L+UAIiFZ4fJ5jA0uiGRiBo2gEwxylujZlt609SQiQCYND+XrFY3fWkHC8vyW
 JfR3IfrYER7KXlxkdJiFE36eIEpgYGIguVp6Uj6B35gxr0+npIrcjY38v/KJILGl
 5mbxnwblGQpLgnBRMb2JmffetK+puFrTSOzEQDSIaOTjuQ0hHX1Ocjg3NfiEoxfi
 eG25SNaqMMUE2U2+cdojP97vCscoU71rwTpuklY1MG37O50jWsjgcUpVKYwcoljA
 TBOhwIJ2jLIzs5Ax37V81Bh7zj95nGYHupHnZOcQ/+SPnjnQ5Je6RE4Me4d0JJdN
 aR/hj/mF+DU80/ySfQwN9/bFp9hbCsozjFClIKiJxnWi71wQZl2o8ZfA8oJZyG6K
 VwYkVTQMoQtTuyDdyD6lbNbbC8/uq8ZnX9qKVHuEZlHWigvGSvuDQLGExuK7Ksjy
 sQPYBdGGWoIJGbqwuJX+FQ/hJgSnY1/VBp82N4//OUYs65LW01ACxF7J8SIIp+nE
 EJhNfCTDnO1hrN5xhmhk+qs=
 =GzNE
 -----END PGP SIGNATURE-----

Merge tag '11.0.3' into dev

11.0.3
dev
Nikita Tokarchuk 3 months ago
commit 0cc7369023
  1. 9
      .gitlab-ci.yml
  2. 23
      .gitlab-ci/build-deps.sh
  3. 2
      .gitlab-ci/debian-install.sh
  4. 6
      .gitlab-ci/leak-sanitizer.supp
  5. 20
      .gitlab-ci/virtme-scripts/per-test-asan.sh
  6. 17
      .gitlab-ci/virtme-scripts/run-weston-tests.sh
  7. 4
      CONTRIBUTING.md
  8. 26
      README.md
  9. 92
      clients/desktop-shell.c
  10. 2
      clients/eventdemo.c
  11. 504
      clients/gears.c
  12. 28
      clients/meson.build
  13. 374
      clients/nested-client.c
  14. 1139
      clients/nested.c
  15. 2
      clients/presentation-shm.c
  16. 10
      clients/simple-dmabuf-egl.c
  17. 114
      clients/simple-dmabuf-feedback.c
  18. 426
      clients/simple-egl.c
  19. 6
      clients/simple-touch.c
  20. 25
      clients/terminal.c
  21. 1890
      clients/weston-info.c
  22. 409
      clients/window.c
  23. 20
      clients/window.h
  24. 634
      compositor/main.c
  25. 24
      compositor/meson.build
  26. 62
      compositor/screen-share.c
  27. 18
      compositor/text-backend.c
  28. 32
      compositor/weston-private.h
  29. 3
      compositor/weston-screenshooter.c
  30. 226
      compositor/xwayland.c
  31. 737
      desktop-shell/exposay.c
  32. 2
      desktop-shell/input-panel.c
  33. 4
      desktop-shell/meson.build
  34. 1201
      desktop-shell/shell.c
  35. 75
      desktop-shell/shell.h
  36. 299
      doc/sphinx/doxygen.ini.in
  37. 1
      doc/sphinx/index.rst
  38. 2
      doc/sphinx/meson.build
  39. BIN
      doc/sphinx/toc/images/ivi-shell.png
  40. 9
      doc/sphinx/toc/images/meson.build
  41. 111
      doc/sphinx/toc/ivi-shell.rst
  42. 2
      doc/sphinx/toc/libweston/images/create_output.msc
  43. 2
      doc/sphinx/toc/meson.build
  44. 31
      doc/sphinx/toc/running-weston.rst
  45. 17
      doc/sphinx/toc/test-suite.rst
  46. 94
      fullscreen-shell/fullscreen-shell.c
  47. 3
      fullscreen-shell/meson.build
  48. 27
      include/libweston-desktop/libweston-desktop.h
  49. 30
      include/libweston/backend-drm.h
  50. 70
      include/libweston/backend-fbdev.h
  51. 13
      include/libweston/backend-rdp.h
  52. 25
      include/libweston/config-parser.h
  53. 339
      include/libweston/libweston.h
  54. 13
      include/libweston/matrix.h
  55. 1
      include/libweston/meson.build
  56. 2
      include/libweston/weston-log.h
  57. 78
      ivi-shell/README
  58. 37
      ivi-shell/hmi-controller.c
  59. 4
      ivi-shell/ivi-layout-export.h
  60. 3
      ivi-shell/ivi-layout-shell.h
  61. 27
      ivi-shell/ivi-layout.c
  62. 14
      ivi-shell/ivi-shell.c
  63. 1
      ivi-shell/meson.build
  64. 72
      kiosk-shell/kiosk-shell.c
  65. 2
      kiosk-shell/kiosk-shell.h
  66. 5
      kiosk-shell/meson.build
  67. 36
      libweston-desktop/meson.build
  68. 497
      libweston-desktop/wl-shell.c
  69. 91
      libweston/backend-drm/drm-gbm.c
  70. 180
      libweston/backend-drm/drm-internal.h
  71. 64
      libweston/backend-drm/drm-virtual.c
  72. 703
      libweston/backend-drm/drm.c
  73. 118
      libweston/backend-drm/fb.c
  74. 178
      libweston/backend-drm/kms-color.c
  75. 311
      libweston/backend-drm/kms.c
  76. 27
      libweston/backend-drm/libbacklight.c
  77. 2
      libweston/backend-drm/meson.build
  78. 72
      libweston/backend-drm/modes.c
  79. 29
      libweston/backend-drm/state-helpers.c
  80. 682
      libweston/backend-drm/state-propose.c
  81. 998
      libweston/backend-fbdev/fbdev.c
  82. 33
      libweston/backend-fbdev/meson.build
  83. 77
      libweston/backend-headless/headless.c
  84. 22
      libweston/backend-rdp/meson.build
  85. 829
      libweston/backend-rdp/rdp.c
  86. 263
      libweston/backend-rdp/rdp.h
  87. 1754
      libweston/backend-rdp/rdpclip.c
  88. 262
      libweston/backend-rdp/rdputil.c
  89. 293
      libweston/backend-wayland/wayland.c
  90. 140
      libweston/backend-x11/x11.c
  91. 24
      libweston/backend.h
  92. 4
      libweston/bindings.c
  93. 2
      libweston/clipboard.c
  94. 283
      libweston/color-lcms/color-lcms.c
  95. 101
      libweston/color-lcms/color-lcms.h
  96. 287
      libweston/color-lcms/color-profile.c
  97. 242
      libweston/color-lcms/color-transform.c
  98. 1
      libweston/color-lcms/meson.build
  99. 68
      libweston/color-noop.c
  100. 52
      libweston/color.c
  101. Some files were not shown because too many files have changed in this diff Show More

@ -43,7 +43,7 @@
variables:
FDO_UPSTREAM_REPO: wayland/weston
FDO_REPO_SUFFIX: "$BUILD_OS/$BUILD_ARCH"
FDO_DISTRIBUTION_TAG: '2021-11-25.0-dmabuf-feedback'
FDO_DISTRIBUTION_TAG: '2022-07-13.00-wayland-protocols-1.26'
include:
@ -202,7 +202,7 @@ aarch64-debian-container_prep:
- $BUILDDIR/weston-virtme
- $PREFIX
reports:
junit: $BUILDDIR/meson-logs/testlog.junit.xml
junit: $BUILDDIR/meson-logs/testlog-per-test-asan.sh.junit.xml
# Same as above, but without running any tests.
.build-no-test:
@ -283,8 +283,8 @@ aarch64-debian-container_prep:
-Dwerror=true
-Dtest-skip-is-failure=true
-Dlauncher-libseat=true
-Ddeprecated-backend-fbdev=true
-Ddeprecated-weston-launch=true
-Ddeprecated-color-management-static=true
-Ddeprecated-color-management-colord=true
after_script:
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
- ninja -C "$BUILDDIR" coverage-xml
@ -340,7 +340,6 @@ docs-build:
-Dpipewire=false
-Dwerror=true
-Dlauncher-libseat=true
-Ddeprecated-weston-launch=true
x86_64-debian-no-gl-build:
extends:

@ -75,7 +75,8 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
--enable CONFIG_DRM \
--enable CONFIG_DRM_KMS_HELPER \
--enable CONFIG_DRM_KMS_FB_HELPER \
--enable CONFIG_DRM_VKMS
--enable CONFIG_DRM_VKMS \
--enable CONFIG_DRM_VGEM
make ARCH=${LINUX_ARCH} oldconfig
make ARCH=${LINUX_ARCH}
@ -94,7 +95,7 @@ fi
# Build and install Wayland; keep this version in sync with our dependency
# in meson.build.
git clone --branch 1.18.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
git clone --branch 1.20.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
cd wayland
git show -s HEAD
mkdir build
@ -106,7 +107,7 @@ rm -rf wayland
# Keep this version in sync with our dependency in meson.build. If you wish to
# raise a MR against custom protocol, please change this reference to clone
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
git clone --branch 1.24 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
git clone --branch 1.26 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
cd wayland-protocols
git show -s HEAD
meson build
@ -129,6 +130,17 @@ ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf mesa
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api. We can stop
# building and installing libdrm as soon as we move to Debian 12.
git clone --branch libdrm-2.4.108 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
cd drm
meson build -Dauto_features=disabled \
-Dvc4=false -Dfreedreno=false -Detnaviv=false
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf drm
# PipeWire is used for remoting support. Unlike our other dependencies its
# behaviour will be stable, however as a pre-1.0 project its API is not yet
# stable, so again we lock it to a fixed version.
@ -142,9 +154,8 @@ ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf pipewire-src
# seatd lets us avoid the pain of handling VTs manually through weston-launch
# or open-coding TTY assignment within Weston. We use this for our tests using
# the DRM backend.
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
# We use this for our tests using the DRM backend.
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
cd seatd
meson build -Dauto_features=disabled \

@ -39,6 +39,7 @@ apt-get -y --no-install-recommends install \
clang-11 \
curl \
doxygen \
graphviz \
freerdp2-dev \
gcovr \
git \
@ -68,6 +69,7 @@ apt-get -y --no-install-recommends install \
libmtdev-dev \
libpam0g-dev \
libpango1.0-dev \
libpciaccess-dev \
libpixman-1-dev \
libpng-dev \
libpulse-dev \

@ -3,3 +3,9 @@
# Cairo internal leaks from weston-keyboard
leak:cairo_select_font_face
leak:cairo_text_extents
# Pango thread-global state (not destroyable?)
leak:pango_language_get_default
# This leaks in Debian's fontconfig/Xwayland setup?
leak:FcConfigSubstituteWithPat

@ -0,0 +1,20 @@
#!/bin/bash
# When running Debian's Xwayland and fontconfig, we hit memory leaks which
# aren't visible on other setups. We do have suppressions for these tests, but
# regrettably ASan can't see through omitted frame pointers in Expat, so for
# Xwayland specifically, we disable fast-unwind.
#
# Doing it globally makes the other tests far, far, too slow to run.
case "$1" in
*xwayland*)
export ASAN_OPTIONS="detect_leaks=0,fast_unwind_on_malloc=0"
;;
*)
export ASAN_OPTIONS="detect_leaks=0"
;;
esac
export ASAN_OPTIONS
exec "$@"

@ -7,8 +7,15 @@ chmod -R 0700 /tmp
# set environment variables to run Weston tests
export XDG_RUNTIME_DIR=/tmp/tests
export WESTON_TEST_SUITE_DRM_DEVICE=card0
export LIBSEAT_BACKEND=seatd
# In our test suite, we use VKMS to run DRM-backend tests. The order in which
# devices are loaded is not predictable, so the DRM node that VKMS takes can
# change across each boot. That's why we have this one-liner shell script to get
# the appropriate node for VKMS.
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/devices/platform/vkms/drm/card*)
# To run tests in the CI that exercise the zwp_linux_dmabuf_v1 implementation in
# Weston, we use VGEM to allocate buffers.
export WESTON_TEST_SUITE_ALLOC_DEVICE=$(basename /sys/devices/platform/vgem/drm/card*)
# ninja test depends on meson, and meson itself looks for its modules on folder
# $HOME/.local/lib/pythonX.Y/site-packages (the Python version may differ).
@ -19,13 +26,17 @@ export HOME=/root
export PATH=$HOME/.local/bin:$PATH
export PATH=/usr/local/bin:$PATH
export ASAN_OPTIONS=detect_leaks=0,atexit=1
export SEATD_LOGLEVEL=debug
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
# llvmpipe driver module location
export WESTON_CI_LEAK_DL_HANDLE=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true)
# run the tests and save the exit status
# we give ourselves a very generous timeout multiplier due to ASan overhead
echo 0x1f > /sys/module/drm/parameters/debug
seatd-launch -- meson test --no-rebuild --timeout-multiplier 4
seatd-launch -- meson test --no-rebuild --timeout-multiplier 4 \
--wrapper $(pwd)/../.gitlab-ci/virtme-scripts/per-test-asan.sh
# note that we need to store the return value from the tests in order to
# determine if the test suite ran successfully or not.
TEST_RES=$?

@ -208,6 +208,10 @@ my_function(void)
parameter3, parameter4);
```
- do not write fallback paths for failed simple memory allocations, use the
`x*alloc()` wrappers from `shared/xalloc.h` instead or use
`abort_oom_if_null()`
Conduct
=======

@ -18,6 +18,12 @@ bugs and shortcomings, we avoid unknown or variable behaviour as much as
possible, including variable performance such as occasional spikes in frame
display time.
Weston and libweston are not suitable for memory constrained environments
where the compositor is expected to continue running even in the face of
trivial memory allocations failing. If standard functions like `malloc()`
fail for small allocations,
[you can expect libweston to abort](https://gitlab.freedesktop.org/wayland/weston/-/issues/631).
A small suite of example or demo clients are also provided: though they can be
useful in themselves, their main purpose is to be an example or test case for
others building compositors or clients.
@ -93,13 +99,6 @@ the available configuration options and display backends. It can also be
configured through a file on disk; more information on this can be found through
`man weston.ini`.
In some special cases, such as when running remotely or without logind's session
control, Weston may not be able to run directly from a text console. In these
situations, you can instead execute the `weston-launch` helper, which will gain
privileged access to input and output devices by running as root, then granting
access to the main Weston binary running as your user. Running Weston this way
is not recommended unless necessary.
Documentation
=============
@ -294,7 +293,7 @@ Details:
- Child process execution and management will be outside of libweston.
- The different backends (drm, fbdev, x11, etc) will be an internal
- The different backends (drm, x11, etc) will be an internal
detail of libweston. Libweston will not support third party
backends. However, hosting programs need to handle
backend-specific configuration due to differences in behaviour and
@ -308,19 +307,12 @@ Details:
- xwayland ???
- weston-launch is still with libweston even though it can only launch
Weston and nothing else. We would like to allow it to launch any compositor,
but since it gives by design root access to input devices and DRM, how can
we restrict it to intended programs?
There are still many more details to be decided.
For packagers
-------------
Always build Weston with --with-cairo=image.
The Weston project is (will be) intended to be split into several
binary packages, each with its own dependencies. The maximal split
would be roughly like this:
@ -337,15 +329,13 @@ would be roughly like this:
- xwayland (depends on X11/xcb libs)
- fbdev-backend (depends on libudev...)
- rdp-backend (depends on freerdp)
- weston (the executable, not parallel-installable):
+ desktop shell
+ ivi-shell
+ fullscreen shell
+ weston-info (deprecated), weston-terminal, etc. we install by default
+ weston-terminal, etc. we install by default
+ screen-share
- weston demos (not parallel-installable)

@ -41,22 +41,23 @@
#include <assert.h>
#include <wayland-client.h>
#include "window.h"
#include "shared/cairo-util.h"
#include <libweston/config-parser.h>
#include <libweston/zalloc.h>
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include <libweston/zalloc.h>
#include "shared/cairo-util.h"
#include "shared/file-util.h"
#include "shared/process-util.h"
#include "shared/timespec-util.h"
#include "window.h"
#include "weston-desktop-shell-client-protocol.h"
#define DEFAULT_CLOCK_FORMAT CLOCK_FORMAT_MINUTES
#define DEFAULT_SPACING 10
extern char **environ; /* defined by libc */
enum clock_format {
CLOCK_FORMAT_MINUTES,
CLOCK_FORMAT_SECONDS,
@ -142,9 +143,11 @@ struct panel_launcher {
cairo_surface_t *icon;
int focused, pressed;
char *path;
char *displayname;
struct wl_list link;
struct wl_array envp;
struct wl_array argv;
struct custom_env env;
char * const *argp;
char * const *envp;
};
struct panel_clock {
@ -211,7 +214,6 @@ check_desktop_ready(struct window *window)
static void
panel_launcher_activate(struct panel_launcher *widget)
{
char **argv;
pid_t pid;
pid = fork();
@ -223,13 +225,11 @@ panel_launcher_activate(struct panel_launcher *widget)
if (pid)
return;
argv = widget->argv.data;
if (setsid() == -1)
exit(EXIT_FAILURE);
if (execve(argv[0], argv, widget->envp.data) < 0) {
fprintf(stderr, "execl '%s' failed: %s\n", argv[0],
if (execve(widget->argp[0], widget->argp, widget->envp) < 0) {
fprintf(stderr, "execl '%s' failed: %s\n", widget->argp[0],
strerror(errno));
exit(1);
}
@ -277,7 +277,7 @@ panel_launcher_motion_handler(struct widget *widget, struct input *input,
{
struct panel_launcher *launcher = data;
widget_set_tooltip(widget, basename((char *)launcher->path), x, y);
widget_set_tooltip(widget, launcher->displayname, x, y);
return CURSOR_LEFT_PTR;
}
@ -575,10 +575,10 @@ panel_configure(void *data,
static void
panel_destroy_launcher(struct panel_launcher *launcher)
{
wl_array_release(&launcher->argv);
wl_array_release(&launcher->envp);
custom_env_fini(&launcher->env);
free(launcher->path);
free(launcher->displayname);
cairo_surface_destroy(launcher->icon);
@ -678,58 +678,19 @@ load_icon_or_fallback(const char *icon)
}
static void
panel_add_launcher(struct panel *panel, const char *icon, const char *path)
panel_add_launcher(struct panel *panel, const char *icon, const char *path, const char *displayname)
{
struct panel_launcher *launcher;
char *start, *p, *eq, **ps;
int i, j, k;
launcher = xzalloc(sizeof *launcher);
launcher->icon = load_icon_or_fallback(icon);
launcher->path = xstrdup(path);
launcher->displayname = xstrdup(displayname);
wl_array_init(&launcher->envp);
wl_array_init(&launcher->argv);
for (i = 0; environ[i]; i++) {
ps = wl_array_add(&launcher->envp, sizeof *ps);
*ps = environ[i];
}
j = 0;
start = launcher->path;
while (*start) {
for (p = start, eq = NULL; *p && !isspace(*p); p++)
if (*p == '=')
eq = p;
if (eq && j == 0) {
ps = launcher->envp.data;
for (k = 0; k < i; k++)
if (strncmp(ps[k], start, eq - start) == 0) {
ps[k] = start;
break;
}
if (k == i) {
ps = wl_array_add(&launcher->envp, sizeof *ps);
*ps = start;
i++;
}
} else {
ps = wl_array_add(&launcher->argv, sizeof *ps);
*ps = start;
j++;
}
while (*p && isspace(*p))
*p++ = '\0';
start = p;
}
ps = wl_array_add(&launcher->envp, sizeof *ps);
*ps = NULL;
ps = wl_array_add(&launcher->argv, sizeof *ps);
*ps = NULL;
custom_env_init_from_environ(&launcher->env);
custom_env_add_from_exec_string(&launcher->env, launcher->path);
launcher->envp = custom_env_get_envp(&launcher->env);
launcher->argp = custom_env_get_argp(&launcher->env);
launcher->panel = panel;
wl_list_insert(panel->launcher_list.prev, &launcher->link);
@ -1447,7 +1408,7 @@ static void
panel_add_launchers(struct panel *panel, struct desktop *desktop)
{
struct weston_config_section *s;
char *icon, *path;
char *icon, *path, *displayname;
const char *name;
int count;
@ -1459,9 +1420,12 @@ panel_add_launchers(struct panel *panel, struct desktop *desktop)
weston_config_section_get_string(s, "icon", &icon, NULL);
weston_config_section_get_string(s, "path", &path, NULL);
weston_config_section_get_string(s, "displayname", &displayname, NULL);
if (displayname == NULL)
displayname = xstrdup(basename(path));
if (icon != NULL && path != NULL) {
panel_add_launcher(panel, icon, path);
panel_add_launcher(panel, icon, path, displayname);
count++;
} else {
fprintf(stderr, "invalid launcher section\n");
@ -1469,6 +1433,7 @@ panel_add_launchers(struct panel *panel, struct desktop *desktop)
free(icon);
free(path);
free(displayname);
}
if (count == 0) {
@ -1477,7 +1442,8 @@ panel_add_launchers(struct panel *panel, struct desktop *desktop)
/* add default launcher */
panel_add_launcher(panel,
name,
BINDIR "/weston-terminal");
BINDIR "/weston-terminal",
"Terminal");
free(name);
}
}

@ -351,8 +351,6 @@ axis_discrete_handler(struct widget *widget, struct input *input,
* \param widget widget
* \param input input device that caused the motion event
* \param time time the event happened
* \param x absolute x position
* \param y absolute y position
* \param x x position relative to the window
* \param y y position relative to the window
* \param data user data associated to the window

@ -1,504 +0,0 @@
/*
* Copyright ยฉ 2008 Kristian Hรธgsberg
*
* 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 <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <errno.h>
#include <GL/gl.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <linux/input.h>
#include <wayland-client.h>
#include "window.h"
struct gears {
struct window *window;
struct widget *widget;
struct display *d;
EGLDisplay display;
EGLDisplay config;
EGLContext context;
GLfloat angle;
struct {
GLfloat rotx;
GLfloat roty;
} view;
int button_down;
int last_x, last_y;
GLint gear_list[3];
int fullscreen;
int frames;
uint32_t last_fps;
};
struct gear_template {
GLfloat material[4];
GLfloat inner_radius;
GLfloat outer_radius;
GLfloat width;
GLint teeth;
GLfloat tooth_depth;
};
static const struct gear_template gear_templates[] = {
{ { 0.8, 0.1, 0.0, 1.0 }, 1.0, 4.0, 1.0, 20, 0.7 },
{ { 0.0, 0.8, 0.2, 1.0 }, 0.5, 2.0, 2.0, 10, 0.7 },
{ { 0.2, 0.2, 1.0, 1.0 }, 1.3, 2.0, 0.5, 10, 0.7 },
};
static GLfloat light_pos[4] = {5.0, 5.0, 10.0, 0.0};
static void die(const char *msg)
{
fprintf(stderr, "%s", msg);
exit(EXIT_FAILURE);
}
static void
make_gear(const struct gear_template *t)
{
GLint i;
GLfloat r0, r1, r2;
GLfloat angle, da;
GLfloat u, v, len;
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, t->material);
r0 = t->inner_radius;
r1 = t->outer_radius - t->tooth_depth / 2.0;
r2 = t->outer_radius + t->tooth_depth / 2.0;
da = 2.0 * M_PI / t->teeth / 4.0;
glShadeModel(GL_FLAT);
glNormal3f(0.0, 0.0, 1.0);
/* draw front face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= t->teeth; i++) {
angle = i * 2.0 * M_PI / t->teeth;
glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
if (i < t->teeth) {
glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
}
}
glEnd();
/* draw front sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / t->teeth / 4.0;
for (i = 0; i < t->teeth; i++) {
angle = i * 2.0 * M_PI / t->teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
}
glEnd();
glNormal3f(0.0, 0.0, -1.0);
/* draw back face */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= t->teeth; i++) {
angle = i * 2.0 * M_PI / t->teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
if (i < t->teeth) {
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
}
}
glEnd();
/* draw back sides of teeth */
glBegin(GL_QUADS);
da = 2.0 * M_PI / t->teeth / 4.0;
for (i = 0; i < t->teeth; i++) {
angle = i * 2.0 * M_PI / t->teeth;
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
}
glEnd();
/* draw outward faces of teeth */
glBegin(GL_QUAD_STRIP);
for (i = 0; i < t->teeth; i++) {
angle = i * 2.0 * M_PI / t->teeth;
glVertex3f(r1 * cos(angle), r1 * sin(angle), t->width * 0.5);
glVertex3f(r1 * cos(angle), r1 * sin(angle), -t->width * 0.5);
u = r2 * cos(angle + da) - r1 * cos(angle);
v = r2 * sin(angle + da) - r1 * sin(angle);
len = sqrt(u * u + v * v);
u /= len;
v /= len;
glNormal3f(v, -u, 0.0);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), t->width * 0.5);
glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -t->width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), t->width * 0.5);
glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -t->width * 0.5);
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
glNormal3f(v, -u, 0.0);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), t->width * 0.5);
glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -t->width * 0.5);
glNormal3f(cos(angle), sin(angle), 0.0);
}
glVertex3f(r1 * cos(0), r1 * sin(0), t->width * 0.5);
glVertex3f(r1 * cos(0), r1 * sin(0), -t->width * 0.5);
glEnd();
glShadeModel(GL_SMOOTH);
/* draw inside radius cylinder */
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= t->teeth; i++) {
angle = i * 2.0 * M_PI / t->teeth;
glNormal3f(-cos(angle), -sin(angle), 0.0);
glVertex3f(r0 * cos(angle), r0 * sin(angle), -t->width * 0.5);
glVertex3f(r0 * cos(angle), r0 * sin(angle), t->width * 0.5);
}
glEnd();
}
static void
update_fps(struct gears *gears, uint32_t time)
{
long diff_ms;
static bool first_call = true;
if (first_call) {
gears->last_fps = time;
first_call = false;
} else
gears->frames++;
diff_ms = time - gears->last_fps;
if (diff_ms > 5000) {
float seconds = diff_ms / 1000.0;
float fps = gears->frames / seconds;
printf("%d frames in %6.3f seconds = %6.3f FPS\n", gears->frames, seconds, fps);
fflush(stdout);
gears->frames = 0;
gears->last_fps = time;
}
}
static void
frame_callback(void *data, struct wl_callback *callback, uint32_t time)
{
struct gears *gears = data;
update_fps(gears, time);
gears->angle = (GLfloat) (time % 8192) * 360 / 8192.0;
window_schedule_redraw(gears->window);
if (callback)
wl_callback_destroy(callback);
}
static const struct wl_callback_listener listener = {
frame_callback
};
static int
motion_handler(struct widget *widget, struct input *input,
uint32_t time, float x, float y, void *data)
{
struct gears *gears = data;
int offset_x, offset_y;
float step = 0.5;
if (gears->button_down) {
offset_x = x - gears->last_x;
offset_y = y - gears->last_y;
gears->last_x = x;
gears->last_y = y;
gears->view.roty += offset_x * step;
gears->view.rotx += offset_y * step;
if (gears->view.roty >= 360)
gears->view.roty = gears->view.roty - 360;
if (gears->view.roty <= 0)
gears->view.roty = gears->view.roty + 360;
if (gears->view.rotx >= 360)
gears->view.rotx = gears->view.rotx - 360;
if (gears->view.rotx <= 0)
gears->view.rotx = gears->view.rotx + 360;
}
return CURSOR_LEFT_PTR;
}
static void
button_handler(struct widget *widget, struct input *input,
uint32_t time, uint32_t button,
enum wl_pointer_button_state state, void *data)
{
struct gears *gears = data;
if (button == BTN_LEFT) {
if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
gears->button_down = 1;
input_get_position(input,
&gears->last_x, &gears->last_y);
} else {
gears->button_down = 0;
}
}
}
static void
redraw_handler(struct widget *widget, void *data)
{
struct rectangle window_allocation;
struct rectangle allocation;
struct wl_callback *callback;
struct gears *gears = data;
widget_get_allocation(gears->widget, &allocation);
window_get_allocation(gears->window, &window_allocation);
if (display_acquire_window_surface(gears->d,
gears->window,
gears->context) < 0) {
die("Unable to acquire window surface, "
"compiled without cairo-egl?\n");
}
glViewport(allocation.x,
window_allocation.height - allocation.height - allocation.y,
allocation.width, allocation.height);
glScissor(allocation.x,
window_allocation.height - allocation.height - allocation.y,
allocation.width, allocation.height);
glEnable(GL_SCISSOR_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glTranslatef(0.0, 0.0, -50);
glRotatef(gears->view.rotx, 1.0, 0.0, 0.0);
glRotatef(gears->view.roty, 0.0, 1.0, 0.0);
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(gears->angle, 0.0, 0.0, 1.0);
glCallList(gears->gear_list[0]);
glPopMatrix();
glPushMatrix();
glTranslatef(3.1, -2.0, 0.0);
glRotatef(-2.0 * gears->angle - 9.0, 0.0, 0.0, 1.0);
glCallList(gears->gear_list[1]);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.1, 4.2, 0.0);
glRotatef(-2.0 * gears->angle - 25.0, 0.0, 0.0, 1.0);
glCallList(gears->gear_list[2]);
glPopMatrix();
glPopMatrix();
glFlush();
display_release_window_surface(gears->d, gears->window);
callback = wl_surface_frame(window_get_wl_surface(gears->window));
wl_callback_add_listener(callback, &listener, gears);
}
static void
resize_handler(struct widget *widget,
int32_t width, int32_t height, void *data)
{
struct gears *gears = data;
int32_t size, big, small;
/* Constrain child size to be square and at least 300x300 */
if (width < height) {
small = width;
big = height;
} else {
small = height;
big = width;
}
if (gears->fullscreen)
size = small;
else
size = big;
widget_set_size(gears->widget, size, size);
}
static void
keyboard_focus_handler(struct window *window,
struct input *device, void *data)
{
window_schedule_redraw(window);
}
static void
fullscreen_handler(struct window *window, void *data)
{
struct gears *gears = data;
gears->fullscreen ^= 1;
window_set_fullscreen(window, gears->fullscreen);
}
static struct gears *
gears_create(struct display *display)
{
const int width = 450, height = 500;
struct gears *gears;
int i;
gears = zalloc(sizeof *gears);
gears->d = display;
gears->window = window_create(display);
gears->widget = window_frame_create(gears->window, gears);
window_set_title(gears->window, "Wayland Gears");
window_set_appid(gears->window, "org.freedesktop.weston.wayland-gears");
gears->display = display_get_egl_display(gears->d);
if (gears->display == NULL)
die("failed to create egl display\n");
eglBindAPI(EGL_OPENGL_API);
gears->config = display_get_argb_egl_config(gears->d);
gears->context = eglCreateContext(gears->display, gears->config,
EGL_NO_CONTEXT, NULL);
if (gears->context == NULL)
die("failed to create context\n");
if (!eglMakeCurrent(gears->display, NULL, NULL, gears->context))
die("failed to make context current\n");
for (i = 0; i < 3; i++) {
gears->gear_list[i] = glGenLists(1);
glNewList(gears->gear_list[i], GL_COMPILE);
make_gear(&gear_templates[i]);
glEndList();
}
gears->button_down = 0;
gears->last_x = 0;
gears->last_y = 0;
gears->view.rotx = 20.0;
gears->view.roty = 30.0;
printf("Warning: FPS count is limited by the wayland compositor or monitor refresh rate\n");
glEnable(GL_NORMALIZE);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0);
glMatrixMode(GL_MODELVIEW);
glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glClearColor(0, 0, 0, 0.92);
window_set_user_data(gears->window, gears);
widget_set_resize_handler(gears->widget, resize_handler);
widget_set_redraw_handler(gears->widget, redraw_handler);
widget_set_button_handler(gears->widget, button_handler);
widget_set_motion_handler(gears->widget, motion_handler);
window_set_keyboard_focus_handler(gears->window,
keyboard_focus_handler);
window_set_fullscreen_handler(gears->window, fullscreen_handler);
window_schedule_resize(gears->window, width, height);
return gears;
}
static void
gears_destroy(struct gears *gears)
{
widget_destroy(gears->widget);
window_destroy(gears->window);
free(gears);
}
int main(int argc, char *argv[])
{
struct display *d;
struct gears *gears;
d = display_create(&argc, argv);
if (d == NULL) {
fprintf(stderr, "failed to create display: %s\n",
strerror(errno));
return -1;
}
gears = gears_create(d);
display_run(d);
gears_destroy(gears);
display_destroy(d);
return 0;
}

@ -35,6 +35,10 @@ dep_toytoolkit = declare_dependency(
link_with: lib_toytoolkit,
dependencies: deps_toytoolkit,
)
dep_gbm = dependency('gbm', required: false)
if dep_gbm.found() and dep_gbm.version().version_compare('>= 21.3')
config_h.set('HAVE_GBM_BO_CREATE_WITH_MODIFIERS2', '1')
endif
simple_clients_enabled = get_option('simple-clients')
simple_build_all = simple_clients_enabled.contains('all')
@ -60,6 +64,8 @@ simple_clients = [
'../libweston/pixel-formats.c',
linux_dmabuf_unstable_v1_client_protocol_h,
linux_dmabuf_unstable_v1_protocol_c,
presentation_time_client_protocol_h,
presentation_time_protocol_c,
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
],
@ -125,7 +131,12 @@ simple_clients = [
ivi_application_client_protocol_h,
ivi_application_protocol_c,
],
'dep_objs': [ dep_wayland_client, dep_libshared, dep_libm ],
'dep_objs': [
dep_libm,
dep_libshared,
dep_matrix_c,
dep_wayland_client,
],
'deps': [ 'egl', 'wayland-egl', 'glesv2', 'wayland-cursor' ],
'options': [ 'renderer-gl' ]
},
@ -217,21 +228,6 @@ tools_list = [
],
'deps': [ dep_wayland_client ]
},
{
'name': 'info',
'sources': [
'weston-info.c',
presentation_time_client_protocol_h,
presentation_time_protocol_c,
linux_dmabuf_unstable_v1_client_protocol_h,
linux_dmabuf_unstable_v1_protocol_c,
tablet_unstable_v2_client_protocol_h,
tablet_unstable_v2_protocol_c,
xdg_output_unstable_v1_client_protocol_h,
xdg_output_unstable_v1_protocol_c,
],
'deps': [ dep_wayland_client, dep_libshared ]
},
{
'name': 'terminal',
'sources': [ 'terminal.c' ],

@ -1,374 +0,0 @@
/*
* Copyright ยฉ 2013 Intel Corporation
*
* 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-egl.h>
#include <wayland-cursor.h>
#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include "shared/platform.h"
struct window;
struct seat;
struct nested_client {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
EGLDisplay egl_display;
EGLContext egl_context;
EGLConfig egl_config;
EGLSurface egl_surface;
struct program *color_program;
GLuint vert, frag, program;
GLuint rotation;
GLuint pos;
GLuint col;
struct wl_surface *surface;
struct wl_egl_window *native;
int width, height;
};
#define POS 0
#define COL 1
static GLuint
create_shader(const char *source, GLenum shader_type)
{
GLuint shader;
GLint status;
shader = glCreateShader(shader_type);
if (shader == 0)
return 0;
glShaderSource(shader, 1, (const char **) &source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if (!status) {
char log[1000];
GLsizei len;
glGetShaderInfoLog(shader, 1000, &len, log);
fprintf(stderr, "Error: compiling %s: %.*s\n",
shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment",
len, log);
return 0;
}
return shader;
}
static void
create_program(struct nested_client *client,
const char *vert, const char *frag)
{
GLint status;
client->vert = create_shader(vert, GL_VERTEX_SHADER);
client->frag = create_shader(frag, GL_FRAGMENT_SHADER);
client->program = glCreateProgram();
glAttachShader(client->program, client->frag);
glAttachShader(client->program, client->vert);
glBindAttribLocation(client->program, POS, "pos");
glBindAttribLocation(client->program, COL, "color");
glLinkProgram(client->program);
glGetProgramiv(client->program, GL_LINK_STATUS, &status);
if (!status) {
char log[1000];
GLsizei len;
glGetProgramInfoLog(client->program, 1000, &len, log);
fprintf(stderr, "Error: linking:\n%.*s\n", len, log);
exit(1);
}
client->rotation =
glGetUniformLocation(client->program, "rotation");
}
static const char vertex_shader_text[] =
"uniform mat4 rotation;\n"
"attribute vec4 pos;\n"
"attribute vec4 color;\n"
"varying vec4 v_color;\n"
"void main() {\n"
" gl_Position = rotation * pos;\n"
" v_color = color;\n"
"}\n";
static const char color_fragment_shader_text[] =
"precision mediump float;\n"
"varying vec4 v_color;\n"
"void main() {\n"
" gl_FragColor = v_color;\n"
"}\n";
static void
render_triangle(struct nested_client *client, uint32_t time)
{
static const GLfloat verts[3][2] = {
{ -0.5, -0.5 },
{ 0.5, -0.5 },
{ 0, 0.5 }
};
static const GLfloat colors[3][3] = {
{ 1, 0, 0 },
{ 0, 1, 0 },
{ 0, 0, 1 }
};
GLfloat angle;
GLfloat rotation[4][4] = {
{ 1, 0, 0, 0 },
{ 0, 1, 0, 0 },
{ 0, 0, 1, 0 },
{ 0, 0, 0, 1 }
};
static const int32_t speed_div = 5;
static uint32_t start_time = 0;
if (client->program == 0)
create_program(client, vertex_shader_text,
color_fragment_shader_text);
if (start_time == 0)
start_time = time;
angle = ((time - start_time) / speed_div) % 360 * M_PI / 180.0;
rotation[0][0] = cos(angle);
rotation[0][2] = sin(angle);
rotation[2][0] = -sin(angle);
rotation[2][2] = cos(angle);
glClearColor(0.4, 0.4, 0.4, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(client->program);
glViewport(0, 0, client->width, client->height);
glUniformMatrix4fv(client->rotation, 1, GL_FALSE,
(GLfloat *) rotation);
glVertexAttribPointer(POS, 2, GL_FLOAT, GL_FALSE, 0, verts);
glVertexAttribPointer(COL, 3, GL_FLOAT, GL_FALSE, 0, colors);
glEnableVertexAttribArray(POS);
glEnableVertexAttribArray(COL);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(POS);
glDisableVertexAttribArray(COL);
glFlush();
}
static void
frame_callback(void *data, struct wl_callback *callback, uint32_t time);
static const