Compare commits

..

No commits in common. "main" and "13.0.92" have entirely different histories.

340 changed files with 16545 additions and 52375 deletions

View file

@ -1,6 +1,6 @@
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
.templates_sha: &template_sha 32afe5644697e503af18a736587c8619fa036a72 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
.templates_sha: &template_sha 184ca628f89f3193c249b4e34e45afee2773a833 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
# This file uses the freedesktop ci-templates to build Weston and run our
# tests in CI.
#
@ -43,7 +43,7 @@
variables:
FDO_UPSTREAM_REPO: wayland/weston
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
FDO_DISTRIBUTION_TAG: '2025-12-19-mesa-25.3.2'
FDO_DISTRIBUTION_TAG: '2024-08-14-00-freerdp3.x'
include:
@ -66,11 +66,6 @@ include:
# we need a default case though, so all the rest still run
- when: on_success
default:
retry:
max: 2
when: runner_system_failure
.merge-rules:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
@ -84,7 +79,7 @@ stages:
- "Pre Base container"
- "Base container"
- "Full build and test"
- "No-GL/Vulkan build and test"
- "No-GL build and test"
- "Other builds"
- pages
@ -93,23 +88,20 @@ stages:
.os-debian-lts:
variables:
BUILD_OS: debian
LLVM_VERSION: 15
USE_DEBIAN_BACKPORTS: y
PACKAGES_SPECIFIC: vulkan-validationlayers-dev
LLVM_VERSION: 11
FREERDP_VERSION: 2
FDO_DISTRIBUTION_VERSION: bookworm
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
FDO_DISTRIBUTION_VERSION: bullseye
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
.os-debian:
variables:
BUILD_OS: debian
LLVM_VERSION: 19
LLVM_VERSION: 15
FREERDP_VERSION: 3
USE_DEBIAN_BACKPORTS: y
PACKAGES_SPECIFIC: vulkan-utility-libraries-dev libpolly-19-dev libclang-rt-19-dev python3-standard-imghdr
# If you upgrade from trixie, see the use_tls=0 notes in tests/meson.build.
FDO_DISTRIBUTION_VERSION: trixie
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
USE_BOOKWORM_BACKPORTS: y
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
FDO_DISTRIBUTION_VERSION: bookworm
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
# Does not inherit .default-rules as we only want it to run in MR context.
check-commit:
@ -119,6 +111,7 @@ check-commit:
stage: "Merge request checks"
script:
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
variables:
GIT_DEPTH: 100
artifacts:
@ -146,14 +139,12 @@ check-commit:
- .os-debian-lts
variables:
BUILD_ARCH: "armv7"
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
.debian-armv7:
extends:
- .os-debian
variables:
BUILD_ARCH: "armv7"
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
# Inhibit installation of freerdp-dev
@ -220,6 +211,8 @@ armv7-debian-lts-container_prep:
- .fdo.container-build@debian
tags:
- aarch64
variables:
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
needs:
- job: base-container-pre
timeout: 30m
@ -232,6 +225,8 @@ armv7-debian-container_prep:
- .fdo.container-build@debian
tags:
- aarch64
variables:
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
needs:
- job: base-container-pre
timeout: 30m
@ -267,23 +262,17 @@ aarch64-debian-container_prep:
timeout: 15m
variables:
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
BUILDDIR_WESTINY: $CI_PROJECT_DIR/build-westiny-$CI_JOB_NAME
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
PREFIX_WESTINY: $CI_PROJECT_DIR/prefix-westiny-$CI_JOB_NAME
before_script:
- export PATH=~/.local/bin:$PATH
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
- export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
- mkdir "$BUILDDIR" "$PREFIX"
- mkdir "$BUILDDIR_WESTINY" "$PREFIX_WESTINY"
.build-with-clang:
variables:
CC: clang-$LLVM_VERSION
CC_LD: lld-$LLVM_VERSION
CXX: clang++-$LLVM_VERSION
CXX_LD: lld-$LLVM_VERSION
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
# Extends the core build templates to also provide for running our testing. We
@ -293,8 +282,17 @@ aarch64-debian-container_prep:
extends:
- .default-rules
script:
"${CI_PROJECT_DIR}/.gitlab-ci/build-and-test.sh"
- cd "$BUILDDIR"
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
- ninja install
- test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
- virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
- TEST_RES=$(cat $TESTS_RES_PATH)
- rm $TESTS_RES_PATH
- cp -R /weston-virtme ./
- rm weston-virtme/${KERNEL_IMAGE}
- exit $TEST_RES
artifacts:
name: weston-$CI_COMMIT_SHA
when: always
@ -305,7 +303,7 @@ aarch64-debian-container_prep:
- $BUILDDIR/weston-virtme
- $PREFIX
reports:
junit: $BUILDDIR/meson-logs/testlog.junit.xml
junit: $BUILDDIR/meson-logs/testlog-junit.xml
# Same as above, but without running any tests.
.build-no-test:
@ -427,79 +425,67 @@ aarch64-debian-container_prep:
- job: aarch64-debian-container_prep
artifacts: false
# Full build (gcov + perfetto) used for testing under KVM.
# Full build, used for testing under KVM.
.build-options-full:
stage: "Full build and test"
variables:
MESON_OPTIONS: >
-Doptimization=0
-Db_coverage=true
--force-fallback-for=perfetto
-Dperfetto=true
-Dperfetto:werror=false
-Dwerror=true
-Dtest-skip-is-failure=true
after_script:
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
- ninja -C "$BUILDDIR" coverage-xml
# Full build, (without gcov and perfetto)
.build-options-full-v2:
stage: "Full build and test"
variables:
MESON_OPTIONS: >
-Doptimization=0
-Dwerror=true
-Dtest-skip-is-failure=true
x86_64-debian-lts-full-build:
extends:
- .test-env-debian-lts-x86_64
- .build-options-full
x86_64-debian-full-build:
extends:
- .test-env-debian-x86_64
- .build-options-full
artifacts:
reports:
coverage_report:
coverage_format: cobertura
path: $BUILDDIR/meson-logs/coverage.xml
x86_64-debian-full-build:
extends:
- .test-env-debian-x86_64
- .build-options-full-v2
aarch64-debian-lts-full-build:
extends:
- .test-env-debian-lts-aarch64
- .build-options-full-v2
- .build-options-full
aarch64-debian-full-build:
extends:
- .test-env-debian-aarch64
- .build-options-full-v2
- .build-options-full
x86_64-clang-debian-lts-full-build:
extends:
- .test-env-debian-lts-x86_64
- .build-with-clang
- .build-options-full-v2
- .build-options-full
x86_64-clang-debian-full-build:
extends:
- .test-env-debian-x86_64
- .build-with-clang
- .build-options-full-v2
- .build-options-full
aarch64-clang-debian-lts-full-build:
extends:
- .test-env-debian-lts-aarch64
- .build-with-clang
- .build-options-full-v2
- .build-options-full
aarch64-clang-debian-full-build:
extends:
- .test-env-debian-aarch64
- .build-with-clang
- .build-options-full-v2
- .build-options-full
# Docs should be invariant on all architectures, so we only do it on Debian
# x86-64.
@ -513,20 +499,9 @@ docs-build:
- .build-env-debian-x86_64
- .build-no-test
# Building without gl-renderer and/or vulkan-renderer, to make sure this keeps working.
.build-options-no-gl-no-vulkan:
stage: "No-GL/Vulkan build and test"
variables:
MESON_OPTIONS: >
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
-Drenderer-gl=false
-Drenderer-vulkan=false
-Dremoting=false
-Dpipewire=false
-Dwerror=true
# Building without gl-renderer, to make sure this keeps working.
.build-options-no-gl:
stage: "No-GL/Vulkan build and test"
stage: "No-GL build and test"
variables:
MESON_OPTIONS: >
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
@ -535,72 +510,51 @@ docs-build:
-Dpipewire=false
-Dwerror=true
.build-options-no-vulkan:
stage: "No-GL/Vulkan build and test"
variables:
MESON_OPTIONS: >
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
-Drenderer-vulkan=false
-Dremoting=false
-Dpipewire=false
-Dwerror=true
x86_64-debian-lts-no-gl-no-vulkan-build:
x86_64-debian-lts-no-gl-build:
extends:
- .test-env-debian-lts-x86_64
- .build-options-no-gl-no-vulkan
x86_64-debian-no-gl-no-vulkan-build:
extends:
- .test-env-debian-x86_64
- .build-options-no-gl-no-vulkan
armv7-debian-lts-no-gl-no-vulkan-build:
extends:
- .build-env-debian-lts-armv7
- .build-no-test
- .build-options-no-gl-no-vulkan
armv7-debian-no-gl-no-vulkan-build:
extends:
- .build-env-debian-armv7
- .build-no-test
- .build-options-no-gl-no-vulkan
armv7-clang-debian-lts-no-gl-no-vulkan-build:
extends:
- .build-env-debian-lts-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl-no-vulkan
armv7-clang-debian-no-gl-no-vulkan-build:
extends:
- .build-env-debian-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl-no-vulkan
aarch64-debian-lts-no-gl-no-vulkan-build:
extends:
- .test-env-debian-lts-aarch64
- .build-options-no-gl-no-vulkan
aarch64-debian-no-gl-no-vulkan-build:
extends:
- .test-env-debian-aarch64
- .build-options-no-gl-no-vulkan
- .build-options-no-gl
x86_64-debian-no-gl-build:
extends:
- .test-env-debian-x86_64
- .build-options-no-gl
x86_64-debian-no-vulkan-build:
armv7-debian-lts-no-gl-build:
extends:
- .test-env-debian-x86_64
- .build-options-no-vulkan
- .build-env-debian-lts-armv7
- .build-no-test
- .build-options-no-gl
armv7-debian-no-gl-build:
extends:
- .build-env-debian-armv7
- .build-no-test
- .build-options-no-gl
armv7-clang-debian-lts-no-gl-build:
extends:
- .build-env-debian-lts-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl
armv7-clang-debian-no-gl-build:
extends:
- .build-env-debian-armv7
- .build-with-clang
- .build-no-test
- .build-options-no-gl
aarch64-debian-lts-no-gl-build:
extends:
- .test-env-debian-lts-aarch64
- .build-options-no-gl
aarch64-debian-no-gl-build:
extends:
- .test-env-debian-aarch64
- .build-options-no-gl
# Expose docs and coverage reports, so we can show users any changes to these
# inside their merge requests, letting us check them before merge.
@ -612,18 +566,18 @@ x86_64-debian-no-vulkan-build:
docs-and-coverage:
extends:
- .default-rules
- .debian-lts-x86_64
- .debian-x86_64
- .fdo.suffixed-image@debian
stage: pages
needs:
- job: docs-build
artifacts: true
- job: x86_64-debian-lts-full-build
- job: x86_64-debian-full-build
artifacts: true
timeout: 5m
script:
- mv prefix-weston-docs-build/share/doc/weston Documentation
- mv build-weston-x86_64-debian-lts-full-build/meson-logs/coveragereport Test_Coverage
- mv build-weston-x86_64-debian-full-build/meson-logs/coveragereport Test_Coverage
- rm Test_Coverage/gcov.css
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
- cp doc/style/*.png Test_Coverage/

View file

@ -1,29 +0,0 @@
#!/bin/bash
source "${FDO_CI_BASH_HELPERS}"
fdo_log_section_start_collapsed build_weston "build_weston"
cd "$BUILDDIR"
meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
ninja install
if [ "$CI_JOB_NAME" == "x86_64-debian-full-build" ]; then
cd "$BUILDDIR_WESTINY"
export NPREFIX=$CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
export PKG_CONFIG_PATH=$NPREFIX/lib/pkgconfig/:$NPREFIX/share/pkgconfig/:$NPREFIX/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
meson setup --prefix="$PREFIX_WESTINY" --wrap-mode=nofallback ../westinyplus/
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
ninja install
ninja clean
cd -
fi
fdo_log_section_end build_weston
test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
TEST_RES=$(cat $TESTS_RES_PATH)
rm $TESTS_RES_PATH
cp -R /weston-virtme ./
rm weston-virtme/${KERNEL_IMAGE}
exit $TEST_RES

View file

@ -4,8 +4,6 @@
# .gitlab-ci.yml for more information. This script is called from an
# OS-specific build scripts like debian-install.sh.
source "${FDO_CI_BASH_HELPERS}"
set -o xtrace -o errexit
# Set concurrency to an appropriate level for our shared runners, falling back
@ -27,8 +25,7 @@ esac
# Build and install Meson. Generally we want to keep this in sync with what
# we require inside meson.build.
fdo_log_section_start_collapsed install_meson "install_meson"
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.4.2
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.0.0
export PATH=$HOME/.local/bin:$PATH
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
@ -44,22 +41,31 @@ pip3 install $PIP_ARGS sphinxcontrib-qthelp==1.0.3
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
pip3 install $PIP_ARGS breathe==4.31.0
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
fdo_log_section_end install_meson
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
# predictably test the DRM backend in the absence of real hardware. We lock the
# version here so we see predictable results.
#
# To run this we use virtme-ng, a QEMU wrapper. It is a fork from virtme, whose
# development stalled.
# To run this we use virtme, a QEMU wrapper: https://github.com/amluto/virtme
#
# virtme-ng makes our lives easier by abstracting handling of the console,
# virtme makes our lives easier by abstracting handling of the console,
# filesystem, etc, so we can pretend that the VM we execute in is actually
# just a regular container.
fdo_log_section_start_collapsed install_kernel "install_kernel"
#
# The reason why we are using a fork here is that it adds a patch to have the
# --script-dir command line option. With that we can run scripts that are in a
# certain folder when virtme starts, which is necessary in our use case.
#
# The upstream also has some commands that could help us to reach the same
# results: --script-sh and --script-exec. Unfornutately they are not completely
# implemented yet, so we had some trouble to use them and it was becoming
# hackery.
#
# The fork pulls in this support from the original GitHub PR, rebased on top of
# a newer upstream version which fixes AArch64 support.
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
git clone --depth=1 --branch=v6.18 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
# 6.3 is (still) used as >= 6.5 drm-writeback test will timeout
git clone --depth=1 --branch=v6.3 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
cd linux
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
@ -85,8 +91,9 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
./scripts/config \
--enable CONFIG_DRM \
--enable CONFIG_DRM_KMS_HELPER \
--enable CONFIG_DRM_KMS_FB_HELPER \
--enable CONFIG_DRM_VKMS \
--enable CONFIG_UDMABUF
--enable CONFIG_DRM_VGEM
make ARCH=${LINUX_ARCH} oldconfig
make ARCH=${LINUX_ARCH}
@ -101,15 +108,14 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
./setup.py install
cd ..
fi
fdo_log_section_end install_kernel
# Build and install Wayland; keep this version in sync with our dependency
# in meson.build.
fdo_log_section_start_collapsed install_wayland "install_wayland"
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
cd wayland
git show -s HEAD
meson setup build --wrap-mode=nofallback -Ddocumentation=false
mkdir build
meson build --wrap-mode=nofallback -Ddocumentation=false
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf wayland
@ -117,39 +123,24 @@ 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.46 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
git clone --branch 1.33 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
cd wayland-protocols
git show -s HEAD
meson setup build --wrap-mode=nofallback -Dtests=false
meson build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf wayland-protocols
fdo_log_section_end install_wayland
# 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, and Mesa
# depends on 2.4.109 as well.
# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30}
fdo_log_section_start_collapsed install_libdrm "install_libdrm"
git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
git clone --branch libdrm-2.4.109 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
cd drm
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
-Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled
meson build --wrap-mode=nofallback -Dauto_features=disabled \
-Dvc4=false -Dfreedreno=false -Detnaviv=false
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf drm
fdo_log_section_end install_libdrm
# Build and install Vulkan-Headers with a defined version, mostly because
# the version in Debian 11 (bullseye) is too old to build vulkan-renderer.
fdo_log_section_start_collapsed install_vulkan_headers "install_vulkan_headers"
git clone --branch sdk-1.3.239.0 --depth=1 https://github.com/KhronosGroup/Vulkan-Headers
cd Vulkan-Headers
cmake -G Ninja -B build
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf Vulkan-Headers
fdo_log_section_end install_vulkan_headers
# Build and install our own version of Mesa. Debian provides a perfectly usable
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
@ -158,89 +149,64 @@ fdo_log_section_end install_vulkan_headers
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
# please be prepared for some of the tests to change output, which will need to
# be manually inspected for correctness.
fdo_log_section_start_collapsed install_mesa "install_mesa"
# Needed for Mesa >= 25.3
git clone --branch 12.2.0 --depth=1 https://github.com/KhronosGroup/glslang
cd glslang
cmake -G Ninja -B build
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf glslang
# The 25.3 was the first stable release where the Vulkan backend works with
# vkms+lavapipe.
git clone --branch mesa-25.3.2 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
git clone --branch 23.0 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
cd mesa
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
-Dgallium-drivers=llvmpipe -Dvulkan-drivers=swrast -Dvideo-codecs= \
-Degl=enabled -Dgbm=enabled -Dgles2=enabled -Dllvm=enabled \
-Dshared-glapi=enabled -Dglx=disabled
meson build --wrap-mode=nofallback -Dauto_features=disabled \
-Dgallium-drivers=swrast -Dvulkan-drivers= -Ddri-drivers=
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf mesa
fdo_log_section_end install_mesa
# 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.
#
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
fdo_log_section_start_collapsed install_pipewire "install_pipewire"
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
cd pipewire-src
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
meson setup build --wrap-mode=nofallback
meson build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf pipewire-src
fdo_log_section_end install_pipewire
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
# We use this for our tests using the DRM backend.
fdo_log_section_start_collapsed install_seatd "install_seatd"
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
cd seatd
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
meson build --wrap-mode=nofallback -Dauto_features=disabled \
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf seatd
fdo_log_section_end install_seatd
# Build and install aml and neatvnc, which are required for the VNC backend
fdo_log_section_start_collapsed install_aml_neatvnc "install_aml_neatvnc"
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
cd aml
meson setup build --wrap-mode=nofallback
meson build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf aml
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
cd neatvnc
meson setup build --wrap-mode=nofallback -Dauto_features=disabled
meson build --wrap-mode=nofallback -Dauto_features=disabled
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf neatvnc
fdo_log_section_end install_aml_neatvnc
# Build and install libdisplay-info, used by drm-backend
fdo_log_section_start_collapsed install_libdisplay-info "install_libdisplay-info"
git clone --branch 0.2.0 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
git clone --branch 0.1.1 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
cd libdisplay-info
meson setup build --wrap-mode=nofallback
meson build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf libdisplay-info
fdo_log_section_end install_libdisplay-info
# Build and install lcms2, which we use to support color-management.
fdo_log_section_start_collapsed install_lcms2 "install_lcms2"
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
cd lcms2
git checkout -b snapshot lcms2.16
meson setup build --wrap-mode=nofallback
meson build --wrap-mode=nofallback
ninja ${NINJAFLAGS} -C build install
cd ..
rm -rf lcms2
fdo_log_section_end install_lcms2

View file

@ -26,22 +26,14 @@ MESA_DEV_PKGS="
python3-mako
"
# These get temporarily installed for other build dependencies and then
# force-removed.
# cmake is used by Vulkan-Headers
BUILD_DEV_PKGS="
cmake
"
# Needed for running the custom-built mesa
MESA_RUNTIME_PKGS="
libllvm${LLVM_VERSION}
"
if [ x"$USE_DEBIAN_BACKPORTS" = "xy" ] ; then
echo 'deb http://deb.debian.org/debian '${FDO_DISTRIBUTION_VERSION}'-backports main' >> /etc/apt/sources.list
if [ x"$USE_BOOKWORM_BACKPORTS" = "xy" ] ; then
echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
fi
apt-get update
apt-get -y --no-install-recommends install \
autoconf \
@ -53,7 +45,6 @@ apt-get -y --no-install-recommends install \
graphviz \
gcovr \
git \
glslang-tools \
hwdata \
lcov \
libasound2-dev \
@ -68,7 +59,7 @@ apt-get -y --no-install-recommends install \
libexpat1-dev \
libffi-dev \
libgbm-dev \
libgdk-pixbuf-xlib-2.0-dev \
libgdk-pixbuf2.0-dev \
libgles2-mesa-dev \
libglu1-mesa-dev \
libgstreamer1.0-dev \
@ -77,7 +68,6 @@ apt-get -y --no-install-recommends install \
libjack-jackd2-dev \
libjpeg-dev \
libjpeg-dev \
liblua5.4-dev \
libmtdev-dev \
libpam0g-dev \
libpango1.0-dev \
@ -132,9 +122,7 @@ apt-get -y --no-install-recommends install \
cargo rustc \
iproute2 udev \
$MESA_DEV_PKGS \
$BUILD_DEV_PKGS \
$MESA_RUNTIME_PKGS \
$PACKAGES_SPECIFIC \
$LINUX_DEV_PKGS \
if [ "$FREERDP_VERSION" -ne 0 ] ; then
@ -147,4 +135,4 @@ fi
# And remove packages which are only required for our build dependencies,
# which we don't need bloating the image whilst we build and run Weston.
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS $BUILD_DEV_PKGS
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS

View file

@ -11,16 +11,3 @@ leak:wl_shm_buffer_begin_access
leak:g_malloc0
leak:sysprof_collector_get
leak:/ld-*.so*
# Add all of perfetto, since it's not easy to clean up after it
leak:perfetto
# lavapipe inexplicably leaks when Vulkan physical devices are enumerated,
# despite us a) not using that device and b) freeing the instance. This is
# apparently a known issue. (Also when ASan creates threads ...)
leak:vkEnumeratePhysicalDevices
leak:asan_thread_start
# glib/pangoft for Trixie update
leak:libpangoft2
leak:libglib

View file

@ -12,7 +12,10 @@ export LIBSEAT_BACKEND=seatd
# 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/bus/faux/devices/vkms/drm/card*)
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).
@ -23,11 +26,11 @@ export HOME=/root
export PATH=$HOME/.local/bin:$PATH
export PATH=/usr/local/bin:$PATH
export SEATD_LOGLEVEL=debug
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
# llvmpipe/lavapipe driver module location
export WESTON_CI_LEAK_DL_HANDLES=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true):
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libvulkan_lvp.so -print 2>/dev/null || true)
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libgallium\*.so -print 2>/dev/null || true)
# 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

View file

@ -117,11 +117,11 @@ finish_calibration (struct calibrator *calibrator)
*/
memset(&m, 0, sizeof(m));
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
m.M.col[0].el[i] = calibrator->tests[i].clicked_x;
m.M.col[1].el[i] = calibrator->tests[i].clicked_y;
m.M.col[2].el[i] = 1;
m.d[i] = calibrator->tests[i].clicked_x;
m.d[i + 4] = calibrator->tests[i].clicked_y;
m.d[i + 8] = 1;
}
m.M.col[3].el[3] = 1;
m.d[15] = 1;
weston_matrix_invert(&inverse, &m);
@ -129,8 +129,8 @@ finish_calibration (struct calibrator *calibrator)
memset(&y_calib, 0, sizeof(y_calib));
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
x_calib.v.el[i] = calibrator->tests[i].drawn_x;
y_calib.v.el[i] = calibrator->tests[i].drawn_y;
x_calib.f[i] = calibrator->tests[i].drawn_x;
y_calib.f[i] = calibrator->tests[i].drawn_y;
}
/* Multiples into the vector */
@ -138,8 +138,8 @@ finish_calibration (struct calibrator *calibrator)
weston_matrix_transform(&inverse, &y_calib);
printf ("Calibration values: %f %f %f %f %f %f\n",
x_calib.v.el[0], x_calib.v.el[1], x_calib.v.el[2],
y_calib.v.el[0], y_calib.v.el[1], y_calib.v.el[2]);
x_calib.f[0], x_calib.f[1], x_calib.f[2],
y_calib.f[0], y_calib.f[1], y_calib.f[2]);
exit(0);
}

View file

@ -1,584 +0,0 @@
/*
* Copyright (C) 2024 SUSE Software Solutions Germany GmbH
*
* 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 <assert.h>
#include <errno.h>
#include "color-management-v1-client-protocol.h"
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "window.h"
enum image_description_status {
IMAGE_DESCRIPTION_NOT_CREATED = 0,
IMAGE_DESCRIPTION_READY,
IMAGE_DESCRIPTION_FAILED,
};
struct pixel_color {
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
};
struct color {
struct display *display;
struct window *window;
struct widget *parent_widget;
struct widget *widget;
struct wp_color_manager_v1 *color_manager;
struct wp_color_management_surface_v1 *color_surface;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
struct wp_viewporter *viewporter;
struct wp_viewport *viewport;
struct pixel_color pixel_color;
enum wp_color_manager_v1_primaries primaries;
enum wp_color_manager_v1_transfer_function transfer_function;
float min_lum;
float max_lum;
float ref_lum;
uint32_t supported_color_features;
uint32_t supported_rendering_intents;
uint32_t supported_primaries_named;
uint32_t supported_tf_named;
};
struct valid_enum {
const char *name;
uint32_t value;
};
static bool opt_help = false;
static uint32_t opt_width = 250;
static uint32_t opt_height = 250;
static const char *opt_r = NULL;
static const char *opt_g = NULL;
static const char *opt_b = NULL;
static const char *opt_a = NULL;
static const char *opt_primaries = NULL;
static const char *opt_transfer_function = NULL;
static const char *opt_min_lum = NULL;
static const char *opt_max_lum = NULL;
static const char *opt_ref_lum = NULL;
static const struct weston_option cli_options[] = {
{ WESTON_OPTION_BOOLEAN, "help", 0, &opt_help },
{ WESTON_OPTION_UNSIGNED_INTEGER, "width", 'w', &opt_width },
{ WESTON_OPTION_UNSIGNED_INTEGER, "height", 'h', &opt_height },
{ WESTON_OPTION_STRING, 0, 'R', &opt_r },
{ WESTON_OPTION_STRING, 0, 'G', &opt_g },
{ WESTON_OPTION_STRING, 0, 'B', &opt_b },
{ WESTON_OPTION_STRING, 0, 'A', &opt_a },
{ WESTON_OPTION_STRING, "primaries", 'p', &opt_primaries },
{ WESTON_OPTION_STRING, "transfer-function", 't', &opt_transfer_function },
{ WESTON_OPTION_STRING, "min-lum", 'm', &opt_min_lum },
{ WESTON_OPTION_STRING, "max-lum", 'M', &opt_max_lum },
{ WESTON_OPTION_STRING, "ref-lum", 'r', &opt_ref_lum },
};
static const struct valid_enum valid_primaries[] = {
{ "srgb", WP_COLOR_MANAGER_V1_PRIMARIES_SRGB },
{ "bt2020", WP_COLOR_MANAGER_V1_PRIMARIES_BT2020 },
};
static const struct valid_enum valid_transfer_functions[] = {
{ "srgb", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB },
{ "pq", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ },
{ "linear", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR },
};
static bool
validate_color(const char *c, uint32_t *dest, uint32_t fallback)
{
char *end;
double value;
if (!c) {
*dest = fallback;
return true;
}
value = strtod(c, &end);
if (value < 0.0 || value > 1.0 || *end != '\0') {
fprintf(stderr, "Validating color failed, it should be between 0.0 and 1.0\n");
return false;
}
*dest = value * UINT32_MAX;
return true;
}
static bool
validate_option(const char *option, uint32_t *dest,
const struct valid_enum *valid_options,
int count, uint32_t fallback)
{
int i;
if (!option) {
*dest = fallback;
return true;
}
for (i = 0; i < count; i++) {
if (strcmp(valid_options[i].name, option) == 0) {
*dest = valid_options[i].value;
return true;
}
}
fprintf(stderr, "Validating option '%s' failed, valid options:\n", option);
for (i = 0; i < count; i++)
fprintf(stderr, "'%s' ", valid_options[i].name);
fprintf(stderr, "\n");
return false;
}
static bool
validate_luminance(const char *c, float *dest, float fallback)
{
char *end;
float value;
if (!c) {
*dest = fallback;
return true;
}
value = strtof(c, &end);
if (value < 0.f || value > 10000.f || *end != '\0') {
fprintf(stderr, "Validating luminance failed, it should be between 0 and 10,000\n");
return false;
}
*dest = value;
return true;
}
static bool
validate_options(struct color *color)
{
return validate_color(opt_r, &color->pixel_color.r, 0) &&
validate_color(opt_g, &color->pixel_color.g, 0) &&
validate_color(opt_b, &color->pixel_color.b, 0) &&
validate_color(opt_a, &color->pixel_color.a, UINT32_MAX) &&
validate_option(opt_primaries, &color->primaries,
valid_primaries,
ARRAY_LENGTH(valid_primaries),
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
validate_option(opt_transfer_function, &color->transfer_function,
valid_transfer_functions,
ARRAY_LENGTH(valid_transfer_functions),
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
validate_luminance(opt_min_lum, &color->min_lum, -1.f) &&
validate_luminance(opt_max_lum, &color->max_lum, -1.f) &&
validate_luminance(opt_ref_lum, &color->ref_lum, -1.f);
}
static void
usage(const char *program_name, int exit_code)
{
unsigned int i;
fprintf(stderr, "Usage: %s [OPTIONS]\n", program_name);
fprintf(stderr, " --help\n");
fprintf(stderr, " --width or -w\n");
fprintf(stderr, " --height or -h\n");
fprintf(stderr, " -R (0.0 to 1.0)\n");
fprintf(stderr, " -G (0.0 to 1.0)\n");
fprintf(stderr, " -B (0.0 to 1.0)\n");
fprintf(stderr, " -A (0.0 to 1.0)\n");
fprintf(stderr, " --primaries or -p:");
fprintf(stderr, "\n ");
for (i = 0; i < ARRAY_LENGTH(valid_primaries); i++)
fprintf(stderr, " '%s'", valid_primaries[i].name);
fprintf(stderr, "\n");
fprintf(stderr, " --transfer-function or -t:");
fprintf(stderr, "\n ");
for (i = 0; i < ARRAY_LENGTH(valid_transfer_functions); i++)
fprintf(stderr, " '%s'", valid_transfer_functions[i].name);
fprintf(stderr, "\n");
fprintf(stderr, " --min-lum or -m (0.0 to 10000.0)\n");
fprintf(stderr, " --max-lum or -M (0.0 to 10000.0)\n");
fprintf(stderr, " --ref-lum or -r (0.0 to 10000.0)\n");
exit(exit_code);
}
static void
supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t render_intent)
{
struct color *color = data;
color->supported_rendering_intents |= 1 << render_intent;
}
static void
supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t feature)
{
struct color *color = data;
color->supported_color_features |= 1 << feature;
}
static void
supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t tf)
{
struct color *color = data;
color->supported_tf_named |= 1 << tf;
}
static void
supported_primaries_named(void *data,
struct wp_color_manager_v1 *wp_color_manager_v1,
uint32_t primaries)
{
struct color *color = data;
color->supported_primaries_named |= 1 << primaries;
}
static void
done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
{
}
static const struct wp_color_manager_v1_listener color_manager_listener = {
supported_intent,
supported_feature,
supported_tf_named,
supported_primaries_named,
done,
};
static void
global_handler(struct display *display, uint32_t name,
const char *interface, uint32_t version, void *data)
{
struct color *color = data;
struct wl_surface *surface = widget_get_wl_surface(color->widget);
if (strcmp(interface, wp_color_manager_v1_interface.name) == 0) {
color->color_manager = display_bind(display, name,
&wp_color_manager_v1_interface, 1);
color->color_surface = wp_color_manager_v1_get_surface(color->color_manager,
surface);
wp_color_manager_v1_add_listener(color->color_manager,
&color_manager_listener, color);
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
color->single_pixel_manager =
display_bind(display, name,
&wp_single_pixel_buffer_manager_v1_interface, 1);
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
color->viewporter = display_bind(display, name,
&wp_viewporter_interface, 1);
color->viewport = wp_viewporter_get_viewport(color->viewporter, surface);
}
}
static bool
check_color_requirements(struct color *color)
{
if (!color->color_manager) {
fprintf(stderr, "The compositor doesn't expose %s\n",
wp_color_manager_v1_interface.name);
return false;
}
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC))) {
fprintf(stderr, "The color manager doesn't support the parametric creator\n");
return false;
}
if (!(color->supported_primaries_named & (1 << color->primaries))) {
fprintf(stderr, "The color manager doesn't support the primaries name\n");
return false;
}
if (!(color->supported_tf_named & (1 << color->transfer_function))) {
fprintf(stderr, "The color manager doesn't support the transfer function\n");
return false;
}
if (!(color->supported_rendering_intents & (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL))) {
fprintf(stderr, "The color manager doesn't support perceptual render intent\n");
return false;
}
if (color->min_lum != -1.f || color->max_lum != -1.f || color->ref_lum != -1.f) {
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES))) {
fprintf(stderr, "The color manager doesn't support setting luminances\n");
return false;
}
if (color->min_lum == -1.f || color->max_lum == -1.f || color->ref_lum == -1.f) {
fprintf(stderr, "To set the luminances it is required min-lum, max-lum and ref-lum\n");
return false;
}
}
return true;
}
static void
color_destroy(struct color *color)
{
if (color->color_surface)
wp_color_management_surface_v1_destroy(color->color_surface);
if (color->color_manager)
wp_color_manager_v1_destroy(color->color_manager);
if (color->single_pixel_manager)
wp_single_pixel_buffer_manager_v1_destroy(color->single_pixel_manager);
if (color->viewport)
wp_viewport_destroy(color->viewport);
if (color->viewporter)
wp_viewporter_destroy(color->viewporter);
if (color->widget)
widget_destroy(color->widget);
if (color->parent_widget)
widget_destroy(color->parent_widget);
if (color->window)
window_destroy(color->window);
if (color->display)
display_destroy(color->display);
free(color);
}
static void
resize_handler(struct widget *parent_widget, int32_t width, int32_t height, void *data)
{
struct color *color = data;
struct rectangle allocation;
struct wl_surface *surface = widget_get_wl_surface(color->widget);
struct wl_subsurface *subsurface = widget_get_wl_subsurface(color->widget);
widget_get_allocation(parent_widget, &allocation);
wl_subsurface_set_position(subsurface, allocation.x, allocation.y);
wp_viewport_set_destination(color->viewport, width, height);
wl_surface_commit(surface);
}
static void
set_empty_input_region(struct color *color, struct widget *widget)
{
struct wl_region *region;
struct wl_compositor *compositor;
struct wl_surface *surface = widget_get_wl_surface(widget);
compositor = display_get_compositor(color->display);
region = wl_compositor_create_region(compositor);
wl_surface_set_input_region(surface, region);
wl_region_destroy(region);
}
static void
buffer_release(void *data, struct wl_buffer *buffer)
{
wl_buffer_destroy(buffer);
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
static void
set_single_pixel(struct color *color, struct widget *widget)
{
struct wl_surface *surface = widget_get_wl_surface(widget);
struct wl_buffer *buffer =
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(color->single_pixel_manager,
color->pixel_color.r,
color->pixel_color.g,
color->pixel_color.b,
color->pixel_color.a);
wl_buffer_add_listener(buffer, &buffer_listener, NULL);
wl_surface_attach(surface, buffer, 0, 0);
}
static void
image_description_failed(void *data,
struct wp_image_description_v1 *wp_image_description_v1,
uint32_t cause, const char *msg)
{
enum image_description_status *image_desc_status = data;
fprintf(stderr, "Failed to create image description: %u - %s\n",
cause, msg);
*image_desc_status = IMAGE_DESCRIPTION_FAILED;
}
static void
image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
uint32_t identity)
{
enum image_description_status *image_desc_status = data;
*image_desc_status = IMAGE_DESCRIPTION_READY;
}
static const struct wp_image_description_v1_listener image_description_listener = {
image_description_failed,
image_description_ready,
};
static struct wp_image_description_v1 *
create_image_description(struct color *color, uint32_t primaries_named, uint32_t tf_named)
{
struct wp_image_description_creator_params_v1 *params_creator;
struct wp_image_description_v1 *image_description;
enum image_description_status image_desc_status = IMAGE_DESCRIPTION_NOT_CREATED;
int ret = 0;
params_creator = wp_color_manager_v1_create_parametric_creator(color->color_manager);
wp_image_description_creator_params_v1_set_primaries_named(params_creator, primaries_named);
wp_image_description_creator_params_v1_set_tf_named(params_creator, tf_named);
if (color->min_lum != -1 && color->max_lum != -1 && color->ref_lum != -1)
wp_image_description_creator_params_v1_set_luminances(params_creator,
color->min_lum * 10000,
color->max_lum,
color->ref_lum);
image_description = wp_image_description_creator_params_v1_create(params_creator);
wp_image_description_v1_add_listener(image_description,
&image_description_listener,
&image_desc_status);
while (ret != -1 && image_desc_status == IMAGE_DESCRIPTION_NOT_CREATED)
ret = wl_display_dispatch(display_get_display(color->display));
if (ret == -1) {
wp_image_description_v1_destroy(image_description);
fprintf(stderr, "Error when creating the image description: %s\n", strerror(errno));
return NULL;
}
if (image_desc_status == IMAGE_DESCRIPTION_FAILED) {
wp_image_description_v1_destroy(image_description);
return NULL;
}
assert(image_desc_status == IMAGE_DESCRIPTION_READY);
return image_description;
}
static bool
set_image_description(struct color *color, struct widget *widget)
{
struct wp_image_description_v1 *image_description;
image_description =
create_image_description(color,
color->primaries,
color->transfer_function);
if (!image_description)
return false;
wp_color_management_surface_v1_set_image_description(
color->color_surface,
image_description,
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
wp_image_description_v1_destroy(image_description);
return true;
}
int
main(int argc, char *argv[])
{
struct color *color;
if (parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv) > 1)
usage(argv[0], EXIT_FAILURE);
if (opt_help)
usage(argv[0], EXIT_SUCCESS);
color = xzalloc(sizeof *color);
if (!validate_options(color)) {
color_destroy(color);
exit(EXIT_FAILURE);
}
color->display = display_create(&argc, argv);
if (!color->display) {
color_destroy(color);
exit(EXIT_FAILURE);
}
color->window = window_create(color->display);
color->parent_widget = window_frame_create(color->window, color);
color->widget = window_add_subsurface(color->window, color, SUBSURFACE_SYNCHRONIZED);
display_set_user_data(color->display, color);
display_set_global_handler(color->display, global_handler);
wl_display_roundtrip(display_get_display(color->display));
if (!check_color_requirements(color)) {
color_destroy(color);
exit(EXIT_SUCCESS);
}
window_unset_shadow(color->window);
window_set_title(color->window, "Color");
window_set_appid(color->window, "org.freedesktop.weston.color");
/* The first resize call sets the min size,
* setting 0, 0 sets a default size */
window_schedule_resize(color->window, 0, 0);
window_schedule_resize(color->window, opt_width, opt_height);
widget_set_resize_handler(color->parent_widget, resize_handler);
widget_set_use_cairo(color->widget, 0);
set_empty_input_region(color, color->widget);
set_single_pixel(color, color->widget);
if (set_image_description(color, color->widget))
display_run(color->display);
color_destroy(color);
return 0;
}

View file

@ -53,7 +53,6 @@
#include "window.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h"
#include "weston-desktop-shell-client-protocol.h"
@ -778,148 +777,95 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path, cons
enum {
BACKGROUND_SCALE,
BACKGROUND_SCALE_CROP,
BACKGROUND_SCALE_FIT,
BACKGROUND_TILE,
BACKGROUND_CENTERED
};
static void
buffer_release(void *data, struct wl_buffer *buffer)
{
wl_buffer_destroy(buffer);
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
static void
background_draw(struct widget *widget, void *data)
{
struct background *background = data;
cairo_surface_t *surface, *image;
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
cairo_t *cr;
double im_w, im_h;
double sx, sy, s;
double tx, ty;
struct rectangle allocation;
if (!background->image && background->color) {
struct display *display = window_get_display(background->window);
struct wp_single_pixel_buffer_manager_v1 *sp_manager;
struct wl_surface *wl_surface;
struct wl_buffer *wl_buffer;
uint32_t r8, g8, b8;
uint32_t r32, g32, b32;
surface = window_get_surface(background->window);
/* Single pixel buffer must use scale 1 */
window_set_buffer_scale(background->window, 1);
cr = widget_cairo_create(background->widget);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
if (background->color == 0)
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
else
set_hex_color(cr, background->color);
cairo_paint(cr);
sp_manager = display_get_single_pixel_buffer_manager(display);
assert(sp_manager);
wl_surface = widget_get_wl_surface(background->widget);
assert(wl_surface);
widget_get_allocation(widget, &allocation);
image = NULL;
if (background->image)
image = load_cairo_surface(background->image);
else if (background->color == 0) {
char *name = file_name_with_datadir("pattern.png");
r8 = (background->color >> 16) & 0xff;
g8 = (background->color >> 8) & 0xff;
b8 = (background->color >> 0) & 0xff;
r32 = r8 << 24 | r8 << 16 | r8 << 8 | r8;
g32 = g8 << 24 | g8 << 16 | g8 << 8 | g8;
b32 = b8 << 24 | b8 << 16 | b8 << 8 | b8;
wl_buffer =
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(sp_manager,
r32,
g32,
b32,
0xffffffff);
assert(wl_buffer);
wl_surface_attach(wl_surface, wl_buffer, 0, 0);
wl_buffer_add_listener(wl_buffer, &buffer_listener, NULL);
widget_surface_flush(widget);
} else {
cairo_surface_t *surface, *image;
cairo_pattern_t *pattern;
cairo_matrix_t matrix;
cairo_t *cr;
double im_w, im_h;
double sx, sy, s;
double tx, ty;
struct rectangle allocation;
surface = window_get_surface(background->window);
cr = widget_cairo_create(background->widget);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
if (background->color == 0)
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
else
set_hex_color(cr, background->color);
cairo_paint(cr);
widget_get_allocation(widget, &allocation);
image = NULL;
if (background->image)
image = load_cairo_surface(background->image);
else if (background->color == 0) {
char *name = file_name_with_datadir("pattern.png");
image = load_cairo_surface(name);
free(name);
}
if (image && background->type != -1) {
im_w = cairo_image_surface_get_width(image);
im_h = cairo_image_surface_get_height(image);
sx = im_w / allocation.width;
sy = im_h / allocation.height;
pattern = cairo_pattern_create_for_surface(image);
switch (background->type) {
case BACKGROUND_SCALE:
cairo_matrix_init_scale(&matrix, sx, sy);
cairo_pattern_set_matrix(pattern, &matrix);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
break;
case BACKGROUND_SCALE_CROP:
case BACKGROUND_SCALE_FIT:
if (background->type == BACKGROUND_SCALE_CROP)
s = (sx < sy) ? sx : sy;
else
s = (sx > sy) ? sx : sy;
/* align center */
tx = (im_w - s * allocation.width) * 0.5;
ty = (im_h - s * allocation.height) * 0.5;
cairo_matrix_init_translate(&matrix, tx, ty);
cairo_matrix_scale(&matrix, s, s);
cairo_pattern_set_matrix(pattern, &matrix);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
break;
case BACKGROUND_TILE:
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
break;
case BACKGROUND_CENTERED:
s = (sx < sy) ? sx : sy;
if (s < 1.0)
s = 1.0;
/* align center */
tx = (im_w - s * allocation.width) * 0.5;
ty = (im_h - s * allocation.height) * 0.5;
cairo_matrix_init_translate(&matrix, tx, ty);
cairo_matrix_scale(&matrix, s, s);
cairo_pattern_set_matrix(pattern, &matrix);
break;
}
cairo_set_source(cr, pattern);
cairo_pattern_destroy (pattern);
cairo_surface_destroy(image);
cairo_mask(cr, pattern);
}
cairo_destroy(cr);
cairo_surface_destroy(surface);
image = load_cairo_surface(name);
free(name);
}
if (image && background->type != -1) {
im_w = cairo_image_surface_get_width(image);
im_h = cairo_image_surface_get_height(image);
sx = im_w / allocation.width;
sy = im_h / allocation.height;
pattern = cairo_pattern_create_for_surface(image);
switch (background->type) {
case BACKGROUND_SCALE:
cairo_matrix_init_scale(&matrix, sx, sy);
cairo_pattern_set_matrix(pattern, &matrix);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
break;
case BACKGROUND_SCALE_CROP:
s = (sx < sy) ? sx : sy;
/* align center */
tx = (im_w - s * allocation.width) * 0.5;
ty = (im_h - s * allocation.height) * 0.5;
cairo_matrix_init_translate(&matrix, tx, ty);
cairo_matrix_scale(&matrix, s, s);
cairo_pattern_set_matrix(pattern, &matrix);
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
break;
case BACKGROUND_TILE:
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
break;
case BACKGROUND_CENTERED:
s = (sx < sy) ? sx : sy;
if (s < 1.0)
s = 1.0;
/* align center */
tx = (im_w - s * allocation.width) * 0.5;
ty = (im_h - s * allocation.height) * 0.5;
cairo_matrix_init_translate(&matrix, tx, ty);
cairo_matrix_scale(&matrix, s, s);
cairo_pattern_set_matrix(pattern, &matrix);
break;
}
cairo_set_source(cr, pattern);
cairo_pattern_destroy (pattern);
cairo_surface_destroy(image);
cairo_mask(cr, pattern);
}
cairo_destroy(cr);
cairo_surface_destroy(surface);
background->painted = 1;
check_desktop_ready(background->window);
}
@ -946,7 +892,6 @@ background_configure(void *data,
}
if (!background->image && background->color) {
widget_set_use_cairo(background->widget, 0);
widget_set_viewport_destination(background->widget, width, height);
width = 1;
height = 1;
@ -1246,10 +1191,6 @@ background_create(struct desktop *desktop, struct output *output)
weston_config_section_get_color(s, "background-color",
&background->color, 0x00000000);
/* Backgrounds must be fully opaque. */
if (background->color != 0)
background->color |= 0xFF000000;
weston_config_section_get_string(s, "background-type",
&type, "tile");
if (type == NULL) {
@ -1261,8 +1202,6 @@ background_create(struct desktop *desktop, struct output *output)
background->type = BACKGROUND_SCALE;
} else if (strcmp(type, "scale-crop") == 0) {
background->type = BACKGROUND_SCALE_CROP;
} else if (strcmp(type, "scale-fit") == 0) {
background->type = BACKGROUND_SCALE_FIT;
} else if (strcmp(type, "tile") == 0) {
background->type = BACKGROUND_TILE;
} else if (strcmp(type, "centered") == 0) {
@ -1382,11 +1321,10 @@ output_handle_scale(void *data,
int32_t scale)
{
struct output *output = data;
struct background *background = output->background;
if (output->panel)
window_set_buffer_scale(output->panel->window, scale);
if (background && !background->color)
if (output->background)
window_set_buffer_scale(output->background->window, scale);
}

View file

@ -515,7 +515,7 @@ create_drag_source(struct dnd *dnd,
dnd_drag->drag_surface =
wl_compositor_create_surface(compositor);
if (dnd->self_only || display_get_data_device_manager_version(display) <
if (display_get_data_device_manager_version(display) <
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
/* Data sources version < 3 will not get action
* nor dnd_finished events, as we can't honor
@ -546,11 +546,11 @@ create_drag_source(struct dnd *dnd,
flower_mime_type);
wl_data_source_offer(dnd_drag->data_source,
text_mime_type);
}
if (display_get_data_device_manager_version(display) >=
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
wl_data_source_set_actions(dnd_drag->data_source, actions);
}
if (display_get_data_device_manager_version(display) >=
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
wl_data_source_set_actions(dnd_drag->data_source, actions);
}
wl_data_device_start_drag(input_get_data_device(input),

View file

@ -346,7 +346,6 @@ usage(int error_code)
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
" -w <width>\tSet window width to <width>\n"
" -h <height>\tSet window height to <height>\n"
" -f\t\tMap window as fullscreen\n"
" --help\tShow this help text\n\n");
exit(error_code);
@ -395,8 +394,6 @@ int main(int argc, char *argv[])
usage(EXIT_FAILURE);
fullscreen.height = atol(argv[i]);
} else if (strcmp(argv[i], "-f") == 0) {
fullscreen.fullscreen = 1;
} else if (strcmp(argv[i], "--help") == 0)
usage(EXIT_SUCCESS);
else
@ -437,8 +434,6 @@ int main(int argc, char *argv[])
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
window_set_user_data(fullscreen.window, &fullscreen);
if (fullscreen.fullscreen)
window_set_fullscreen(fullscreen.window, fullscreen.fullscreen);
/* Hack to set minimum allocation so we can shrink later */
window_schedule_resize(fullscreen.window,
1, 1);

View file

@ -143,8 +143,6 @@ hmi_homescreen_launcher {
uint32_t workspace_id;
char *icon;
char *path;
char **argv;
struct wl_list link;
};
@ -310,10 +308,12 @@ launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
struct hmi_homescreen_launcher *launcher = NULL;
wl_list_for_each(launcher, launcher_list, link) {
char *argv[] = { NULL };
if (surfaceId != launcher->icon_surface_id)
continue;
execute_process(launcher->path, launcher->argv);
execute_process(launcher->path, argv);
return 1;
}
@ -1065,32 +1065,6 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
free(launchers);
}
static char **
parse_command(char *str)
{
char **argv;
char *saveptr;
char *token;
int i;
int count = 1;
for (i = 1; str[i]; i++)
if (str[i] == ' ' && str[i-1] != ' ')
count++;
argv = xcalloc(count + 1, sizeof(char*));
i = 0;
token = strtok_r(str, " ", &saveptr);
while (token != NULL) {
argv[i++] = token;
token = strtok_r(NULL, " ", &saveptr);
}
return argv;
}
/**
* Internal method to read out weston.ini to get configuration
*/
@ -1203,7 +1177,6 @@ hmi_homescreen_setting_create(void)
while (weston_config_next_section(config, &section, &name)) {
struct hmi_homescreen_launcher *launcher;
char *command;
if (strcmp(name, "ivi-launcher") != 0)
continue;
@ -1213,18 +1186,8 @@ hmi_homescreen_setting_create(void)
weston_config_section_get_string(section, "icon",
&launcher->icon, NULL);
weston_config_section_get_string(section, "command",
&command, NULL);
if (command == NULL) {
weston_config_section_get_string(section, "path",
&launcher->path, NULL);
launcher->argv = NULL;
} else {
launcher->argv = parse_command(command);
launcher->path = launcher->argv[0];
}
weston_config_section_get_string(section, "path",
&launcher->path, NULL);
weston_config_section_get_uint(section, "workspace-id",
&launcher->workspace_id, 0);
weston_config_section_get_uint(section, "icon-id",

View file

@ -14,8 +14,6 @@ srcs_toytoolkit = [
relative_pointer_unstable_v1_protocol_c,
pointer_constraints_unstable_v1_client_protocol_h,
pointer_constraints_unstable_v1_protocol_c,
single_pixel_buffer_v1_client_protocol_h,
single_pixel_buffer_v1_protocol_c,
tablet_unstable_v2_client_protocol_h,
tablet_unstable_v2_protocol_c,
ivi_application_client_protocol_h,
@ -163,21 +161,6 @@ simple_clients = [
],
'dep_objs': [ dep_wayland_client, dep_libshared ]
},
{
'name': 'timing',
'sources': [
'simple-timing.c',
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
commit_timing_v1_client_protocol_h,
commit_timing_v1_protocol_c,
fifo_v1_client_protocol_h,
fifo_v1_protocol_c,
presentation_time_client_protocol_h,
presentation_time_protocol_c,
],
'dep_objs': [ dep_wayland_client, dep_libshared ]
},
{
'name': 'touch',
'sources': [
@ -189,89 +172,6 @@ simple_clients = [
},
]
if dep_vulkan.found() and prog_glslang.found()
srcs_simple_vulkan_shaders = [
'simple_vulkan_vertex_shader.vert',
'simple_vulkan_fragment_shader.frag',
]
simple_vulkan_shaders = []
foreach s : srcs_simple_vulkan_shaders
simple_vulkan_shaders += custom_target(s + '.spv.h',
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
input: s,
output: '@BASENAME@.spv.h',
)
endforeach
simple_clients += {
'name': 'vulkan',
'sources': [
'simple-vulkan.c',
simple_vulkan_shaders,
fractional_scale_v1_client_protocol_h,
fractional_scale_v1_protocol_c,
tearing_control_v1_client_protocol_h,
tearing_control_v1_protocol_c,
viewporter_client_protocol_h,
viewporter_protocol_c,
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
],
'dep_objs': [
dep_vulkan,
dep_libm,
dep_libshared,
dep_matrix_c,
dep_wayland_client,
],
'deps': [ 'vulkan', 'wayland-cursor' ],
'options': [ 'renderer-gl' ]
}
srcs_simple_dmabuf_vulkan_shaders = [
'simple_dmabuf_vulkan_vertex_shader.vert',
'simple_dmabuf_vulkan_fragment_shader.frag',
]
simple_dmabuf_vulkan_shaders = []
foreach s : srcs_simple_dmabuf_vulkan_shaders
simple_dmabuf_vulkan_shaders += custom_target(s + '.spv.h',
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
input: s,
output: '@BASENAME@.spv.h',
)
endforeach
simple_clients += {
'name': 'dmabuf-vulkan',
'sources': [
'simple-dmabuf-vulkan.c',
simple_dmabuf_vulkan_shaders,
linux_dmabuf_unstable_v1_client_protocol_h,
linux_dmabuf_unstable_v1_protocol_c,
linux_explicit_synchronization_unstable_v1_client_protocol_h,
linux_explicit_synchronization_unstable_v1_protocol_c,
xdg_shell_client_protocol_h,
xdg_shell_protocol_c,
weston_direct_display_client_protocol_h,
weston_direct_display_protocol_c,
],
'dep_objs': [
dep_vulkan,
dep_libdrm_headers,
dep_libm,
dep_libdrm,
dep_libshared,
dep_matrix_c,
dep_wayland_client,
dep_libweston_private, # for pixel-formats.h
],
'deps': [ 'vulkan', 'wayland-cursor', 'gbm' ],
'options': [ 'renderer-gl' ]
}
endif
foreach t : simple_clients
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
t_name = 'weston-simple-' + t.get('name')
@ -369,15 +269,6 @@ demo_clients = [
'basename': 'cliptest',
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
},
{
'basename': 'color',
'add_sources': [
color_management_v1_client_protocol_h,
color_management_v1_protocol_c,
single_pixel_buffer_v1_client_protocol_h,
single_pixel_buffer_v1_protocol_c,
],
},
{
'basename': 'constraints',
'add_sources': [
@ -500,7 +391,7 @@ if get_option('shell-desktop')
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
endif
if get_option('shell-desktop') or get_option('deprecated-shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
exe_shooter = executable(
'weston-screenshooter',
'screenshot.c',
@ -508,7 +399,6 @@ if get_option('shell-desktop') or get_option('deprecated-shell-fullscreen') or g
weston_output_capture_protocol_c,
include_directories: common_inc,
dependencies: [
dep_client_buffer,
dep_toytoolkit,
dep_libweston_private, # for pixel-formats.h
dep_pixman,

View file

@ -775,7 +775,7 @@ registry_handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
d->presentation =
wl_registry_bind(registry,
name, &wp_presentation_interface, 2);
name, &wp_presentation_interface, 1);
wp_presentation_add_listener(d->presentation,
&presentation_listener, d);
}

View file

@ -24,44 +24,33 @@
#include "config.h"
#include <assert.h>
#include <cairo.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <limits.h>
#include <pixman.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/param.h>
#include <fcntl.h>
#include <unistd.h>
#include <wayland-client.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/mman.h>
#include <pixman.h>
#include <cairo.h>
#include <assert.h>
#include "linux-dmabuf-unstable-v1-client-protocol.h"
#include "pixel-formats.h"
#include "shared/client-buffer-util.h"
#include "shared/file-util.h"
#include "shared/os-compatibility.h"
#include "shared/string-helpers.h"
#include "shared/xalloc.h"
#include <wayland-client.h>
#include "weston-output-capture-client-protocol.h"
#include "shared/os-compatibility.h"
#include "shared/xalloc.h"
#include "shared/file-util.h"
#include "pixel-formats.h"
struct screenshooter_app {
struct wl_display *display;
struct wl_registry *registry;
struct wl_shm *shm;
struct zwp_linux_dmabuf_v1 *dmabuf;
struct weston_capture_v1 *capture_factory;
bool verbose;
const struct pixel_format_info *requested_format;
enum weston_capture_v1_source src_type;
enum client_buffer_type buffer_type;
struct wl_list output_list; /* struct screenshooter_output::link */
bool retry;
@ -70,14 +59,14 @@ struct screenshooter_app {
};
struct screenshooter_buffer {
struct client_buffer *buf;
size_t len;
void *data;
struct wl_buffer *wl_buffer;
pixman_image_t *image;
enum weston_capture_v1_source src_type;
};
struct screenshooter_output {
struct screenshooter_app *app;
uint32_t name;
struct wl_list link; /* struct screenshooter_app::output_list */
struct wl_output *wl_output;
@ -87,8 +76,7 @@ struct screenshooter_output {
int buffer_width;
int buffer_height;
struct wl_array formats;
bool formats_done;
const struct pixel_format_info *fmt;
struct screenshooter_buffer *buffer;
};
@ -105,6 +93,10 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
const struct pixel_format_info *fmt)
{
struct screenshooter_buffer *buffer;
struct wl_shm_pool *pool;
int fd;
size_t bytes_pp;
size_t stride;
assert(width > 0);
assert(height > 0);
@ -113,60 +105,54 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
buffer = xzalloc(sizeof *buffer);
buffer->buf = client_buffer_util_create_shm_buffer(app->shm,
fmt,
width,
height);
bytes_pp = fmt->bpp / 8;
stride = width * bytes_pp;
buffer->len = stride * height;
assert(width == stride / bytes_pp);
assert(height == buffer->len / stride);
fd = os_create_anonymous_file(buffer->len);
if (fd < 0) {
fprintf(stderr, "creating a buffer file for %zd B failed: %s\n",
buffer->len, strerror(errno));
free(buffer);
return NULL;
}
buffer->data = mmap(NULL, buffer->len, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (buffer->data == MAP_FAILED) {
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
close(fd);
free(buffer);
return NULL;
}
pool = wl_shm_create_pool(app->shm, fd, buffer->len);
close(fd);
buffer->wl_buffer =
wl_shm_pool_create_buffer(pool, 0, width, height, stride,
pixel_format_get_shm_format(fmt));
wl_shm_pool_destroy(pool);
buffer->image = pixman_image_create_bits(fmt->pixman_format,
width, height,
buffer->buf->data,
buffer->buf->strides[0]);
buffer->data, stride);
abort_oom_if_null(buffer->image);
return buffer;
}
static struct screenshooter_buffer *
screenshot_create_udmabuf(struct screenshooter_app *app,
int width, int height,
const struct pixel_format_info *fmt)
{
struct screenshooter_buffer* buffer = NULL;
assert(width > 0);
assert(height > 0);
assert(fmt);
buffer = xzalloc(sizeof *buffer);
buffer->buf = client_buffer_util_create_dmabuf_buffer(app->display,
app->dmabuf,
fmt,
width,
height);
if (fmt->pixman_format) {
buffer->image = pixman_image_create_bits(fmt->pixman_format,
width, height,
buffer->buf->data,
buffer->buf->strides[0]);
abort_oom_if_null(buffer->image);
}
return buffer;
}
static void
screenshooter_buffer_destroy(struct screenshooter_buffer *buffer)
{
if (!buffer)
return;
if (buffer->image)
pixman_image_unref(buffer->image);
client_buffer_util_destroy_buffer(buffer->buf);
pixman_image_unref(buffer->image);
munmap(buffer->data, buffer->len);
wl_buffer_destroy(buffer->wl_buffer);
free(buffer);
}
@ -176,37 +162,10 @@ capture_source_handle_format(void *data,
uint32_t drm_format)
{
struct screenshooter_output *output = data;
uint32_t *fmt;
assert(output->source == proxy);
if (output->formats_done) {
wl_array_release(&output->formats);
wl_array_init(&output->formats);
output->formats_done = false;
}
fmt = wl_array_add(&output->formats, sizeof(uint32_t));
assert(fmt);
*fmt = drm_format;
if (output->app->verbose) {
const struct pixel_format_info *fmt_info;
fmt_info = pixel_format_get_info(drm_format);
assert(fmt_info);
printf("Got format %s / 0x%x\n", fmt_info->drm_format_name,
drm_format);
}
}
static void
capture_source_handle_formats_done(void *data,
struct weston_capture_source_v1 *proxy)
{
struct screenshooter_output *output = data;
output->formats_done = true;
output->fmt = pixel_format_get_info(drm_format);
}
static void
@ -221,9 +180,6 @@ capture_source_handle_size(void *data,
output->buffer_width = width;
output->buffer_height = height;
if (output->app->verbose)
printf("Got size %dx%d\n", width, height);
}
static void
@ -253,9 +209,7 @@ capture_source_handle_failed(void *data,
struct screenshooter_output *output = data;
output->app->waitcount--;
/* We don't set app.failed here because there could be other
* outputs we still want to capture!
*/
output->app->failed = true;
if (msg)
fprintf(stderr, "Output capture error: %s\n", msg);
@ -263,7 +217,6 @@ capture_source_handle_failed(void *data,
static const struct weston_capture_source_v1_listener capture_source_handlers = {
.format = capture_source_handle_format,
.formats_done = capture_source_handle_formats_done,
.size = capture_source_handle_size,
.complete = capture_source_handle_complete,
.retry = capture_source_handle_retry,
@ -278,20 +231,17 @@ create_output(struct screenshooter_app *app, uint32_t output_name, uint32_t vers
version = MIN(version, 4);
output = xzalloc(sizeof *output);
output->app = app;
output->name = output_name;
output->wl_output = wl_registry_bind(app->registry, output_name,
&wl_output_interface, version);
abort_oom_if_null(output->wl_output);
output->source = weston_capture_v1_create(app->capture_factory,
output->wl_output,
app->src_type);
WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER);
abort_oom_if_null(output->source);
weston_capture_source_v1_add_listener(output->source,
&capture_source_handlers, output);
wl_array_init(&output->formats);
wl_list_insert(&app->output_list, &output->link);
}
@ -300,8 +250,6 @@ destroy_output(struct screenshooter_output *output)
{
weston_capture_source_v1_destroy(output->source);
wl_array_release(&output->formats);
if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
wl_output_release(output->wl_output);
else
@ -329,13 +277,7 @@ handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, weston_capture_v1_interface.name) == 0) {
app->capture_factory = wl_registry_bind(registry, name,
&weston_capture_v1_interface,
2);
} else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) {
if (version < 3)
return;
app->dmabuf = wl_registry_bind(registry, name,
&zwp_linux_dmabuf_v1_interface,
3);
1);
}
}
@ -353,46 +295,15 @@ static const struct wl_registry_listener registry_listener = {
static void
screenshooter_output_capture(struct screenshooter_output *output)
{
const struct pixel_format_info *fmt_info = NULL;
uint32_t *fmt;
screenshooter_buffer_destroy(output->buffer);
wl_array_for_each(fmt, &output->formats) {
fmt_info = pixel_format_get_info(*fmt);
assert(fmt_info);
if (fmt_info == output->app->requested_format ||
output->app->requested_format == NULL)
break;
fmt_info = NULL;
}
if (!fmt_info) {
fprintf(stderr, "No supported format found\n");
exit(1);
}
if (output->app->verbose)
printf("Creating buffer with format %s / 0x%x and size %ux%u\n",
fmt_info->drm_format_name, fmt_info->format,
output->buffer_width, output->buffer_height);
if (output->app->buffer_type == CLIENT_BUFFER_TYPE_SHM) {
output->buffer = screenshot_create_shm_buffer(output->app,
output->buffer_width,
output->buffer_height,
fmt_info);
} else if (output->app->buffer_type == CLIENT_BUFFER_TYPE_DMABUF) {
output->buffer = screenshot_create_udmabuf(output->app,
output->buffer_width,
output->buffer_height,
fmt_info);
}
output->buffer = screenshot_create_shm_buffer(output->app,
output->buffer_width,
output->buffer_height,
output->fmt);
abort_oom_if_null(output->buffer);
weston_capture_source_v1_capture(output->source,
output->buffer->buf->wl_buffer);
output->buffer->wl_buffer);
output->app->waitcount++;
}
@ -412,8 +323,6 @@ screenshot_write_png(const struct buffer_size *buff_size,
abort_oom_if_null(shot);
wl_list_for_each(output, output_list, link) {
client_buffer_util_maybe_sync_dmabuf_start(output->buffer->buf);
pixman_image_composite32(PIXMAN_OP_SRC,
output->buffer->image, /* src */
NULL, /* mask */
@ -422,8 +331,6 @@ screenshot_write_png(const struct buffer_size *buff_size,
0, 0, /* mask x,y */
output->offset_x, output->offset_y, /* dst x,y */
output->buffer_width, output->buffer_height);
client_buffer_util_maybe_sync_dmabuf_end(output->buffer->buf);
}
surface = cairo_image_surface_create_for_data((void *)pixman_image_get_data(shot),
@ -442,59 +349,6 @@ screenshot_write_png(const struct buffer_size *buff_size,
pixman_image_unref(shot);
}
static void
screenshot_write_yuv(const struct buffer_size *buff_size,
struct wl_list *output_list)
{
struct screenshooter_output *output;
int i = 0;
wl_list_for_each(output, output_list, link) {
struct screenshooter_buffer *buffer = output->buffer;
char filepath[PATH_MAX];
char filepath_prefix[100];
int write_offset = 0;
FILE *fp;
sprintf(filepath_prefix, "wayland-screenshot-output-%d-", i++);
fp = file_create_dated(getenv("XDG_PICTURES_DIR"),
filepath_prefix, ".yuv", filepath,
sizeof(filepath));
if (!fp) {
fprintf(stderr, "Writing yuv file for output %d failed\n", i);
return;
}
client_buffer_util_maybe_sync_dmabuf_start(buffer->buf);
for (unsigned int j = 0; j < pixel_format_get_plane_count(buffer->buf->fmt); j++) {
int plane_height =
buffer->buf->height / pixel_format_hsub(buffer->buf->fmt, j);
for (int k = 0; k < plane_height; k++) {
size_t lines_written;
lines_written = fwrite(buffer->buf->data + write_offset,
buffer->buf->bytes_per_line[j],
1, fp);
if (lines_written != 1) {
fprintf(stderr,
"Writing yuv file for output %d " \
"failed during write(): %s\n",
i, strerror(errno));
return;
}
write_offset += buffer->buf->strides[j];
}
}
fclose (fp);
client_buffer_util_maybe_sync_dmabuf_end(buffer->buf);
}
}
static int
screenshot_set_buffer_size(struct buffer_size *buff_size,
struct wl_list *output_list)
@ -528,182 +382,41 @@ screenshot_set_buffer_size(struct buffer_size *buff_size,
return 0;
}
static bool
received_formats_for_all_outputs(struct screenshooter_app *app)
{
struct screenshooter_output *output;
wl_list_for_each(output, &app->output_list, link) {
if (!output->formats_done)
return false;
}
return true;
}
static bool
all_output_formats_are_yuv(struct wl_list *output_list)
{
struct screenshooter_output *output;
int color_model = -1;
wl_list_for_each(output, output_list, link) {
if (color_model == -1) {
color_model = output->buffer->buf->fmt->color_model;
continue;
}
if ((int)output->buffer->buf->fmt->color_model != color_model) {
fprintf(stderr, "Mixing of RGB and YUV output formats not supported\n");
exit(1);
}
}
assert(color_model == (int)COLOR_MODEL_RGB ||
color_model == (int)COLOR_MODEL_YUV);
return color_model == COLOR_MODEL_YUV;
}
static void
print_usage_and_exit(void)
{
printf("usage flags:\n"
"\t'-h,--help'"
"\n\t\tprint this help output\n"
"\t'-v,--verbose'"
"\n\t\tprint additional output\n"
"\t'-f,--format=<>'"
"\n\t\tthe DRM format name to use without the DRM_FORMAT_ prefix, e.g. RGBA8888 or NV12\n"
"\n\t\tIn case of YCbCr formats like NV12, instead of a single .png, the output will consist of raw .yuv files for each output."
"\n\t\tThese files do not contain any metadata, however that can be added by converting to .y4m with a command like:"
"\n\t\tffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m\n"
"\n\t\tNote that this may not work for all YCbCr pixel formats.\n"
"\t'-s,--source-type=<>'"
"\n\t\tframebuffer to use framebuffer source (default), "
"\n\t\twriteback to use writeback source\n"
"\t'-b,--buffer-type=<>'"
"\n\t\tshm to use a SHM buffer (default), "
"\n\t\tdmabuf to use a DMA buffer\n");
exit(0);
}
static const struct weston_enum_map source_types [] = {
{ "framebuffer", WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER },
{ "writeback", WESTON_CAPTURE_V1_SOURCE_WRITEBACK },
};
static const struct weston_enum_map buffer_types [] = {
{ "shm", CLIENT_BUFFER_TYPE_SHM },
{ "dmabuf", CLIENT_BUFFER_TYPE_DMABUF },
};
int
main(int argc, char *argv[])
{
struct wl_display *display;
struct screenshooter_output *output;
struct screenshooter_output *tmp_output;
struct buffer_size buff_size = {};
struct screenshooter_app app = {};
int c, option_index;
app.src_type = WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER;
app.buffer_type = CLIENT_BUFFER_TYPE_SHM;
static struct option long_options[] = {
{"help", no_argument, NULL, 'h'},
{"verbose", no_argument, NULL, 'v'},
{"format", required_argument, NULL, 'f'},
{"source-type", required_argument, NULL, 's'},
{"buffer-type", required_argument, NULL, 'b'},
{0, 0, 0, 0}
};
while ((c = getopt_long(argc, argv, "hvf:s:b:",
long_options, &option_index)) != -1) {
const struct weston_enum_map *entry;
switch(c) {
case 'v':
app.verbose = true;
break;
case 'f':
app.requested_format = pixel_format_get_info_by_drm_name(optarg);
if (!app.requested_format) {
fprintf(stderr, "Unknown format %s\n", optarg);
return -1;
}
break;
case 's':
entry = weston_enum_map_find_name(source_types,
optarg);
if (!entry)
print_usage_and_exit();
app.src_type = entry->value;
break;
case 'b':
entry = weston_enum_map_find_name(buffer_types,
optarg);
if (!entry)
print_usage_and_exit();
app.buffer_type = entry->value;
break;
default:
print_usage_and_exit();
}
}
wl_list_init(&app.output_list);
app.display = wl_display_connect(NULL);
if (app.display == NULL) {
display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "failed to create display: %s\n",
strerror(errno));
return -1;
}
app.registry = wl_display_get_registry(app.display);
app.registry = wl_display_get_registry(display);
wl_registry_add_listener(app.registry, &registry_listener, &app);
/* Process wl_registry advertisements */
wl_display_roundtrip(app.display);
wl_display_roundtrip(display);
if (!app.shm) {
fprintf(stderr, "Error: display does not support wl_shm\n");
return -1;
}
if (!app.capture_factory) {
fprintf(stderr, "Error: display does not support weston_capture_v1\n");
return -1;
}
if (app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER &&
app.buffer_type != CLIENT_BUFFER_TYPE_SHM) {
fprintf(stderr, "Error: Only support shm buffer with framebuffer source\n");
return -1;
}
if(app.buffer_type == CLIENT_BUFFER_TYPE_SHM && !app.shm) {
fprintf(stderr, "Error: display does not support wl_shm\n");
return -1;
}
if (app.buffer_type == CLIENT_BUFFER_TYPE_DMABUF && !app.dmabuf) {
fprintf(stderr, "Error: Compositor does not support zwp_linux_dmabuf_v1\n");
return -1;
}
if (app.verbose) {
printf("Taking screenshot with %s source %s buffer\n",
(app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER) ? "framebuffer" : "writeback",
(app.buffer_type == CLIENT_BUFFER_TYPE_SHM) ? "shm" : "dma");
}
/* Process initial events for wl_output and weston_capture_source_v1 */
wl_display_roundtrip(app.display);
while (!received_formats_for_all_outputs(&app)) {
if (app.verbose)
printf("Waiting for compositor to send capture source data\n");
if (wl_display_dispatch(app.display) < 0) {
fprintf(stderr, "Error: connection terminated\n");
return -1;
}
}
wl_display_roundtrip(display);
do {
app.retry = false;
@ -712,7 +425,7 @@ main(int argc, char *argv[])
screenshooter_output_capture(output);
while (app.waitcount > 0 && !app.failed) {
if (wl_display_dispatch(app.display) < 0)
if (wl_display_dispatch(display) < 0)
app.failed = true;
assert(app.waitcount >= 0);
}
@ -721,11 +434,7 @@ main(int argc, char *argv[])
if (!app.failed) {
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
return -1;
if (all_output_formats_are_yuv(&app.output_list))
screenshot_write_yuv(&buff_size, &app.output_list);
else
screenshot_write_png(&buff_size, &app.output_list);
screenshot_write_png(&buff_size, &app.output_list);
} else {
fprintf(stderr, "Error: screenshot or protocol failure\n");
}
@ -735,10 +444,8 @@ main(int argc, char *argv[])
weston_capture_v1_destroy(app.capture_factory);
wl_shm_destroy(app.shm);
if (app.dmabuf)
zwp_linux_dmabuf_v1_destroy(app.dmabuf);
wl_registry_destroy(app.registry);
wl_display_disconnect(app.display);
wl_display_disconnect(display);
return 0;
}

View file

@ -815,7 +815,7 @@ render(struct window *window, struct buffer *buffer)
glUniform1f(window->gl.offset_uniform, offset);
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
(GLfloat *) reflection.M.colmaj);
(GLfloat *) reflection.d);
glClearColor(0.0,0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -864,7 +864,7 @@ render_mandelbrot(struct window *window, struct buffer *buffer)
glUniform1f(window->gl.offset_uniform, offset);
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
(GLfloat *) reflection.M.colmaj);
(GLfloat *) reflection.d);
glClearColor(0.6, 0.6, 0.6, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
@ -1110,12 +1110,6 @@ destroy_display(struct display *display)
free(display->modifiers);
if (display->direct_display)
weston_direct_display_v1_destroy(display->direct_display);
if (display->explicit_sync)
zwp_linux_explicit_synchronization_v1_destroy(display->explicit_sync);
if (display->dmabuf)
zwp_linux_dmabuf_v1_destroy(display->dmabuf);

File diff suppressed because it is too large Load diff

View file

@ -564,6 +564,7 @@ init_gl(struct window *window)
glBindAttribLocation(program, window->gl.pos, "pos");
glBindAttribLocation(program, window->gl.col, "color");
glLinkProgram(program);
window->gl.rotation_uniform =
glGetUniformLocation(program, "rotation");
@ -939,10 +940,10 @@ redraw(struct window *window)
angle = ((time - window->initial_frame_time) / speed_div)
% 360 * M_PI / 180.0;
}
rotation.M.col[0].el[0] = cos(angle);
rotation.M.col[0].el[2] = sin(angle);
rotation.M.col[2].el[0] = -sin(angle);
rotation.M.col[2].el[2] = cos(angle);
rotation.d[0] = cos(angle);
rotation.d[2] = sin(angle);
rotation.d[8] = -sin(angle);
rotation.d[10] = cos(angle);
switch (window->buffer_transform) {
case WL_OUTPUT_TRANSFORM_FLIPPED:
@ -981,7 +982,7 @@ redraw(struct window *window)
glViewport(0, 0, window->buffer_size.width, window->buffer_size.height);
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
(GLfloat *) rotation.M.colmaj);
(GLfloat *) rotation.d);
if (window->opaque || window->fullscreen)
glClearColor(0.0, 0.0, 0.0, 1);
@ -1473,10 +1474,15 @@ main(int argc, char **argv)
create_surface(&window);
/* we already have wait_for_configure set after create_surface() */
while (running && ret != -1 && window.wait_for_configure)
while (running && ret != -1 && window.wait_for_configure) {
ret = wl_display_dispatch(display.display);
init_gl(&window);
/* wait until xdg_surface::configure acks the new dimensions */
if (window.wait_for_configure)
continue;
init_gl(&window);
}
display.cursor_surface =
wl_compositor_create_surface(display.compositor);
@ -1524,9 +1530,6 @@ out_no_xdg_shell:
if (display.compositor)
wl_compositor_destroy(display.compositor);
if (display.tearing_manager)
wp_tearing_control_manager_v1_destroy(display.tearing_manager);
if (display.viewporter)
wp_viewporter_destroy(display.viewporter);

View file

@ -34,7 +34,6 @@
#include <sys/mman.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <linux/input.h>
@ -43,20 +42,8 @@
#include <libweston/zalloc.h>
#include "xdg-shell-client-protocol.h"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#define FMT(fmt, bpp, r, g, b, a) { WL_SHM_FORMAT_ ## fmt, #fmt, bpp, { r, g, b, a } }
#define MAX_BUFFER_ALLOC 2
struct window;
struct format {
uint32_t code;
const char *string;
int bpp;
uint64_t color[4];
};
struct display {
struct wl_display *display;
struct wl_registry *registry;
@ -65,10 +52,7 @@ struct display {
struct wl_seat *seat;
struct wl_keyboard *keyboard;
struct wl_shm *shm;
const struct format *format;
bool paint_format;
bool has_format;
struct window *window;
bool has_xrgb;
};
struct buffer {
@ -97,68 +81,6 @@ struct window {
bool needs_update_buffer;
};
static const struct format shm_formats[] = {
/* 8 bpp formats */
FMT(R8, 8, 0x00, 0x55, 0xaa, 0xff ),
/* 16 bpp formats */
FMT(R16, 16, 0x0000, 0x5555, 0xaaaa, 0xffff ),
FMT(GR88, 16, 0x00ff, 0xff00, 0x0000, 0xffff ),
FMT(RG88, 16, 0xff00, 0x00ff, 0x0000, 0xffff ),
FMT(RGB565, 16, 0xf800, 0x07e0, 0x001f, 0xffff ),
FMT(BGR565, 16, 0x001f, 0x07e0, 0xf800, 0xffff ),
FMT(XRGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
FMT(ARGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
FMT(XBGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
FMT(ABGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
FMT(RGBX4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
FMT(RGBA4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
FMT(BGRX4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
FMT(BGRA4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
FMT(XRGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
FMT(ARGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
FMT(XBGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
FMT(ABGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
FMT(RGBX5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
FMT(RGBA5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
FMT(BGRX5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
FMT(BGRA5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
/* 24 bpp formats */
FMT(RGB888, 24, 0xff0000, 0x00ff00, 0x0000ff, 0xffffff ),
FMT(BGR888, 24, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff ),
/* 32 bpp formats */
FMT(GR1616, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff ),
FMT(RG1616, 32, 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff ),
FMT(XRGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
FMT(ARGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
FMT(XBGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
FMT(ABGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
FMT(RGBX8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
FMT(RGBA8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
FMT(BGRX8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
FMT(BGRA8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
FMT(XRGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
FMT(ARGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
FMT(XBGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
FMT(ABGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
FMT(RGBX1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
FMT(RGBA1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
FMT(BGRX1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
FMT(BGRA1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
/* 64 bpp formats */
FMT(XRGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
FMT(ARGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
FMT(XBGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
FMT(ABGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
FMT(XRGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
FMT(ARGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
FMT(XBGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
FMT(ABGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
};
static int running = 1;
static void
@ -229,8 +151,7 @@ static const struct wl_buffer_listener buffer_listener = {
};
static int
create_shm_buffer(struct window *window, struct buffer *buffer,
const struct format *format)
create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
{
struct wl_shm_pool *pool;
int fd, size, stride;
@ -240,7 +161,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer,
width = window->width;
height = window->height;
stride = width * (format->bpp / 8);
stride = width * 4;
size = stride * height;
display = window->display;
@ -261,7 +182,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer,
pool = wl_shm_create_pool(display->shm, fd, size);
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
width, height,
stride, format->code);
stride, format);
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
wl_shm_pool_destroy(pool);
close(fd);
@ -298,16 +219,8 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state)
{
struct display *d = data;
if (key == KEY_F11 && state) {
if (d->window->fullscreen)
xdg_toplevel_unset_fullscreen(d->window->xdg_toplevel);
else
xdg_toplevel_set_fullscreen(d->window->xdg_toplevel, NULL);
} else if (key == KEY_ESC && state) {
if (key == KEY_ESC && state)
running = 0;
}
}
static void
@ -503,16 +416,14 @@ window_next_buffer(struct window *window)
return NULL;
if (!buffer->buffer) {
ret = create_shm_buffer(window, buffer,
window->display->format);
ret = create_shm_buffer(window, buffer, WL_SHM_FORMAT_XRGB8888);
if (ret < 0)
return NULL;
/* paint the padding */
memset(buffer->shm_data, 0xff,
window->width * window->height *
(window->display->format->bpp / 8));
window->width * window->height * 4);
}
return buffer;
@ -564,122 +475,6 @@ paint_pixels(void *image, int padding, int width, int height, uint32_t time)
}
}
static void
paint_format(void *image, const struct format *format, int width, int height)
{
uint64_t *img64 = (uint64_t*) image;
uint32_t *img32 = (uint32_t*) image;
uint16_t *img16 = (uint16_t*) image;
uint8_t *img8 = (uint8_t*) image;
uint64_t color;
int i, j;
#define GET_COLOR(y) \
(y < (1 * (height / 4))) ? format->color[0] : \
(y < (2 * (height / 4))) ? format->color[1] : \
(y < (3 * (height / 4))) ? format->color[2] : \
format->color[3]
switch (format->code) {
case WL_SHM_FORMAT_R8:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img8[i * width + j] = color;
}
break;
case WL_SHM_FORMAT_R16:
case WL_SHM_FORMAT_GR88:
case WL_SHM_FORMAT_RG88:
case WL_SHM_FORMAT_RGB565:
case WL_SHM_FORMAT_BGR565:
case WL_SHM_FORMAT_XRGB4444:
case WL_SHM_FORMAT_ARGB4444:
case WL_SHM_FORMAT_XBGR4444:
case WL_SHM_FORMAT_ABGR4444:
case WL_SHM_FORMAT_RGBX4444:
case WL_SHM_FORMAT_RGBA4444:
case WL_SHM_FORMAT_BGRX4444:
case WL_SHM_FORMAT_BGRA4444:
case WL_SHM_FORMAT_XRGB1555:
case WL_SHM_FORMAT_ARGB1555:
case WL_SHM_FORMAT_XBGR1555:
case WL_SHM_FORMAT_ABGR1555:
case WL_SHM_FORMAT_RGBX5551:
case WL_SHM_FORMAT_RGBA5551:
case WL_SHM_FORMAT_BGRX5551:
case WL_SHM_FORMAT_BGRA5551:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img16[i * width + j] = color;
}
break;
case WL_SHM_FORMAT_RGB888:
case WL_SHM_FORMAT_BGR888:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++) {
img8[(i * width + j) * 3 + 0] =
(color >> 0) & 0xff;
img8[(i * width + j) * 3 + 1] =
(color >> 8) & 0xff;
img8[(i * width + j) * 3 + 2] =
(color >> 16) & 0xff;
}
}
break;
case WL_SHM_FORMAT_GR1616:
case WL_SHM_FORMAT_RG1616:
case WL_SHM_FORMAT_XRGB8888:
case WL_SHM_FORMAT_ARGB8888:
case WL_SHM_FORMAT_XBGR8888:
case WL_SHM_FORMAT_ABGR8888:
case WL_SHM_FORMAT_RGBX8888:
case WL_SHM_FORMAT_RGBA8888:
case WL_SHM_FORMAT_BGRX8888:
case WL_SHM_FORMAT_BGRA8888:
case WL_SHM_FORMAT_XRGB2101010:
case WL_SHM_FORMAT_ARGB2101010:
case WL_SHM_FORMAT_XBGR2101010:
case WL_SHM_FORMAT_ABGR2101010:
case WL_SHM_FORMAT_RGBX1010102:
case WL_SHM_FORMAT_RGBA1010102:
case WL_SHM_FORMAT_BGRX1010102:
case WL_SHM_FORMAT_BGRA1010102:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img32[i * width + j] = color;
}
break;
case WL_SHM_FORMAT_XRGB16161616:
case WL_SHM_FORMAT_ARGB16161616:
case WL_SHM_FORMAT_XBGR16161616:
case WL_SHM_FORMAT_ABGR16161616:
case WL_SHM_FORMAT_XRGB16161616F:
case WL_SHM_FORMAT_ARGB16161616F:
case WL_SHM_FORMAT_XBGR16161616F:
case WL_SHM_FORMAT_ABGR16161616F:
for (i = 0; i < height; i++) {
color = GET_COLOR(i);
for (j = 0; j < width; j++)
img64[i * width + j] = color;
}
break;
default:
assert(0);
break;
};
#undef GET_COLOR
}
static const struct wl_callback_listener frame_listener;
static void
@ -698,12 +493,7 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
abort();
}
if (window->display->paint_format)
paint_format(buffer->shm_data, window->display->format,
window->width, window->height);
else
paint_pixels(buffer->shm_data, 20, window->width,
window->height, time);
paint_pixels(buffer->shm_data, 20, window->width, window->height, time);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface,
@ -727,8 +517,8 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{
struct display *d = data;
if (format == d->format->code)
d->has_format = true;
if (format == WL_SHM_FORMAT_XRGB8888)
d->has_xrgb = true;
}
struct wl_shm_listener shm_listener = {
@ -782,7 +572,7 @@ static const struct wl_registry_listener registry_listener = {
};
static struct display *
create_display(const struct format *format, bool paint_format)
create_display(void)
{
struct display *display;
@ -794,9 +584,7 @@ create_display(const struct format *format, bool paint_format)
display->display = wl_display_connect(NULL);
assert(display->display);
display->format = format;
display->paint_format = paint_format;
display->has_format= false;
display->has_xrgb = false;
display->registry = wl_display_get_registry(display->display);
wl_registry_add_listener(display->registry,
&registry_listener, display);
@ -848,9 +636,8 @@ create_display(const struct format *format, bool paint_format)
* technique.
*/
if (!display->has_format) {
fprintf(stderr, "Format '%s' not supported by compositor.\n",
format->string);
if (!display->has_xrgb) {
fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
exit(1);
}
@ -881,86 +668,19 @@ signal_int(int signum)
running = 0;
}
static void
usage(const char *program)
{
fprintf(stdout,
"Usage: %s [OPTIONS]\n"
"\n"
"Draw pixels into shared memory buffers using wl_shm\n"
"\n"
"Options:\n"
" -h, --help Show this help\n"
" -F, --format <format> Test format (see list below)\n"
"\n"
"RGB formats:\n"
" - 8 bpp: r8.\n"
"\n"
" - 16 bpp: r16, gr88, rg88, rgb565, bgr565, xrgb4444, argb4444, xbgr4444,\n"
" abgr4444, rgbx4444, rgba4444, bgrx4444, bgra4444, xrgb1555,\n"
" argb1555, xbgr1555, abgr1555, rgbx5551, rgba5551, bgrx5551,\n"
" bgra5551.\n"
"\n"
" - 24 bpp: rgb888, bgr888.\n"
"\n"
" - 32 bpp: gr1616, rg1616, xrgb8888, argb8888, xbgr8888, abgr8888, rgbx8888,\n"
" rgba8888, bgrx8888, bgra8888, xrgb2101010, argb2101010, xbgr2101010,\n"
" abgr2101010, rgbx1010102, rgba1010102, bgrx1010102, bgra1010102.\n"
"\n"
" - 64 bpp: xrgb16161616, argb16161616, xbgr16161616, abgr16161616,\n"
" xrgb16161616f, argb16161616f, xbgr16161616f, abgr16161616f.\n",
program);
}
int
main(int argc, char **argv)
{
struct sigaction sigint;
struct display *display;
struct window *window;
const struct format *format = NULL;
bool paint_format = false;
const char *value;
int ret = 0, i, j;
int ret = 0;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") ||
!strcmp(argv[i], "--help")) {
usage(argv[0]);
return 0;
} else if (!strcmp(argv[i], "-F") ||
!strcmp(argv[i], "--format")) {
value = ++i == argc ? "" : argv[i];
for (j = 0; j < (int) ARRAY_SIZE(shm_formats); j++) {
if (!strcasecmp(shm_formats[j].string, value)) {
format = &shm_formats[j];
paint_format = true;
break;
}
}
if (!format) {
fprintf(stderr, "Format '%s' not supported by "
"client.\n", value);
return 1;
}
} else {
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
return 1;
}
}
if (!format)
for (i = 0; i < (int) ARRAY_SIZE(shm_formats); i++)
if (shm_formats[i].code == WL_SHM_FORMAT_XRGB8888)
format = &shm_formats[i];
assert(format);
display = create_display(format, paint_format);
window = create_window(display, 256, 256);
display = create_display();
window = create_window(display, 250, 250);
if (!window)
return 1;
display->window = window;
sigint.sa_handler = signal_int;
sigemptyset(&sigint.sa_mask);
sigint.sa_flags = SA_RESETHAND;

View file

@ -1,885 +0,0 @@
/*
* Copyright © 2011 Benjamin Franzke
* Copyright © 2010 Intel Corporation
* Copyright © 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "config.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <assert.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
#include <errno.h>
#include <assert.h>
#include <linux/input.h>
#include <wayland-client.h>
#include "shared/os-compatibility.h"
#include "shared/timespec-util.h"
#include "shared/xalloc.h"
#include <libweston/zalloc.h>
#include "xdg-shell-client-protocol.h"
#include "commit-timing-v1-client-protocol.h"
#include "fifo-v1-client-protocol.h"
#include "presentation-time-client-protocol.h"
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
#define MAX_BUFFER_ALLOC 1000
struct display {
struct wl_display *display;
struct wl_registry *registry;
struct wl_compositor *compositor;
struct xdg_wm_base *wm_base;
struct wl_seat *seat;
struct wl_keyboard *keyboard;
struct wl_shm *shm;
struct wp_commit_timing_manager_v1 *commit_timing_manager;
struct wp_fifo_manager_v1 *fifo_manager;
struct wp_presentation *presentation;
bool have_clock_id;
clockid_t presentation_clock_id;
int64_t first_frame_time;
int64_t refresh_nsec;
};
struct buffer {
struct window *window;
struct wl_buffer *buffer;
void *shm_data;
int busy;
int width, height;
size_t size; /* width * 4 * height */
struct wl_list buffer_link; /** window::buffer_list */
};
struct window {
struct display *display;
int width, height;
int init_width, init_height;
struct wl_surface *surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
struct wl_list buffer_list;
struct wl_callback *callback;
struct wp_fifo_v1 *fifo;
struct wp_commit_timer_v1 *commit_timer;
bool wait_for_configure;
bool maximized;
bool fullscreen;
bool needs_update_buffer;
};
struct feedback {
struct wp_presentation_feedback *fb;
struct window *window;
int64_t target_time;
bool final;
};
static int running = 1;
static void
draw_for_time(void *data, int64_t time, bool wait_fifo);
static void
finish_run(struct window *window);
static struct buffer *
alloc_buffer(struct window *window, int width, int height)
{
struct buffer *buffer = calloc(1, sizeof(*buffer));
buffer->width = width;
buffer->height = height;
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
return buffer;
}
static void
destroy_buffer(struct buffer *buffer)
{
if (buffer->buffer)
wl_buffer_destroy(buffer->buffer);
munmap(buffer->shm_data, buffer->size);
wl_list_remove(&buffer->buffer_link);
free(buffer);
}
static struct buffer *
pick_free_buffer(struct window *window)
{
struct buffer *b;
struct buffer *buffer = NULL;
wl_list_for_each(b, &window->buffer_list, buffer_link) {
if (!b->busy) {
buffer = b;
break;
}
}
return buffer;
}
static void
prune_old_released_buffers(struct window *window)
{
struct buffer *b, *b_next;
wl_list_for_each_safe(b, b_next,
&window->buffer_list, buffer_link) {
if (!b->busy && (b->width != window->width ||
b->height != window->height))
destroy_buffer(b);
}
}
static void
buffer_release(void *data, struct wl_buffer *buffer)
{
struct buffer *mybuf = data;
mybuf->busy = 0;
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
static int
create_shm_buffer(struct window *window, struct buffer *buffer)
{
struct wl_shm_pool *pool;
int fd, size, stride;
void *data;
int width, height;
struct display *display;
width = window->width;
height = window->height;
stride = width * 4;
size = stride * height;
display = window->display;
fd = os_create_anonymous_file(size);
if (fd < 0) {
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
size, strerror(errno));
return -1;
}
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) {
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
close(fd);
return -1;
}
pool = wl_shm_create_pool(display->shm, fd, size);
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
width, height,
stride,
WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
wl_shm_pool_destroy(pool);
close(fd);
buffer->size = size;
buffer->shm_data = data;
return 0;
}
static void
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
uint32_t format, int fd, uint32_t size)
{
/* Just so we dont leak the keymap fd */
close(fd);
}
static void
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface,
struct wl_array *keys)
{
}
static void
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
uint32_t serial, struct wl_surface *surface)
{
}
static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t time, uint32_t key,
uint32_t state)
{
if (key == KEY_ESC && state)
running = 0;
}
static void
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
uint32_t serial, uint32_t mods_depressed,
uint32_t mods_latched, uint32_t mods_locked,
uint32_t group)
{
}
static const struct wl_keyboard_listener keyboard_listener = {
keyboard_handle_keymap,
keyboard_handle_enter,
keyboard_handle_leave,
keyboard_handle_key,
keyboard_handle_modifiers,
};
static void
seat_handle_capabilities(void *data, struct wl_seat *seat,
enum wl_seat_capability caps)
{
struct display *d = data;
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
d->keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
wl_keyboard_destroy(d->keyboard);
d->keyboard = NULL;
}
}
static const struct wl_seat_listener seat_listener = {
seat_handle_capabilities,
};
static void
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
uint32_t serial)
{
struct window *window = data;
xdg_surface_ack_configure(surface, serial);
if (window->wait_for_configure) {
draw_for_time(window, 0, false);
window->wait_for_configure = false;
}
}
static const struct xdg_surface_listener xdg_surface_listener = {
handle_xdg_surface_configure,
};
static void
handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
int32_t width, int32_t height,
struct wl_array *states)
{
struct window *window = data;
uint32_t *p;
window->fullscreen = false;
window->maximized = false;
wl_array_for_each(p, states) {
uint32_t state = *p;
switch (state) {
case XDG_TOPLEVEL_STATE_FULLSCREEN:
window->fullscreen = true;
break;
case XDG_TOPLEVEL_STATE_MAXIMIZED:
window->maximized = true;
break;
}
}
if (width > 0 && height > 0) {
if (!window->fullscreen && !window->maximized) {
window->init_width = width;
window->init_height = height;
}
window->width = width;
window->height = height;
} else if (!window->fullscreen && !window->maximized) {
window->width = window->init_width;
window->height = window->init_height;
}
window->needs_update_buffer = true;
}
static void
handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
{
running = 0;
}
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
handle_xdg_toplevel_configure,
handle_xdg_toplevel_close,
};
static struct window *
create_window(struct display *display, int width, int height)
{
struct window *window;
int i;
window = zalloc(sizeof *window);
if (!window)
return NULL;
window->callback = NULL;
window->display = display;
window->width = width;
window->height = height;
window->init_width = width;
window->init_height = height;
window->surface = wl_compositor_create_surface(display->compositor);
window->fifo = wp_fifo_manager_v1_get_fifo(display->fifo_manager,
window->surface);
window->commit_timer = wp_commit_timing_manager_v1_get_timer(display->commit_timing_manager,
window->surface);
window->needs_update_buffer = false;
wl_list_init(&window->buffer_list);
assert(display->wm_base);
window->xdg_surface =
xdg_wm_base_get_xdg_surface(display->wm_base,
window->surface);
assert(window->xdg_surface);
xdg_surface_add_listener(window->xdg_surface,
&xdg_surface_listener, window);
window->xdg_toplevel =
xdg_surface_get_toplevel(window->xdg_surface);
assert(window->xdg_toplevel);
xdg_toplevel_add_listener(window->xdg_toplevel,
&xdg_toplevel_listener, window);
xdg_toplevel_set_title(window->xdg_toplevel, "simple-shm");
xdg_toplevel_set_app_id(window->xdg_toplevel,
"org.freedesktop.weston.simple-shm");
wl_surface_commit(window->surface);
window->wait_for_configure = true;
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
alloc_buffer(window, window->width, window->height);
return window;
}
static void
destroy_window(struct window *window)
{
struct buffer *buffer, *buffer_next;
if (window->callback)
wl_callback_destroy(window->callback);
wl_list_for_each_safe(buffer, buffer_next,
&window->buffer_list, buffer_link)
destroy_buffer(buffer);
if (window->xdg_toplevel)
xdg_toplevel_destroy(window->xdg_toplevel);
if (window->xdg_surface)
xdg_surface_destroy(window->xdg_surface);
wl_surface_destroy(window->surface);
if (window->fifo)
wp_fifo_v1_destroy(window->fifo);
if (window->commit_timer)
wp_commit_timer_v1_destroy(window->commit_timer);
free(window);
}
static struct buffer *
window_next_buffer(struct window *window)
{
struct buffer *buffer = NULL;
int ret = 0;
if (window->needs_update_buffer) {
int i;
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
alloc_buffer(window, window->width, window->height);
window->needs_update_buffer = false;
}
buffer = pick_free_buffer(window);
if (!buffer)
return NULL;
if (!buffer->buffer) {
ret = create_shm_buffer(window, buffer);
if (ret < 0)
return NULL;
/* paint the padding */
memset(buffer->shm_data, 0xff,
window->width * window->height * 4);
}
return buffer;
}
static void
paint_pixels(void *image, int width, int height, uint32_t time)
{
const int halfh = height / 2;
const int halfw = width / 2;
int ir, or;
uint32_t *pixel = image;
int y;
/* squared radii thresholds */
or = (halfw < halfh ? halfw : halfh) - 8;
ir = or - 32;
or *= or;
ir *= ir;
for (y = 0; y < height; y++) {
int x;
int y2 = (y - halfh) * (y - halfh);
for (x = 0; x < width; x++) {
uint32_t v;
/* squared distance from center */
int r2 = (x - halfw) * (x - halfw) + y2;
if (r2 < ir)
v = (r2 / 32 + time / 64) * 0x0080401;
else if (r2 < or)
v = (y + time / 32) * 0x0080401;
else
v = (x + time / 16) * 0x0080401;
v &= 0x00ffffff;
/* cross if compositor uses X from XRGB as alpha */
if (abs(x - y) > 6 && abs(x + y - height) > 6)
v |= 0xff000000;
*pixel++ = v;
}
}
}
static void
queue_some_frames(struct window *window)
{
struct display *display = window->display;
int64_t target_nsec;
int i;
assert(display->first_frame_time);
/* Round off error will cause us problems if we don't
* reduce this a bit, because we could end up rounding
* to either side of a refresh.
*/
target_nsec = display->first_frame_time - 100000;
for (i = 0; i < 60; i++) {
target_nsec += display->refresh_nsec * 2;
draw_for_time(window, target_nsec, false);
}
for (i = 0; i < 30; i++) {
target_nsec += display->refresh_nsec * 4;
draw_for_time(window, target_nsec, false);
}
for (i = 0; i < 10; i++) {
target_nsec += display->refresh_nsec * 10;
draw_for_time(window, target_nsec, false);
}
for (i = 0; i < 10; i++) {
target_nsec += display->refresh_nsec * 100;
draw_for_time(window, target_nsec, false);
}
finish_run(window);
}
static void
feedback_sync_output(void *data,
struct wp_presentation_feedback *presentation_feedback,
struct wl_output *output)
{
/* Just don't care */
}
static void
feedback_presented(void *data,
struct wp_presentation_feedback *presentation_feedback,
uint32_t tv_sec_hi,
uint32_t tv_sec_lo,
uint32_t tv_nsec,
uint32_t refresh_nsec,
uint32_t seq_hi,
uint32_t seq_lo,
uint32_t flags)
{
struct feedback *feedback = data;
struct window *window = feedback->window;
struct display *display = window->display;
struct timespec pres_ts = {
.tv_sec = ((int64_t)tv_sec_hi << 32) + tv_sec_lo,
.tv_nsec = tv_nsec,
};
int64_t ntime = timespec_to_nsec(&pres_ts);
double delay;
if (feedback->final) {
running = 0;
goto out;
}
if (!feedback->target_time) {
display->first_frame_time = ntime;
display->refresh_nsec = refresh_nsec;
queue_some_frames(window);
goto out;
}
delay = (ntime - feedback->target_time) / 1000000.0;
printf("%fms away from intended time\n", delay);
if (fabs(delay) > display->refresh_nsec / 1000000)
printf("Warning: we missed the intended target display cycle.\n");
out:
wp_presentation_feedback_destroy(feedback->fb);
free(feedback);
}
static void
feedback_discarded(void *data,
struct wp_presentation_feedback *presentation_feedback)
{
struct feedback *feedback = data;
printf("Warning: a frame was discarded\n");
if (feedback->final)
running = 0;
wp_presentation_feedback_destroy(feedback->fb);
free(feedback);
}
static const struct wp_presentation_feedback_listener feedback_listener = {
feedback_sync_output,
feedback_presented,
feedback_discarded,
};
static void
finish_run(struct window *window)
{
struct display *display = window->display;
struct feedback *feedback;
struct buffer *buffer;
feedback = xzalloc(sizeof *feedback);
feedback->window = window;
feedback->final = true;
feedback->target_time = 0;
buffer = window_next_buffer(window);
assert(buffer);
paint_pixels(buffer->shm_data, window->width,
window->height, 1);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
feedback->fb = wp_presentation_feedback(display->presentation,
window->surface);
wp_presentation_feedback_add_listener(feedback->fb,
&feedback_listener, feedback);
wp_fifo_v1_wait_barrier(window->fifo);
wl_surface_commit(window->surface);
}
static void
draw_for_time(void *data, int64_t time, bool wait_fifo)
{
struct window *window = data;
struct display *display = window->display;
struct buffer *buffer;
struct feedback *feedback;
assert(display->have_clock_id);
prune_old_released_buffers(window);
buffer = window_next_buffer(window);
assert(buffer);
paint_pixels(buffer->shm_data, window->width,
window->height, time / 1000000);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
feedback = xzalloc(sizeof *feedback);
feedback->window = window;
feedback->fb = wp_presentation_feedback(display->presentation,
window->surface);
wp_presentation_feedback_add_listener(feedback->fb,
&feedback_listener, feedback);
feedback->target_time = time;
if (time) {
struct timespec target;
timespec_from_nsec(&target, time);
wp_commit_timer_v1_set_timestamp(window->commit_timer,
(int64_t)target.tv_sec >> 32,
target.tv_sec,
target.tv_nsec);
}
wp_fifo_v1_set_barrier(window->fifo);
wl_surface_commit(window->surface);
buffer->busy = 1;
}
static void
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
{
xdg_wm_base_pong(shell, serial);
}
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
xdg_wm_base_ping,
};
static void
presentation_handle_clock_id(void *data,
struct wp_presentation *wp_presentation,
uint32_t clock_id)
{
struct display *display = data;
display->presentation_clock_id = clock_id;
display->have_clock_id = true;
}
static const struct wp_presentation_listener presentation_listener = {
presentation_handle_clock_id,
};
static void
registry_handle_global(void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
struct display *d = data;
if (strcmp(interface, "wl_compositor") == 0) {
d->compositor =
wl_registry_bind(registry,
id, &wl_compositor_interface, 1);
} else if (strcmp(interface, "xdg_wm_base") == 0) {
d->wm_base = wl_registry_bind(registry,
id, &xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
} else if (strcmp(interface, "wl_seat") == 0) {
d->seat = wl_registry_bind(registry, id,
&wl_seat_interface, 1);
wl_seat_add_listener(d->seat, &seat_listener, d);
} else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry,
id, &wl_shm_interface, 1);
} else if (strcmp(interface, wp_commit_timing_manager_v1_interface.name) == 0) {
d->commit_timing_manager = wl_registry_bind(registry, id,
&wp_commit_timing_manager_v1_interface,
1);
} else if (strcmp(interface, wp_fifo_manager_v1_interface.name) == 0) {
d->fifo_manager = wl_registry_bind(registry, id,
&wp_fifo_manager_v1_interface,
1);
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
d->presentation = wl_registry_bind(registry, id,
&wp_presentation_interface,
2);
wp_presentation_add_listener(d->presentation,
&presentation_listener, d);
}
}
static void
registry_handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name)
{
}
static const struct wl_registry_listener registry_listener = {
registry_handle_global,
registry_handle_global_remove
};
static struct display *
create_display(void)
{
struct display *display;
display = xzalloc(sizeof *display);
display->display = wl_display_connect(NULL);
assert(display->display);
display->registry = wl_display_get_registry(display->display);
wl_registry_add_listener(display->registry,
&registry_listener, display);
wl_display_roundtrip(display->display);
if (display->shm == NULL) {
fprintf(stderr, "No wl_shm global\n");
exit(1);
}
wl_display_roundtrip(display->display);
return display;
}
static void
destroy_display(struct display *display)
{
if (display->shm)
wl_shm_destroy(display->shm);
if (display->wm_base)
xdg_wm_base_destroy(display->wm_base);
if (display->compositor)
wl_compositor_destroy(display->compositor);
if (display->presentation)
wp_presentation_destroy(display->presentation);
if (display->fifo_manager)
wp_fifo_manager_v1_destroy(display->fifo_manager);
if (display->commit_timing_manager)
wp_commit_timing_manager_v1_destroy(display->commit_timing_manager);
if (display->keyboard)
wl_keyboard_destroy(display->keyboard);
if (display->seat)
wl_seat_destroy(display->seat);
wl_registry_destroy(display->registry);
wl_display_flush(display->display);
wl_display_disconnect(display->display);
free(display);
}
static void
signal_int(int signum)
{
running = 0;
}
static void
usage(const char *program)
{
fprintf(stdout,
"Usage: %s [OPTIONS]\n"
"\n"
"Schedule frames in the future with commit-timing\n"
"\n"
"Options:\n"
" -h, --help Show this help\n"
"\n",
program);
}
int
main(int argc, char **argv)
{
struct sigaction sigint;
struct display *display;
struct window *window;
int ret = 0, i;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-h") ||
!strcmp(argv[i], "--help")) {
usage(argv[0]);
return 0;
} else {
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
return 1;
}
}
display = create_display();
window = create_window(display, 256, 256);
if (!window)
return 1;
sigint.sa_handler = signal_int;
sigemptyset(&sigint.sa_mask);
sigint.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &sigint, NULL);
while (running && ret != -1)
ret = wl_display_dispatch(display->display);
fprintf(stderr, "simple-timing exiting\n");
destroy_window(window);
destroy_display(display);
return 0;
}

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
#version 450 core
layout(location = 0) in vec4 v_color;
layout(location = 0) out vec4 f_color;
void main() {
f_color = v_color;
}

View file

@ -1,17 +0,0 @@
#version 450 core
layout(std140, set = 0, binding = 0) uniform block {
uniform mat4 reflection;
uniform float offset;
};
layout(location = 0) in vec4 pos;
layout(location = 1) in vec4 color;
layout(location = 0) out vec4 v_color;
void main()
{
gl_Position = reflection * (pos + vec4(offset, offset, 0.0, 0.0));
v_color = color;
}

View file

@ -1,9 +0,0 @@
#version 450 core
layout(location = 0) in vec4 vVaryingColor;
layout(location = 0) out vec4 f_color;
void main()
{
f_color = vVaryingColor;
}

View file

@ -1,16 +0,0 @@
#version 450 core
layout(std140, set = 0, binding = 0) uniform block {
uniform mat4 rotation;
};
layout(location = 0) in vec4 in_position;
layout(location = 1) in vec4 in_color;
layout(location = 0) out vec4 vVaryingColor;
void main()
{
gl_Position = rotation * in_position;
vVaryingColor = vec4(in_color.rgba);
}

View file

@ -58,7 +58,6 @@ static char *option_term;
static char *option_shell;
static struct wl_list terminal_list;
struct sigaction oldact;
static struct terminal *
terminal_create(struct display *display);
@ -3101,9 +3100,6 @@ terminal_run(struct terminal *terminal, const char *path)
close(pipes[0]);
setenv("TERM", option_term, 1);
setenv("COLORTERM", option_term, 1);
sigaction(SIGPIPE, &oldact, NULL);
if (execl(path, path, NULL)) {
printf("exec failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
@ -3181,10 +3177,8 @@ int main(int argc, char *argv[])
* socket whose reading end has been closed */
sigpipe.sa_handler = SIG_IGN;
sigemptyset(&sigpipe.sa_mask);
sigemptyset(&oldact.sa_mask);
sigpipe.sa_flags = 0;
sigaction(SIGPIPE, &sigpipe, &oldact);
sigaction(SIGPIPE, &sigpipe, NULL);
d = display_create(&argc, argv);
if (d == NULL) {

View file

@ -330,9 +330,9 @@ compute_calibration(struct calibrator *cal, float *result)
*/
weston_matrix_init(&m);
for (i = 0; i < 3; i++) {
m.M.col[0].el[i] = cal->samples[i].touched.x;
m.M.col[1].el[i] = cal->samples[i].touched.y;
m.M.col[2].el[i] = 1.0f;
m.d[i + 0] = cal->samples[i].touched.x;
m.d[i + 4] = cal->samples[i].touched.y;
m.d[i + 8] = 1.0f;
}
m.type = WESTON_MATRIX_TRANSFORM_OTHER;
@ -342,20 +342,20 @@ compute_calibration(struct calibrator *cal, float *result)
}
for (i = 0; i < 3; i++) {
x_calib.v.el[i] = cal->samples[i].drawn_cal.x;
y_calib.v.el[i] = cal->samples[i].drawn_cal.y;
x_calib.f[i] = cal->samples[i].drawn_cal.x;
y_calib.f[i] = cal->samples[i].drawn_cal.y;
}
x_calib.v.el[3] = 0.0f;
y_calib.v.el[3] = 0.0f;
x_calib.f[3] = 0.0f;
y_calib.f[3] = 0.0f;
/* Multiples into the vector */
weston_matrix_transform(&inverse, &x_calib);
weston_matrix_transform(&inverse, &y_calib);
for (i = 0; i < 3; i++)
result[i] = x_calib.v.el[i];
result[i] = x_calib.f[i];
for (i = 0; i < 3; i++)
result[i + 3] = y_calib.v.el[i];
result[i + 3] = y_calib.f[i];
return 0;
}

View file

@ -44,7 +44,9 @@
#include <xkbcommon/xkbcommon.h>
#ifdef HAVE_XKBCOMMON_COMPOSE
#include <xkbcommon/xkbcommon-compose.h>
#endif
#include <wayland-cursor.h>
#include <linux/input.h>
@ -55,7 +57,6 @@
#include <libweston/zalloc.h>
#include "xdg-shell-client-protocol.h"
#include "color-management-v1-client-protocol.h"
#include "single-pixel-buffer-v1-client-protocol.h"
#include "text-cursor-position-client-protocol.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "relative-pointer-unstable-v1-client-protocol.h"
@ -90,11 +91,10 @@ struct display {
struct wl_data_device_manager *data_device_manager;
struct text_cursor_position *text_cursor_position;
struct xdg_wm_base *xdg_shell;
struct wp_color_manager_v1 *color_manager;
struct xx_color_manager_v4 *color_manager;
struct zwp_tablet_manager_v2 *tablet_manager;
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
struct zwp_pointer_constraints_v1 *pointer_constraints;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager;
uint32_t serial;
uint32_t color_manager_features;
@ -217,7 +217,7 @@ struct surface {
struct wl_callback *frame_cb;
uint32_t last_time;
struct wp_color_management_surface_v1 *cm_surface;
struct xx_color_management_surface_v4 *cm_surface;
struct rectangle allocation;
struct rectangle server_allocation;
@ -400,8 +400,10 @@ struct input {
struct {
struct xkb_keymap *keymap;
struct xkb_state *state;
#ifdef HAVE_XKBCOMMON_COMPOSE
struct xkb_compose_table *compose_table;
struct xkb_compose_state *compose_state;
#endif
xkb_mod_mask_t control_mask;
xkb_mod_mask_t alt_mask;
xkb_mod_mask_t shift_mask;
@ -478,7 +480,7 @@ struct shm_pool {
};
struct cm_image_description {
struct wp_image_description_v1 *image_desc;
struct xx_image_description_v4 *image_desc;
enum cm_image_desc_status {
CM_IMAGE_DESC_NOT_CREATED = 0,
CM_IMAGE_DESC_READY,
@ -491,27 +493,27 @@ render_intent_info_table[] = {
{
.intent = RENDER_INTENT_PERCEPTUAL,
.desc = "Perceptual",
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL,
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_PERCEPTUAL,
},
{
.intent = RENDER_INTENT_RELATIVE,
.desc = "Media-relative colorimetric",
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE,
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE,
},
{
.intent = RENDER_INTENT_RELATIVE_BPC,
.desc = "Media-relative colorimetric + black point compensation",
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE_BPC,
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_RELATIVE_BPC,
},
{
.intent = RENDER_INTENT_SATURATION,
.desc = "Saturation",
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION,
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_SATURATION,
},
{
.intent = RENDER_INTENT_ABSOLUTE,
.desc = "ICC-absolute colorimetric",
.protocol_intent = WP_COLOR_MANAGER_V1_RENDER_INTENT_ABSOLUTE,
.protocol_intent = XX_COLOR_MANAGER_V4_RENDER_INTENT_ABSOLUTE,
},
};
@ -566,7 +568,7 @@ debug_print(void *proxy, int line, const char *func, const char *fmt, ...)
#endif
static void
cm_image_desc_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
cm_image_desc_ready(void *data, struct xx_image_description_v4 *xx_image_description_v4,
uint32_t identity)
{
struct cm_image_description *cm_image_desc = data;
@ -575,7 +577,7 @@ cm_image_desc_ready(void *data, struct wp_image_description_v1 *wp_image_descrip
}
static void
cm_image_desc_failed(void *data, struct wp_image_description_v1 *wp_image_description_v1,
cm_image_desc_failed(void *data, struct xx_image_description_v4 *xx_image_description_v4,
uint32_t cause, const char *msg)
{
struct cm_image_description *cm_image_desc = data;
@ -586,7 +588,7 @@ cm_image_desc_failed(void *data, struct wp_image_description_v1 *wp_image_descri
cm_image_desc->status = CM_IMAGE_DESC_FAILED;
}
static const struct wp_image_description_v1_listener cm_image_desc_listener = {
static const struct xx_image_description_v4_listener cm_image_desc_listener = {
.ready = cm_image_desc_ready,
.failed = cm_image_desc_failed,
};
@ -608,10 +610,10 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
uint32_t length, uint32_t offset,
enum render_intent intent, char **err_msg)
{
struct wp_image_description_creator_icc_v1 *icc_creator;
struct xx_image_description_creator_icc_v4 *icc_creator;
struct display *display = widget->window->display;
struct surface *surface = widget->surface;
struct wp_color_manager_v1 *color_manager_wrapper;
struct xx_color_manager_v4 *color_manager_wrapper;
struct wl_event_queue *queue;
struct cm_image_description cm_image_desc;
const struct render_intent_info *intent_info;
@ -621,11 +623,11 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
str_printf(err_msg,
"%s extension not supported by the Wayland " \
"compositor, ignoring image color profile.",
wp_color_manager_v1_interface.name);
xx_color_manager_v4_interface.name);
return false;
}
if (!((display->color_manager_features >> WP_COLOR_MANAGER_V1_FEATURE_ICC_V2_V4) & 1)) {
if (!((display->color_manager_features >> XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4) & 1)) {
str_printf(err_msg,
"Wayland compositor does not support creating image " \
"descriptions from ICC files, ignoring color profile.");
@ -648,15 +650,15 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
wl_proxy_set_queue((struct wl_proxy *)color_manager_wrapper, queue);
/* Create ICC image description creator and set the ICC file. */
icc_creator = wp_color_manager_v1_create_icc_creator(color_manager_wrapper);
icc_creator = xx_color_manager_v4_new_icc_creator(color_manager_wrapper);
wl_proxy_wrapper_destroy(color_manager_wrapper);
wp_image_description_creator_icc_v1_set_icc_file(icc_creator,
xx_image_description_creator_icc_v4_set_icc_file(icc_creator,
icc_fd, offset, length);
/* Create the image description. It will also destroy the ICC creator. */
cm_image_desc.status = CM_IMAGE_DESC_NOT_CREATED;
cm_image_desc.image_desc = wp_image_description_creator_icc_v1_create(icc_creator);
wp_image_description_v1_add_listener(cm_image_desc.image_desc,
cm_image_desc.image_desc = xx_image_description_creator_icc_v4_create(icc_creator);
xx_image_description_v4_add_listener(cm_image_desc.image_desc,
&cm_image_desc_listener, &cm_image_desc);
/* Wait until compositor creates the image description or gracefully
@ -664,7 +666,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
while (ret != -1 && cm_image_desc.status == CM_IMAGE_DESC_NOT_CREATED)
ret = wl_display_dispatch_queue(display->display, queue);
if (ret == -1) {
wp_image_description_v1_destroy(cm_image_desc.image_desc);
xx_image_description_v4_destroy(cm_image_desc.image_desc);
wl_event_queue_destroy(queue);
str_printf(err_msg,
"Disconnected from the Wayland compositor, " \
@ -675,7 +677,7 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
/* Gracefully failed to create image description. Error already printed
* in the handler. */
if (cm_image_desc.status == CM_IMAGE_DESC_FAILED) {
wp_image_description_v1_destroy(cm_image_desc.image_desc);
xx_image_description_v4_destroy(cm_image_desc.image_desc);
wl_event_queue_destroy(queue);
str_printf(err_msg,
"Image description creation gracefully failed.");
@ -685,14 +687,14 @@ widget_set_image_description_icc(struct widget *widget, int icc_fd,
if (!surface->cm_surface)
surface->cm_surface =
wp_color_manager_v1_get_surface(display->color_manager,
xx_color_manager_v4_get_surface(display->color_manager,
surface->surface);
wp_color_management_surface_v1_set_image_description(surface->cm_surface,
xx_color_management_surface_v4_set_image_description(surface->cm_surface,
cm_image_desc.image_desc,
intent_info->protocol_intent);
wp_image_description_v1_destroy(cm_image_desc.image_desc);
xx_image_description_v4_destroy(cm_image_desc.image_desc);
wl_event_queue_destroy(queue);
return true;
@ -1449,35 +1451,6 @@ surface_flush(struct surface *surface)
surface->cairo_surface = NULL;
}
void
widget_surface_flush(struct widget *widget)
{
struct surface *surface = widget->surface;
if (surface->opaque_region) {
wl_surface_set_opaque_region(surface->surface,
surface->opaque_region);
wl_region_destroy(surface->opaque_region);
surface->opaque_region = NULL;
}
if (surface->input_region) {
wl_surface_set_input_region(surface->surface,
surface->input_region);
wl_region_destroy(surface->input_region);
surface->input_region = NULL;
}
if (surface->viewport) {
wp_viewport_set_destination(surface->viewport,
widget->viewport_dest_width,
widget->viewport_dest_height);
}
wl_surface_damage(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(surface->surface);
}
int
window_has_focus(struct window *window)
{
@ -1605,7 +1578,7 @@ surface_destroy(struct surface *surface)
wp_viewport_destroy(surface->viewport);
if (surface->cm_surface)
wp_color_management_surface_v1_destroy(surface->cm_surface);
xx_color_management_surface_v4_destroy(surface->cm_surface);
wl_surface_destroy(surface->surface);
@ -1873,9 +1846,8 @@ widget_cairo_update_transform(struct widget *widget, cairo_t *cr)
surface->allocation.width,
surface->allocation.height,
surface->buffer_scale);
cairo_matrix_init(&m, matrix.M.col[0].x, matrix.M.col[0].y,
matrix.M.col[1].x, matrix.M.col[1].y,
matrix.M.col[3].x, matrix.M.col[3].y);
cairo_matrix_init(&m, matrix.d[0], matrix.d[1], matrix.d[4],
matrix.d[5], matrix.d[12], matrix.d[13]);
cairo_transform(cr, &m);
}
@ -3130,8 +3102,10 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
struct input *input = data;
struct xkb_keymap *keymap;
struct xkb_state *state;
#ifdef HAVE_XKBCOMMON_COMPOSE
struct xkb_compose_table *compose_table;
struct xkb_compose_state *compose_state;
#endif
char *locale;
char *map_str;
@ -3179,6 +3153,7 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
locale = "C";
/* Set up XKB compose table */
#ifdef HAVE_XKBCOMMON_COMPOSE
compose_table =
xkb_compose_table_new_from_locale(input->display->xkb_context,
locale,
@ -3202,6 +3177,7 @@ keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
fprintf(stderr, "could not create XKB compose table for locale '%s'. "
"Disabiling compose\n", locale);
}
#endif
xkb_keymap_unref(input->xkb.keymap);
xkb_state_unref(input->xkb.state);
@ -3252,6 +3228,7 @@ keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
static xkb_keysym_t
process_key_press(xkb_keysym_t sym, struct input *input)
{
#ifdef HAVE_XKBCOMMON_COMPOSE
if (!input->xkb.compose_state)
return sym;
if (sym == XKB_KEY_NoSymbol)
@ -3272,6 +3249,9 @@ process_key_press(xkb_keysym_t sym, struct input *input)
default:
return sym;
}
#else
return sym;
#endif
}
static void
@ -4392,8 +4372,8 @@ undo_resize(struct window *window)
}
}
static void
window_configure_resize(struct window *window, int width, int height)
void
window_schedule_resize(struct window *window, int width, int height)
{
/* We should probably get these numbers from the theme. */
const int min_width = 200, min_height = 200;
@ -4420,12 +4400,6 @@ window_configure_resize(struct window *window, int width, int height)
window->pending_allocation.height = window->min_allocation.height;
window->resize_needed = 1;
}
void
window_schedule_resize(struct window *window, int width, int height)
{
window_configure_resize(window, width, height);
window_schedule_redraw(window);
}
@ -4514,14 +4488,6 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
}
}
/* If the window is being mapped fullscreen,
* save the last pending allocation */
if (window->fullscreen &&
(window->saved_allocation.width == 0 ||
window->saved_allocation.height == 0)) {
window->saved_allocation = window->pending_allocation;
}
if (window->frame) {
if (window->maximized) {
frame_set_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED);
@ -4542,14 +4508,14 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
* on the shadow margin to get the difference. */
int margin = window_get_shadow_margin(window);
window_configure_resize(window,
width + margin * 2,
height + margin * 2);
window_schedule_resize(window,
width + margin * 2,
height + margin * 2);
} else if (window->saved_allocation.width > 0 &&
window->saved_allocation.height > 0) {
window_configure_resize(window,
window->saved_allocation.width,
window->saved_allocation.height);
window_schedule_resize(window,
window->saved_allocation.width,
window->saved_allocation.height);
}
}
@ -4971,20 +4937,6 @@ window_set_locked_pointer_motion_handler(struct window *window,
window->locked_pointer_motion_handler = handler;
}
void
window_set_shadow(struct window *window)
{
if (window->frame)
frame_unset_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
}
void
window_unset_shadow(struct window *window)
{
if (window->frame)
frame_set_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
}
void
window_set_title(struct window *window, const char *title)
{
@ -6719,7 +6671,7 @@ display_bind_tablets(struct display *d, uint32_t id)
}
static void
cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
uint32_t render_intent)
{
struct display *d = data;
@ -6728,7 +6680,7 @@ cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
}
static void
cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
uint32_t feature)
{
struct display *d = data;
@ -6737,31 +6689,24 @@ cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1
}
static void
cm_supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
uint32_t tf_code)
{
/* unused in this file */
}
static void
cm_supported_primaries_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
uint32_t primaries_code)
{
/* unused in this file */
}
static void
cm_done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
{
/* unused in this file */
}
static const struct wp_color_manager_v1_listener cm_listener = {
static const struct xx_color_manager_v4_listener cm_listener = {
.supported_intent = cm_supported_intent,
.supported_feature = cm_supported_feature,
.supported_tf_named = cm_supported_tf_named,
.supported_primaries_named = cm_supported_primaries_named,
.done = cm_done,
};
static void
@ -6832,17 +6777,12 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
&wp_viewporter_interface, 1);
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
display_bind_tablets(d, id);
} else if (strcmp(interface, "wp_color_manager_v1") == 0) {
} else if (strcmp(interface, "xx_color_manager_v4") == 0) {
d->color_manager =
wl_registry_bind(registry, id,
&wp_color_manager_v1_interface, 1);
wp_color_manager_v1_add_listener(d->color_manager,
&xx_color_manager_v4_interface, 1);
xx_color_manager_v4_add_listener(d->color_manager,
&cm_listener, d);
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
d->single_pixel_buffer_manager =
wl_registry_bind(registry, id,
&wp_single_pixel_buffer_manager_v1_interface,
1);
}
if (d->global_handler)
@ -7065,7 +7005,7 @@ display_destroy(struct display *display)
xdg_wm_base_destroy(display->xdg_shell);
if (display->color_manager)
wp_color_manager_v1_destroy(display->color_manager);
xx_color_manager_v4_destroy(display->color_manager);
if (display->shm)
wl_shm_destroy(display->shm);
@ -7131,12 +7071,6 @@ display_get_compositor(struct display *display)
return display->compositor;
}
struct wp_single_pixel_buffer_manager_v1 *
display_get_single_pixel_buffer_manager(struct display *display)
{
return display->single_pixel_buffer_manager;
}
uint32_t
display_get_serial(struct display *display)
{

View file

@ -76,9 +76,6 @@ display_has_subcompositor(struct display *display);
struct wl_compositor *
display_get_compositor(struct display *display);
struct wp_single_pixel_buffer_manager_v1 *
display_get_single_pixel_buffer_manager(struct display *display);
struct output *
display_get_output(struct display *display);
@ -533,12 +530,6 @@ void
window_set_locked_pointer_motion_handler(
struct window *window, window_locked_pointer_motion_handler_t handler);
void
window_set_shadow(struct window *window);
void
window_unset_shadow(struct window *window);
void
window_set_title(struct window *window, const char *title);
@ -613,9 +604,6 @@ widget_cairo_create(struct widget *widget);
struct wl_surface *
widget_get_wl_surface(struct widget *widget);
void
widget_surface_flush(struct widget *widget);
uint32_t
widget_get_last_time(struct widget *widget);

View file

@ -33,7 +33,6 @@ home.png
icon_ivi_clickdot.png
icon_ivi_flower.png
icon_ivi_simple-egl.png
icon_ivi_simple-egl-vertical.png
icon_ivi_simple-shm.png
icon_ivi_smoke.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -9,7 +9,6 @@ install_data(
'icon_ivi_clickdot.png',
'icon_ivi_flower.png',
'icon_ivi_simple-egl.png',
'icon_ivi_simple-egl-vertical.png',
'icon_ivi_simple-shm.png',
'icon_ivi_smoke.png',
'icon_terminal.png',

View file

@ -48,6 +48,168 @@
#define DEFAULT_NUM_WORKSPACES 1
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
struct focus_state {
struct desktop_shell *shell;
struct weston_seat *seat;
struct workspace *ws;
struct weston_surface *keyboard_focus;
struct wl_list link;
struct wl_listener seat_destroy_listener;
struct wl_listener surface_destroy_listener;
};
/*
* Surface stacking and ordering.
*
* This is handled using several linked lists of surfaces, organised into
* layers. The layers are ordered, and each of the surfaces in one layer are
* above all of the surfaces in the layer below. The set of layers is static and
* in the following order (top-most first):
* Lock layer (only ever displayed on its own)
* Cursor layer
* Input panel layer
* Fullscreen layer
* Panel layer
* Workspace layers
* Background layer
*
* The list of layers may be manipulated to remove whole layers of surfaces from
* display. For example, when locking the screen, all layers except the lock
* layer are removed.
*
* A surfaces layer is modified on configuring the surface, in
* set_surface_type() (which is only called when the surfaces type change is
* _committed_). If a surfaces type changes (e.g. when making a window
* fullscreen) its layer changes too.
*
* In order to allow popup and transient surfaces to be correctly stacked above
* their parent surfaces, each surface tracks both its parent surface, and a
* linked list of its children. When a surfaces layer is updated, so are the
* layers of its children. Note that child surfaces are *not* the same as
* subsurfaces child/parent surfaces are purely for maintaining stacking
* order.
*
* The children_link list of siblings of a surface (i.e. those surfaces which
* have the same parent) only contains weston_surfaces which have a
* shell_surface. Stacking is not implemented for non-shell_surface
* weston_surfaces. This means that the following implication does *not* hold:
* (shsurf->parent != NULL) !wl_list_is_empty(shsurf->children_link)
*/
struct shell_surface {
struct wl_signal destroy_signal;
struct weston_desktop_surface *desktop_surface;
struct weston_view *view;
struct weston_surface *wsurface_anim_fade;
struct weston_view *wview_anim_fade;
int32_t last_width, last_height;
struct desktop_shell *shell;
struct wl_list children_list;
struct wl_list children_link;
struct weston_coord_global saved_pos;
bool saved_position_valid;
bool saved_rotation_valid;
int unresponsive, grabbed;
uint32_t resize_edges;
uint32_t orientation;
struct {
struct weston_transform transform;
struct weston_matrix rotation;
} rotation;
struct {
struct weston_curtain *black_view;
} fullscreen;
struct weston_output *fullscreen_output;
struct weston_output *output;
struct wl_listener output_destroy_listener;
struct surface_state {
bool fullscreen;
bool maximized;
bool lowered;
} state;
struct {
bool is_set;
struct weston_coord_global pos;
} xwayland;
int focus_count;
bool destroying;
struct wl_list link; /** desktop_shell::shsurf_list */
};
struct shell_grab {
struct weston_pointer_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
};
struct shell_touch_grab {
struct weston_touch_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_touch *touch;
};
struct shell_tablet_tool_grab {
struct weston_tablet_tool_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_tablet_tool *tool;
};
struct weston_move_grab {
struct shell_grab base;
struct weston_coord_global delta;
bool client_initiated;
};
struct weston_touch_move_grab {
struct shell_touch_grab base;
int active;
struct weston_coord_global delta;
};
struct weston_tablet_tool_move_grab {
struct shell_tablet_tool_grab base;
wl_fixed_t dx, dy;
};
struct rotate_grab {
struct shell_grab base;
struct weston_matrix rotation;
struct {
float x;
float y;
} center;
};
struct shell_seat {
struct weston_seat *seat;
struct wl_listener seat_destroy_listener;
struct weston_surface *focused_surface;
struct wl_listener caps_changed_listener;
struct wl_listener pointer_focus_listener;
struct wl_listener keyboard_focus_listener;
struct wl_listener tablet_tool_added_listener;
struct wl_list link; /** shell::seat_list */
};
struct tablet_tool_listener {
struct wl_listener base;
struct wl_listener removed_listener;
};
static struct desktop_shell *
shell_surface_get_shell(struct shell_surface *shsurf);
@ -73,6 +235,20 @@ shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
static void
get_maximized_size(struct shell_surface *shsurf, int32_t *width, int32_t *height);
static struct shell_output *
find_shell_output_from_weston_output(struct desktop_shell *shell,
struct weston_output *output)
{
struct shell_output *shell_output;
wl_list_for_each(shell_output, &shell->output_list, link) {
if (shell_output->output == output)
return shell_output;
}
return NULL;
}
static bool
shsurf_is_max_or_fullscreen(struct shell_surface *shsurf)
{
@ -93,8 +269,8 @@ set_shsurf_size_maximized_or_fullscreen(struct shell_surface *shsurf,
if (fullscreen_requested) {
if (shsurf->output) {
width = shsurf->output->output->width;
height = shsurf->output->output->height;
width = shsurf->output->width;
height = shsurf->output->height;
}
} else if (max_requested) {
/* take the panels into considerations */
@ -193,18 +369,21 @@ shell_grab_start(struct shell_grab *grab,
void
get_output_work_area(struct desktop_shell *shell,
struct shell_output *sh_output,
struct weston_output *output,
pixman_rectangle32_t *area)
{
struct weston_output *output;
struct shell_output *sh_output;
area->x = 0;
area->y = 0;
area->width = 0;
area->height = 0;
if (!sh_output)
if (!output)
return;
output = sh_output->output;
sh_output = find_shell_output_from_weston_output(shell, output);
assert(sh_output);
area->x = output->pos.c.x;
area->y = output->pos.c.y;
@ -344,7 +523,6 @@ shell_configuration(struct desktop_shell *shell)
struct weston_config *config;
char *s, *client;
bool allow_zap;
bool disallow_output_changed_move;
config = wet_get_config(shell->compositor);
section = weston_config_get_section(config, "shell", NULL, NULL);
@ -357,11 +535,6 @@ shell_configuration(struct desktop_shell *shell)
"allow-zap", &allow_zap, true);
shell->allow_zap = allow_zap;
weston_config_section_get_bool(section,
"disallow-output-changed-move",
&disallow_output_changed_move, false);
shell->disallow_output_changed_move = disallow_output_changed_move;
shell->binding_modifier = weston_config_get_binding_modifier(config, MODIFIER_SUPER);
weston_config_section_get_string(section, "animation", &s, "none");
@ -888,12 +1061,7 @@ constrain_position(struct weston_move_grab *move)
if (shsurf->shell->panel_position ==
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
struct shell_output *shoutput = NULL;
if (surface->output)
shoutput = weston_output_get_shell_private(surface->output);
get_output_work_area(shsurf->shell, shoutput, &area);
get_output_work_area(shsurf->shell, surface->output, &area);
geometry =
weston_desktop_surface_get_geometry(shsurf->desktop_surface);
@ -1534,26 +1702,15 @@ shell_surface_set_output(struct shell_surface *shsurf,
{
struct weston_surface *es =
weston_desktop_surface_get_surface(shsurf->desktop_surface);
struct shell_output *shoutput = NULL;
if (output)
shoutput = weston_output_get_shell_private(output);
/* get the default output, if the client set it as NULL
check whether the output is available */
if (shoutput)
shsurf->output = shoutput;
if (output)
shsurf->output = output;
else if (es->output)
shsurf->output = weston_output_get_shell_private(es->output);
else {
struct shell_output *shoutput = NULL;
struct weston_output *w_output;
w_output = weston_shell_utils_get_default_output(es->compositor);
if (w_output)
shoutput = weston_output_get_shell_private(w_output);
shsurf->output = shoutput;
}
shsurf->output = es->output;
else
shsurf->output = weston_shell_utils_get_default_output(es->compositor);
if (shsurf->output_destroy_listener.notify) {
wl_list_remove(&shsurf->output_destroy_listener.link);
@ -1564,7 +1721,7 @@ shell_surface_set_output(struct shell_surface *shsurf,
return;
shsurf->output_destroy_listener.notify = notify_output_destroy;
wl_signal_add(&shsurf->output->output->destroy_signal,
wl_signal_add(&shsurf->output->destroy_signal,
&shsurf->output_destroy_listener);
}
@ -1710,13 +1867,7 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
struct weston_surface *surface =
weston_desktop_surface_get_surface(shsurf->desktop_surface);
struct weston_compositor *ec = surface->compositor;
struct weston_output *output = NULL;
if (!shsurf->fullscreen_output)
return;
output = shsurf->fullscreen_output->output;
struct weston_output *output = shsurf->fullscreen_output;
struct weston_curtain_params curtain_params = {
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
.pos = output->pos,
@ -1731,14 +1882,14 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
weston_view_move_to_layer(shsurf->view,
&shsurf->shell->fullscreen_layer.view_list);
weston_shell_utils_center_on_output(shsurf->view, output);
weston_shell_utils_center_on_output(shsurf->view, shsurf->fullscreen_output);
if (!shsurf->fullscreen.black_view) {
shsurf->fullscreen.black_view =
weston_shell_utils_curtain_create(ec, &curtain_params);
}
weston_view_set_output(shsurf->fullscreen.black_view->view,
output);
shsurf->fullscreen_output);
weston_view_move_to_layer(shsurf->fullscreen.black_view->view,
&shsurf->view->layer_link);
@ -1904,8 +2055,8 @@ fade_out_done(struct weston_view_animation *animation, void *data)
if (weston_view_is_mapped(shsurf->wview_anim_fade)) {
weston_view_move_to_layer(shsurf->wview_anim_fade, NULL);
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
}
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
}
struct shell_surface *
@ -2118,13 +2269,8 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf)
shell_surface_update_layer(shsurf);
if (shsurf->state.maximized) {
struct weston_output *w_output = NULL;
if (shsurf->output)
w_output = shsurf->output->output;
surface->output = w_output;
weston_view_set_output(shsurf->view, w_output);
surface->output = shsurf->output;
weston_view_set_output(shsurf->view, shsurf->output);
}
if (!shell->locked) {
@ -2230,12 +2376,8 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
WESTON_ACTIVATE_FLAG_FULLSCREEN);
}
} else if (shsurf->state.maximized) {
struct weston_output *w_output = NULL;
set_maximized_position(shell, shsurf);
if (surface->output)
w_output = shsurf->output->output;
surface->output = w_output;
surface->output = shsurf->output;
} else {
struct weston_coord_surface offset = buf_offset;
struct weston_coord_global pos;
@ -2635,13 +2777,7 @@ background_committed(struct weston_surface *es,
struct weston_coord_surface new_origin)
{
struct shell_output *sh_output = es->committed_private;
struct desktop_shell *shell;
/* The output was destroyed before the background was committed */
if (!sh_output)
return;
shell = sh_output->shell;
struct desktop_shell *shell = sh_output->shell;
if (!weston_surface_has_content(es))
return;
@ -2657,7 +2793,6 @@ background_committed(struct weston_surface *es,
sh_output->output->pos);
weston_view_move_to_layer(sh_output->background_view,
&shell->background_layer.view_list);
weston_output_set_ready(sh_output->output);
}
static void
@ -2677,6 +2812,7 @@ desktop_shell_set_background(struct wl_client *client,
struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
struct desktop_shell *shell = wl_resource_get_user_data(resource);
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
struct shell_output *sh_output;
@ -2693,7 +2829,7 @@ desktop_shell_set_background(struct wl_client *client,
return;
surface->output = head->output;
sh_output = weston_output_get_shell_private(surface->output);
sh_output = find_shell_output_from_weston_output(shell, surface->output);
if (sh_output->background_surface) {
wl_resource_post_error(surface_resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
@ -2730,17 +2866,9 @@ panel_committed(struct weston_surface *es,
struct weston_coord_surface new_origin)
{
struct shell_output *sh_output = es->committed_private;
struct weston_output *output;
struct weston_coord_global pos;
struct desktop_shell *shell;
/* The output was destroyed before the panel was committed */
if (!sh_output)
return;
output = sh_output->output;
pos = output->pos;
shell = sh_output->shell;
struct weston_output *output = sh_output->output;
struct weston_coord_global pos = output->pos;
struct desktop_shell *shell = sh_output->shell;
if (!weston_surface_has_content(es))
return;
@ -2767,14 +2895,13 @@ panel_committed(struct weston_surface *es,
weston_surface_map(es);
assert(wl_list_empty(&es->views));
sh_output->panel_view = weston_view_create(es);
weston_view_move_to_layer(sh_output->panel_view,
&shell->panel_layer.view_list);
}
assert(sh_output->panel_view);
pos = weston_coord_global_add(output->pos, sh_output->panel_offset);
weston_view_set_position(sh_output->panel_view, pos);
weston_view_move_to_layer(sh_output->panel_view,
&shell->panel_layer.view_list);
}
static void
@ -2795,6 +2922,7 @@ desktop_shell_set_panel(struct wl_client *client,
struct wl_resource *output_resource,
struct wl_resource *surface_resource)
{
struct desktop_shell *shell = wl_resource_get_user_data(resource);
struct weston_surface *surface =
wl_resource_get_user_data(surface_resource);
struct shell_output *sh_output;
@ -2811,7 +2939,7 @@ desktop_shell_set_panel(struct wl_client *client,
return;
surface->output = head->output;
sh_output = weston_output_get_shell_private(surface->output);
sh_output = find_shell_output_from_weston_output(shell, surface->output);
if (sh_output->panel_surface) {
wl_resource_post_error(surface_resource,
@ -3303,6 +3431,7 @@ rotate_grab_motion(struct weston_pointer_grab *grab,
}
weston_view_update_transform(shsurf->view);
weston_surface_damage(shsurf->view->surface);
}
static void
@ -3426,7 +3555,7 @@ rotate_binding(struct weston_pointer *pointer, const struct timespec *time,
* the alt-tab switcher, which need to de-promote fullscreen layers. */
void
lower_fullscreen_layer(struct desktop_shell *shell,
struct shell_output *lowering_output)
struct weston_output *lowering_output)
{
struct workspace *ws;
struct weston_view *view, *prev;
@ -3846,6 +3975,9 @@ shell_fade_init(struct desktop_shell *shell)
if (!shell->fade.curtain)
return;
weston_view_update_transform(shell->fade.curtain->view);
weston_surface_damage(shell->fade.curtain->view->surface);
loop = wl_display_get_event_loop(shell->compositor->wl_display);
shell->fade.startup_timer =
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
@ -3915,7 +4047,6 @@ weston_view_set_initial_position(struct weston_view *view,
int32_t range_x, range_y;
int32_t x, y;
struct weston_output *output, *target_output = NULL;
struct shell_output *shoutput;
struct weston_seat *seat;
pixman_rectangle32_t area;
struct weston_coord_global pos;
@ -3953,9 +4084,7 @@ weston_view_set_initial_position(struct weston_view *view,
* If this is negative it means that the surface is bigger than
* output.
*/
assert(target_output);
shoutput = weston_output_get_shell_private(target_output);
get_output_work_area(shell, shoutput, &area);
get_output_work_area(shell, target_output, &area);
x = area.x;
y = area.y;
@ -4337,12 +4466,6 @@ shell_reposition_view_on_output_change(struct weston_view *view)
struct shell_surface *shsurf;
int visible;
/* We can't simply reposition popups and such, they must move with
* the parent.
*/
if (view->geometry.parent)
return;
if (wl_list_empty(&ec->output_list))
return;
@ -4418,18 +4541,12 @@ shell_output_destroy(struct shell_output *shell_output)
{
struct desktop_shell *shell = shell_output->shell;
if (!shell->disallow_output_changed_move) {
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
}
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
if (shell_output->panel_surface) {
if (shell_output->panel_surface)
wl_list_remove(&shell_output->panel_surface_listener.link);
shell_output->panel_surface->committed_private = NULL;
}
if (shell_output->background_surface) {
if (shell_output->background_surface)
wl_list_remove(&shell_output->background_surface_listener.link);
shell_output->background_surface->committed_private = NULL;
}
wl_list_remove(&shell_output->destroy_listener.link);
wl_list_remove(&shell_output->link);
free(shell_output);
@ -4489,7 +4606,7 @@ handle_output_resized(struct wl_listener *listener, void *data)
struct desktop_shell *shell =
container_of(listener, struct desktop_shell, resized_listener);
struct weston_output *output = (struct weston_output *)data;
struct shell_output *sh_output = weston_output_get_shell_private(output);
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
handle_output_resized_shsurfs(shell);
@ -4507,8 +4624,6 @@ create_shell_output(struct desktop_shell *shell,
if (shell_output == NULL)
return;
weston_output_set_shell_private(output, shell_output);
shell_output->output = output;
shell_output->shell = shell;
shell_output->destroy_listener.notify = handle_output_destroy;
@ -4516,7 +4631,7 @@ create_shell_output(struct desktop_shell *shell,
&shell_output->destroy_listener);
wl_list_insert(shell->output_list.prev, &shell_output->link);
if (!shell->disallow_output_changed_move && wl_list_length(&shell->output_list) == 1)
if (wl_list_length(&shell->output_list) == 1)
shell_for_each_layer(shell,
shell_output_changed_move_layer, NULL);
}
@ -4543,12 +4658,6 @@ handle_output_move_layer(struct desktop_shell *shell,
if (view->output != output)
continue;
/* We can't simply reposition popups and such, they must move with
* the parent.
*/
if (view->geometry.parent)
continue;
pos = weston_coord_global_add(
weston_view_get_pos_offset_global(view),
output->move);

View file

@ -23,9 +23,6 @@
* DEALINGS IN THE SOFTWARE.
*/
#ifndef WESTON_DESKTOP_SHELL_H
#define WESTON_DESKTOP_SHELL_H
#include <stdbool.h>
#include <stdint.h>
#include <time.h>
@ -35,169 +32,6 @@
#include "weston-desktop-shell-server-protocol.h"
struct focus_state {
struct desktop_shell *shell;
struct weston_seat *seat;
struct workspace *ws;
struct weston_surface *keyboard_focus;
struct wl_list link;
struct wl_listener seat_destroy_listener;
struct wl_listener surface_destroy_listener;
};
/*
* Surface stacking and ordering.
*
* This is handled using several linked lists of surfaces, organised into
* layers. The layers are ordered, and each of the surfaces in one layer are
* above all of the surfaces in the layer below. The set of layers is static and
* in the following order (top-most first):
* Lock layer (only ever displayed on its own)
* Cursor layer
* Input panel layer
* Fullscreen layer
* Panel layer
* Workspace layers
* Background layer
*
* The list of layers may be manipulated to remove whole layers of surfaces from
* display. For example, when locking the screen, all layers except the lock
* layer are removed.
*
* A surfaces layer is modified on configuring the surface, in
* set_surface_type() (which is only called when the surfaces type change is
* _committed_). If a surfaces type changes (e.g. when making a window
* fullscreen) its layer changes too.
*
* In order to allow popup and transient surfaces to be correctly stacked above
* their parent surfaces, each surface tracks both its parent surface, and a
* linked list of its children. When a surfaces layer is updated, so are the
* layers of its children. Note that child surfaces are *not* the same as
* subsurfaces child/parent surfaces are purely for maintaining stacking
* order.
*
* The children_link list of siblings of a surface (i.e. those surfaces which
* have the same parent) only contains weston_surfaces which have a
* shell_surface. Stacking is not implemented for non-shell_surface
* weston_surfaces. This means that the following implication does *not* hold:
* (shsurf->parent != NULL) !wl_list_is_empty(shsurf->children_link)
*/
struct shell_surface {
struct wl_signal destroy_signal;
struct weston_desktop_surface *desktop_surface;
struct weston_view *view;
struct weston_surface *wsurface_anim_fade;
struct weston_view *wview_anim_fade;
int32_t last_width, last_height;
struct desktop_shell *shell;
struct wl_list children_list;
struct wl_list children_link;
struct weston_coord_global saved_pos;
bool saved_position_valid;
bool saved_rotation_valid;
int unresponsive, grabbed;
uint32_t resize_edges;
uint32_t orientation;
struct {
struct weston_transform transform;
struct weston_matrix rotation;
} rotation;
struct {
struct weston_curtain *black_view;
} fullscreen;
struct shell_output *fullscreen_output;
struct shell_output *output;
struct wl_listener output_destroy_listener;
struct surface_state {
bool fullscreen;
bool maximized;
bool lowered;
} state;
struct {
bool is_set;
struct weston_coord_global pos;
} xwayland;
int focus_count;
bool destroying;
struct wl_list link; /** desktop_shell::shsurf_list */
};
struct shell_grab {
struct weston_pointer_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
};
struct shell_touch_grab {
struct weston_touch_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_touch *touch;
};
struct shell_tablet_tool_grab {
struct weston_tablet_tool_grab grab;
struct shell_surface *shsurf;
struct wl_listener shsurf_destroy_listener;
struct weston_tablet_tool *tool;
};
struct weston_move_grab {
struct shell_grab base;
struct weston_coord_global delta;
bool client_initiated;
};
struct weston_touch_move_grab {
struct shell_touch_grab base;
int active;
struct weston_coord_global delta;
};
struct weston_tablet_tool_move_grab {
struct shell_tablet_tool_grab base;
wl_fixed_t dx, dy;
};
struct rotate_grab {
struct shell_grab base;
struct weston_matrix rotation;
struct {
float x;
float y;
} center;
};
struct shell_seat {
struct weston_seat *seat;
struct wl_listener seat_destroy_listener;
struct weston_surface *focused_surface;
struct wl_listener caps_changed_listener;
struct wl_listener pointer_focus_listener;
struct wl_listener keyboard_focus_listener;
struct wl_listener tablet_tool_added_listener;
struct wl_list link; /** shell::seat_list */
};
struct tablet_tool_listener {
struct wl_listener base;
struct wl_listener removed_listener;
};
enum animation_type {
ANIMATION_NONE,
@ -306,7 +140,6 @@ struct desktop_shell {
} fade;
bool allow_zap;
bool disallow_output_changed_move;
uint32_t binding_modifier;
enum animation_type win_animation_type;
enum animation_type win_close_animation_type;
@ -343,12 +176,12 @@ get_current_workspace(struct desktop_shell *shell);
void
get_output_work_area(struct desktop_shell *shell,
struct shell_output *output,
struct weston_output *output,
pixman_rectangle32_t *area);
void
lower_fullscreen_layer(struct desktop_shell *shell,
struct shell_output *lowering_output);
struct weston_output *lowering_output);
void
activate(struct desktop_shell *shell, struct weston_view *view,
@ -366,5 +199,3 @@ void
shell_for_each_layer(struct desktop_shell *shell,
shell_for_each_layer_func_t func,
void *data);
#endif /* WESTON_DESKTOP_SHELL_H */

View file

@ -196,8 +196,7 @@ epub_exclude_files = ['search.html']
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
intersphinx_mapping = {'https://docs.python.org/3': None}
# -- Options for todo extension ----------------------------------------------

View file

@ -1208,6 +1208,15 @@ HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.

View file

@ -48,7 +48,7 @@ doxygen_conf_weston = configure_file(
script_data = configuration_data()
script_data.set('SRCDIR', meson.current_build_dir())
script_data.set('OUTDIR', meson.current_build_dir() / 'weston')
script_data.set('OUTDIR', meson.current_build_dir() + '/doc')
# Set a different directory for doctrees to avoid installing them
script_data.set('DOCTREES_DIR', meson.current_build_dir() + '/doctrees')
@ -82,11 +82,9 @@ endif
sphinx_doc = custom_target(
'weston-doc-breathe',
command: script_doxy_sphinx,
output: 'weston',
output: 'doc',
build_by_default: true,
env: sphinx_env,
install: true,
install_dir: dir_data / 'doc',
)
# we need this because we will have a stale 'doc' directory
@ -95,3 +93,10 @@ docs = run_target(
'docs',
command: script_doxy_sphinx,
)
install_subdir(
sphinx_doc.full_path(),
install_dir: dir_data / 'doc' / 'weston',
exclude_files: '.buildinfo',
strip_directory: true,
)

View file

@ -6,15 +6,4 @@ else
SPHINX_WERROR=""
fi
set -e
BUILDINFO_ORIG="@OUTDIR@/.buildinfo"
BUILDINFO_SAVE="@SRCDIR@/buildinfo.save"
[ -f "$BUILDINFO_SAVE" ] && mv -f "$BUILDINFO_SAVE" "$BUILDINFO_ORIG"
@DOXYGEN_CMD@ @DOXYGEN_CONF@
@SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
mv -f "$BUILDINFO_ORIG" "$BUILDINFO_SAVE"
@DOXYGEN_CMD@ @DOXYGEN_CONF@ && @SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@

View file

@ -86,8 +86,7 @@ the surface was added to. However, the views are not provided to the IVI
controller.
After configuring all expected changes, the controller must call the
``commit_changes`` to atomically update the display layout and call
``screen_ready`` to inform the compositor that it can start issueing repaints.
``commit_changes`` to atomically update the display layout.
IVI-shell example implementation
--------------------------------

View file

@ -10,7 +10,6 @@ Libweston
libweston/shell-utils.rst
libweston/output-management.rst
libweston/log.rst
libweston/debug-flight-recorder.rst
`Libweston` is an effort to separate the re-usable parts of Weston into a
library. `Libweston` provides most of the boring and tedious bits of correctly

View file

@ -1,51 +0,0 @@
.. _debugging flight recorder:
Debugging with Flight Recorder
==============================
Weston can write debug scopes data to a circular ring buffer. This ring
buffer can be accessed through a debug key, assuming you have a keyboard
attached, or in case Weston dies, through a coredump. This document describes
how to access that data in the later case.
The ring buffer data can be accessed with a gdb python script that searches
the coredump file for the that ring buffer address in order to retrieve
data from it.
Prior to setting this up make sure that flight recorder is configured
accordingly. Make sure that Weston is started with the debug scopes that
you're interested into. For instance if you'd like to get the :samp:`drm-backend` one
Weston should show when starting up:
::
Flight recorder: enabled, scopes subscribed: drm-backend
For that Weston needs to be started with :samp:`--debug -f drm-backend`.
Also, make sure that the system is configured to generate a core dump. Refer
to :samp:`man core(5)` for how to do that.
Next you'll need the `gdb python
script <https://gitlab.freedesktop.org/wayland/weston/-/blob/main/doc/scripts/gdb/flight_rec.py>`_,
as that will be needed to search for the ring buffer within the coredump.
Finally, to make this easier and push everything from the ring buffer to a
file, we would need to create a batch gdb file script to invoke the commands
for us.
As an example name that file :file:`test.gdb` and add the following to entries
to it, making sure to adjust the path for the python script.
::
source /path/to/flight_rec.py
display_flight_rec
Then run the following commands to dump the contents of the ring buffer
straight to a file:
::
$ gdb --batch --command=/path/to/test.gdb -q /path/to/test/weston/binary --core /path/to/coredump &> dump.log.txt

View file

@ -141,9 +141,8 @@ force the contents to be printed on :samp:`stdout` file-descriptor.
The user has first to specify which log scope to subscribe to.
Specifying which scopes to subscribe for the flight-recorder can be done using
:samp:`-f|--flight-rec-scopes`. By default, only the 'log' scope is subscribed
to. See :ref:`debugging flight recorder` on how retrieve the contents of the
flight recorder in case Weston dies/crashes unexpectedly.
:samp:`--flight-rec-scopes`. By default, the 'log' scope and 'drm-backend' are
the scopes subscribed to.
weston-debug protocol
~~~~~~~~~~~~~~~~~~~~~
@ -179,13 +178,6 @@ The following illustrates how to use it:
./weston-debug timeline > log.json
./wesgr -i log.json -o log.svg
Weston has experimental support for `Perfetto <https://perfetto.dev>`_ for
performance profiling. It can be enabled by using `-Dperfetto=true` during
the meson invocation to configure the build.
If Perfetto support is built in, timeline points are added to Perfetto tracks
when Perfetto is running, even when the 'timeline' scope is not enabled.
Inserting timeline points
~~~~~~~~~~~~~~~~~~~~~~~~~
@ -194,13 +186,6 @@ take the :type:`weston_compositor` instance, followed by the name of the
timeline point. What follows next is a variable number of arguments, which
**must** end with the macro :c:macro:`TLP_END`.
Adding Perfetto trace points
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In addition to timeline points, Perfetto can also display timing information
for individual functions. The easiest way to add profiling data for a function
is to insert the :c:macro:`WESTON_TRACE_FUNC` at the top of the function.
Debug protocol API
------------------

View file

@ -2,7 +2,6 @@
files = [
'compositor.rst',
'head.rst',
'debug-flight-recorder.rst',
'log.rst',
'output.rst',
'output-management.rst',

View file

@ -35,15 +35,12 @@ stitching them together is performed by a *renderer*. By doing so, it is
compositing all surfaces into a single image, which is being handed out to a
back-end, and finally, displayed on the screen.
libweston provides multiple useful renderers. There are
`OpenGL ES <https://www.khronos.org/opengles/>`_ and
`Vulkan <https://www.vulkan.org/>`_ renderers, which will often be accelerated
by your GPU when suitable drivers are installed.
Another uses the `Pixman <http://www.pixman.org>`_ library which is entirely
CPU (software) rendered.
You can select between these with the ``--renderer=gl``, ``--renderer=vulkan``
and ``--renderer=pixman`` arguments when starting Weston.
libweston provides two useful renderers. One uses
`OpenGL ES <https://www.khronos.org/opengles/>`_, which will often be accelerated
by your GPU when suitable drivers are installed. The other uses the
`Pixman <http://www.pixman.org>`_ library which is entirely CPU (software)
rendered. You can select between these with the ``--renderer=gl`` and
``--renderer=pixman`` arguments when starting Weston.
Multi-back-end support
----------------------

View file

@ -90,8 +90,7 @@ Standalone tests
Standalone tests do not have a fixture setup function defined in the test
program or the fixture setup function calls
:func:`weston_test_harness_execute_standalone` explicitly. All test cases must
be defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
return a value from :type:`test_result_code`.
be defined with :c:func:`TEST` or :c:func:`TEST_P`.
This is the simplest possible test example:
@ -99,7 +98,7 @@ This is the simplest possible test example:
TEST(always_success)
{
return RESULT_OK;
/* true */
}
@ -111,8 +110,7 @@ Plugin tests
Plugin tests must have a fixture setup function that calls
:func:`weston_test_harness_execute_as_plugin`. All test cases must be defined
with :c:func:`PLUGIN_TEST` which declares an implicit function argument
:type:`weston_compositor` ``*compositor``. Each such function must
return a value from :type:`test_result_code`.
:type:`weston_compositor` ``*compositor``.
The compositor fixture manufactures the necessary environment variables and the
command line argument array to launch Weston, and calls :func:`wet_main`
@ -139,7 +137,6 @@ This is an example of a plugin test that just logs a line:
{
/* struct weston_compositor *compositor; */
testlog("Got compositor %p\n", compositor);
return RESULT_OK;
}
@ -150,8 +147,7 @@ Client tests
Plugin tests must have a fixture setup function that calls
:func:`weston_test_harness_execute_as_client`. All test cases must be
defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
return a value from :type:`test_result_code`.
defined with :c:func:`TEST` or :c:func:`TEST_P`.
The compositor fixture manufactures the necessary environment variables and the
command line argument array to launch Weston, and calls :func:`wet_main`
@ -206,7 +202,6 @@ clients:
expect_protocol_error(client, &wp_viewport_interface,
WP_VIEWPORT_ERROR_BAD_VALUE);
return RESULT_OK;
}
TEST(test_roundtrip)
@ -215,7 +210,6 @@ clients:
client = create_client_and_test_surface(100, 50, 123, 77);
client_roundtrip(client);
return RESULT_OK;
}
@ -263,6 +257,15 @@ type of tests to keep the fixture setup simple. See
:ref:`test-suite-standalone`, :ref:`test-suite-plugin` and
:ref:`test-suite-client` how to set up each type in a test program.
.. note::
**TODO:** Currently it is not possible to gracefully skip or fail a test.
You can skip with ``exit(RESULT_SKIP)`` but that will quit the whole test
program and all defined tests that were not ran yet will be counted as
failed. You can fail a test by any means, e.g. ``exit(RESULT_FAIL)``, but
the same caveat applies. Succeeded tests must simply return and not call any
exit function.
.. toctree::
:hidden:

View file

@ -31,7 +31,6 @@
#include <libweston/config-parser.h>
#include "shared/helpers.h"
#include "shared/string-helpers.h"
#include "weston-private.h"
struct {
@ -65,10 +64,12 @@ get_backend_from_string(const char *name,
return false;
}
static const struct weston_enum_map renderer_name_map[] = {
struct {
char *name;
enum weston_renderer_type renderer;
} renderer_name_map[] = {
{ "auto", WESTON_RENDERER_AUTO },
{ "gl", WESTON_RENDERER_GL },
{ "vulkan", WESTON_RENDERER_VULKAN },
{ "noop", WESTON_RENDERER_NOOP },
{ "pixman", WESTON_RENDERER_PIXMAN },
};
@ -77,15 +78,16 @@ bool
get_renderer_from_string(const char *name,
enum weston_renderer_type *renderer)
{
const struct weston_enum_map *entry;
size_t i;
if (!name)
name = "auto";
entry = weston_enum_map_find_name(renderer_name_map, name);
if (entry) {
*renderer = entry->value;
return true;
for (i = 0; i < ARRAY_LENGTH(renderer_name_map); i++) {
if (strcmp(name, renderer_name_map[i].name) == 0) {
*renderer = renderer_name_map[i].renderer;
return true;
}
}
return false;

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,6 @@ deps_weston = [
dep_libevdev,
dep_libdl,
dep_threads,
dep_libdisplay_info,
]
if get_option('xwayland')
@ -68,8 +67,7 @@ install_data(
install_dir: dir_data / 'wayland-sessions'
)
if get_option('deprecated-screenshare') and get_option('deprecated-shell-fullscreen')
warning('deprecated-screenshare. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848. Consider using mirroring (see man page) for same functionality and better performance.')
if get_option('screenshare')
srcs_screenshare = [
'screen-share.c',
fullscreen_shell_unstable_v1_client_protocol_h,

View file

@ -371,13 +371,7 @@ ss_seat_create(struct shared_output *so, uint32_t id)
if (seat == NULL)
return NULL;
if (so->output) {
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
} else {
weston_log("Skip seat creation the screen share output has not an output compositor\n");
return NULL;
}
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
seat->output = so;
seat->id = id;
seat->parent.seat = wl_registry_bind(so->parent.registry, id,
@ -976,8 +970,6 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
if (!so->parent.display)
goto err_alloc;
/* Set Weston output reference in the shared output before registry */
so->output = output;
so->parent.registry = wl_display_get_registry(so->parent.display);
if (!so->parent.registry)
goto err_display;
@ -1041,6 +1033,7 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
wl_list_init(&so->shm.buffers);
wl_list_init(&so->shm.free_buffers);
so->output = output;
so->output_destroyed.notify = output_destroyed;
wl_signal_add(&so->output->destroy_signal, &so->output_destroyed);
@ -1086,8 +1079,7 @@ shared_output_destroy(struct shared_output *so)
wl_list_remove(&so->output_destroyed.link);
wl_list_remove(&so->frame_listener.link);
if (so->cache_image)
pixman_image_unref(so->cache_image);
pixman_image_unref(so->cache_image);
free(so->tmp_data);
free(so);

View file

@ -53,8 +53,3 @@ wet_output_set_colorimetry_mode(struct weston_output *output,
typedef void (*wet_head_additional_setup)(struct weston_head *head,
struct weston_head *head_to_mirror);
struct weston_color_profile *
wet_create_output_color_profile(struct weston_output *output,
struct weston_config *wc,
const char *prof_name);

View file

@ -260,10 +260,8 @@ wet_load_xwayland(struct weston_compositor *comp)
wxw->compositor = comp;
wxw->api = api;
wxw->xwayland = xwayland;
if (api->listen(xwayland, wxw, spawn_xserver) < 0) {
free(wxw);
if (api->listen(xwayland, wxw, spawn_xserver) < 0)
return NULL;
}
return wxw;
}

View file

@ -353,8 +353,6 @@ fs_output_create(struct fullscreen_shell *shell, struct weston_output *output)
}
}
weston_output_set_ready(output);
return fsout;
}

View file

@ -1,6 +1,4 @@
if get_option('deprecated-shell-fullscreen')
warning('deprecated-shell-fullscreen enabled. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848')
if get_option('shell-fullscreen')
srcs_shell_fullscreen = [
'fullscreen-shell.c',
fullscreen_shell_unstable_v1_server_protocol_h,

View file

@ -258,14 +258,6 @@ struct weston_drm_backend_config {
* rendering device.
*/
char *additional_devices;
/** Try to offload blend-to-output color transformation
*
* As KMS currently only supports to offload the transformation in a
* LUT, this may result in precision issues. Also, this requires
* "color-management" to be enabled.
*/
bool offload_blend_to_output;
};
#ifdef __cplusplus

View file

@ -49,11 +49,6 @@ struct weston_headless_backend_config {
* mHz to 1,000,000 mHz. 0 is a special value that triggers repaints
* only on capture requests, not on damages. */
int refresh;
/** Create a fake seat, some clients may complain without a wl_seat.
* The default is not to create a wl_seat.
*/
bool fake_seat;
};
#ifdef __cplusplus

View file

@ -54,20 +54,19 @@ struct weston_pipewire_output_api {
const char *name,
const struct pipewire_config *config);
/** Set the size and frame rate of a PipeWire output to the specified value.
/** Set the size of a PipeWire output to the specified width and height.
*
* If the width or height or framerate are set to -1, the size or frame rate
* of the underlying PipeWire head will be used.
* If the width or height are set to -1, the size of the underlying
* PipeWire head will be used.
*
* \param output The weston output for which the size shall be set
* \param width Desired width of the output
* \param height Desired height of the output
* \param framerate Desired frame rate of the output
*
* Returns 0 on success, -1 on failure.
*/
int (*output_set_size)(struct weston_output *output,
int width, int height, int framerate);
int width, int height);
/** The pixel format to be used by the output.
*

View file

@ -1,358 +0,0 @@
/*
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2012-2025 Collabora, Ltd.
* Copyright © 2017, 2018 General Electric Company
*
* 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.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
#include <libweston/linalg-3.h>
struct weston_compositor;
struct weston_color_profile_param_builder;
struct weston_color_profile;
struct weston_color_transform;
/** Colorimetry mode for outputs and heads
*
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* Default (RGB) colorimetry differs from all the others in that the signal
* colorimetry is not defined here. It is defined by the video sink, and it
* may be described in e.g. EDID.
*/
enum weston_colorimetry_mode {
/** Invalid colorimetry mode, or none supported. */
WESTON_COLORIMETRY_MODE_NONE = 0,
/** Default (RGB) colorimetry, video sink dependant */
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
/** Rec. ITU-R BT.2020 RGB */
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
/** SMPTE ST 2113 DCI-P3 RGB D65 */
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
/** SMPTE ST 2113 DCI-P3 RGB Theater */
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
};
/** Bitmask of all defined colorimetry modes */
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
WESTON_COLORIMETRY_MODE_P3D65 | \
WESTON_COLORIMETRY_MODE_P3DCI | \
WESTON_COLORIMETRY_MODE_ICTCP))
const char *
weston_colorimetry_mode_to_str(enum weston_colorimetry_mode c);
/** EOTF mode for outputs and heads
*
* A list of EOTF modes for driving displays, defined by CTA-861-G for
* Dynamic Range and Mastering InfoFrame.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
*/
enum weston_eotf_mode {
/** Invalid EOTF mode, or none supported. */
WESTON_EOTF_MODE_NONE = 0,
/** Traditional gamma, SDR luminance range */
WESTON_EOTF_MODE_SDR = 0x01,
/** Traditional gamma, HDR luminance range */
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
/** Preceptual quantizer, SMPTE ST 2084 */
WESTON_EOTF_MODE_ST2084 = 0x04,
/** Hybrid log-gamma, ITU-R BT.2100 */
WESTON_EOTF_MODE_HLG = 0x08,
};
/** Bitmask of all defined EOTF modes */
#define WESTON_EOTF_MODE_ALL_MASK \
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
const char *
weston_eotf_mode_to_str(enum weston_eotf_mode e);
/** CIE 1931 xy chromaticity coordinates */
struct weston_CIExy {
float x;
float y;
};
/** Chromaticity coordinates and white point that defines the color gamut */
struct weston_color_gamut {
struct weston_CIExy primary[3]; /* RGB order */
struct weston_CIExy white_point;
};
enum weston_npm_direction {
WESTON_NPM_FORWARD,
WESTON_NPM_INVERSE
};
bool
weston_normalized_primary_matrix_init(struct weston_mat3f *npm,
const struct weston_color_gamut *gamut,
enum weston_npm_direction dir);
struct weston_mat3f
weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to);
/** Color primaries known by libweston */
enum weston_color_primaries {
WESTON_PRIMARIES_CICP_SRGB = 0,
WESTON_PRIMARIES_CICP_PAL_M,
WESTON_PRIMARIES_CICP_PAL,
WESTON_PRIMARIES_CICP_NTSC,
WESTON_PRIMARIES_CICP_GENERIC_FILM,
WESTON_PRIMARIES_CICP_BT2020,
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
WESTON_PRIMARIES_CICP_DCI_P3,
WESTON_PRIMARIES_CICP_DISPLAY_P3,
WESTON_PRIMARIES_ADOBE_RGB,
};
/** Transfer functions known by libweston */
enum weston_transfer_function {
WESTON_TF_BT1886 = 0,
WESTON_TF_GAMMA22,
WESTON_TF_GAMMA28,
WESTON_TF_SRGB,
WESTON_TF_EXT_SRGB,
WESTON_TF_ST240,
WESTON_TF_ST428,
WESTON_TF_ST2084_PQ,
WESTON_TF_EXT_LINEAR,
WESTON_TF_LOG_100,
WESTON_TF_LOG_316,
WESTON_TF_XVYCC,
WESTON_TF_HLG,
WESTON_TF_POWER,
};
enum weston_alpha_mode {
WESTON_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL = 0,
WESTON_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
WESTON_ALPHA_MODE_STRAIGHT,
};
enum weston_color_matrix_coef {
WESTON_COLOR_MATRIX_COEF_UNSET = 0,
WESTON_COLOR_MATRIX_COEF_IDENTITY,
WESTON_COLOR_MATRIX_COEF_BT601,
WESTON_COLOR_MATRIX_COEF_BT709,
WESTON_COLOR_MATRIX_COEF_BT2020,
};
enum weston_color_quant_range {
WESTON_COLOR_QUANT_RANGE_UNSET = 0,
WESTON_COLOR_QUANT_RANGE_FULL,
WESTON_COLOR_QUANT_RANGE_LIMITED,
};
enum weston_ycbcr_chroma_location {
WESTON_YCBCR_CHROMA_LOCATION_UNSET = 0,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_0,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_1,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_2,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_3,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_4,
WESTON_YCBCR_CHROMA_LOCATION_TYPE_5,
};
/** Error codes that the color profile parameters functions may return. */
enum weston_color_profile_param_builder_error {
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES_NAMED,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CREATE_FAILED,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
};
struct weston_color_profile_param_builder *
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
void
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
bool
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
bool
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *primaries);
bool
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries primaries);
bool
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
enum weston_transfer_function tf);
bool
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
float power_exponent);
bool
weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder,
float ref_lum, float min_lum, float max_lum);
bool
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *target_primaries);
bool
weston_color_profile_param_builder_set_target_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries target_primaries);
bool
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
float min_lum, float max_lum);
bool
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
float maxFALL);
bool
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
float maxCLL);
struct weston_color_profile *
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
const char *name_part,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
enum weston_color_characteristics_groups {
/** weston_color_characteristics::primary is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
/** weston_color_characteristics::white is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
/** weston_color_characteristics::max_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
/** weston_color_characteristics::min_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
/** weston_color_characteristics::maxFALL is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
/** all valid bits */
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
};
/** Basic display color characteristics
*
* This is a simple description of a display or output (monitor) color
* characteristics. The parameters can be found in EDID, with caveats. They
* are particularly useful with HDR monitors.
*/
struct weston_color_characteristics {
/** Which fields are valid
*
* A bitmask of values from enum weston_color_characteristics_groups.
*/
uint32_t group_mask;
/* EOTF is tracked externally with enum weston_eotf_mode */
/** Chromaticities of the primaries */
struct weston_CIExy primary[3];
/** White point chromaticity */
struct weston_CIExy white;
/** Display's desired maximum content peak luminance, cd/m² */
float max_luminance;
/** Display's desired minimum content luminance, cd/m² */
float min_luminance;
/** Display's desired maximum frame-average light level, cd/m² */
float maxFALL;
};
struct weston_color_profile *
weston_color_profile_ref(struct weston_color_profile *cprof);
void
weston_color_profile_unref(struct weston_color_profile *cprof);
const char *
weston_color_profile_get_description(struct weston_color_profile *cprof);
char *
weston_color_profile_get_details(struct weston_color_profile *cprof);
struct weston_color_profile *
weston_compositor_load_icc_file(struct weston_compositor *compositor,
const char *path);
#ifdef __cplusplus
}
#endif

View file

@ -32,7 +32,6 @@ extern "C" {
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#define WESTON_CONFIG_FILE_ENV_VAR "WESTON_CONFIG_FILE"
@ -108,20 +107,6 @@ int weston_config_next_section(struct weston_config *config,
uint32_t
weston_config_get_binding_modifier(struct weston_config *config, uint32_t default_mod);
/** Container for an array of strings. */
struct weston_string_array {
/** Length of \c array. */
size_t len;
/** Pointer to an array of strings. */
char **array;
};
void
weston_string_array_fini(struct weston_string_array *strarr);
struct weston_string_array
weston_parse_space_separated_list(const char *str);
#ifdef __cplusplus
}
#endif

View file

@ -43,7 +43,6 @@ extern "C" {
#include <libweston/matrix.h>
#include <libweston/zalloc.h>
#include <libweston/colorimetry.h>
struct weston_log_pacer {
/** This must be set to zero before first use */
@ -74,12 +73,6 @@ struct weston_point2d_device_normalized {
double y;
};
struct weston_commit_timing_target {
bool valid;
bool satisfied;
struct timespec time;
};
struct weston_compositor;
struct weston_surface;
struct weston_buffer;
@ -92,6 +85,9 @@ struct linux_dmabuf_buffer;
struct weston_recorder;
struct weston_pointer_constraint;
struct ro_anonymous_file;
struct weston_color_profile_param_builder;
struct weston_color_profile;
struct weston_color_transform;
struct pixel_format_info;
struct weston_output_capture_info;
struct weston_output_color_outcome;
@ -111,13 +107,9 @@ enum weston_keyboard_locks {
};
enum weston_led {
WESTON_LED_NUM_LOCK = (1 << 0),
WESTON_LED_CAPS_LOCK = (1 << 1),
WESTON_LED_SCROLL_LOCK = (1 << 2),
#ifdef HAVE_COMPOSE_AND_KANA
WESTON_LED_COMPOSE = (1 << 3),
WESTON_LED_KANA = (1 << 4),
#endif
LED_NUM_LOCK = (1 << 0),
LED_CAPS_LOCK = (1 << 1),
LED_SCROLL_LOCK = (1 << 2),
};
enum weston_mode_aspect_ratio {
@ -137,17 +129,6 @@ enum weston_surface_protection_mode {
WESTON_SURFACE_PROTECTION_MODE_ENFORCED
};
enum weston_output_color_effect_type {
WESTON_OUTPUT_COLOR_EFFECT_TYPE_INVERSION = 0,
WESTON_OUTPUT_COLOR_EFFECT_TYPE_CVD_CORRECTION,
};
enum weston_cvd_correction_type {
WESTON_CVD_CORRECTION_TYPE_DEUTERANOPIA = 0,
WESTON_CVD_CORRECTION_TYPE_PROTANOPIA,
WESTON_CVD_CORRECTION_TYPE_TRITANOPIA,
};
/** Possible mode of an output
*
* \ingroup output
@ -166,6 +147,7 @@ struct weston_animation {
void (*frame)(struct weston_animation *animation,
struct weston_output *output,
const struct timespec *time);
int frame_counter;
struct wl_list link;
};
@ -217,12 +199,10 @@ enum weston_hdcp_protection {
* \ingroup testharness
*/
struct weston_testsuite_quirks {
/** Force GL/Vulkan-renderer to do a full upload of wl_shm buffers. */
bool force_full_upload;
/** Force GL-renderer to do a full upload of wl_shm buffers. */
bool gl_force_full_upload;
/** Ensure GL shadow fb is used, and always repaint it fully. */
bool gl_force_full_redraw_of_shadow_fb;
/** Force GL-renderer to use the internal YUV->RGB shader */
bool gl_force_import_yuv_fallback;
/** Required enum weston_capability bit mask, otherwise skip run. */
uint32_t required_capabilities;
};
@ -245,6 +225,248 @@ struct weston_testsuite_data {
void *test_private_data;
};
/** Colorimetry mode for outputs and heads
*
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* Default (RGB) colorimetry differs from all the others in that the signal
* colorimetry is not defined here. It is defined by the video sink, and it
* may be described in e.g. EDID.
*/
enum weston_colorimetry_mode {
/** Invalid colorimetry mode, or none supported. */
WESTON_COLORIMETRY_MODE_NONE = 0,
/** Default (RGB) colorimetry, video sink dependant */
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
/** Rec. ITU-R BT.2020 RGB */
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
/** SMPTE ST 2113 DCI-P3 RGB D65 */
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
/** SMPTE ST 2113 DCI-P3 RGB Theater */
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
};
/** Bitmask of all defined colorimetry modes */
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
WESTON_COLORIMETRY_MODE_P3D65 | \
WESTON_COLORIMETRY_MODE_P3DCI | \
WESTON_COLORIMETRY_MODE_ICTCP))
/** EOTF mode for outputs and heads
*
* A list of EOTF modes for driving displays, defined by CTA-861-G for
* Dynamic Range and Mastering InfoFrame.
*
* On heads, a bitmask of one or more entries shows which modes are claimed
* supported.
*
* On outputs, the mode to be used for driving the video sink.
*
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
*/
enum weston_eotf_mode {
/** Invalid EOTF mode, or none supported. */
WESTON_EOTF_MODE_NONE = 0,
/** Traditional gamma, SDR luminance range */
WESTON_EOTF_MODE_SDR = 0x01,
/** Traditional gamma, HDR luminance range */
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
/** Preceptual quantizer, SMPTE ST 2084 */
WESTON_EOTF_MODE_ST2084 = 0x04,
/** Hybrid log-gamma, ITU-R BT.2100 */
WESTON_EOTF_MODE_HLG = 0x08,
};
/** Bitmask of all defined EOTF modes */
#define WESTON_EOTF_MODE_ALL_MASK \
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
/** CIE 1931 xy chromaticity coordinates */
struct weston_CIExy {
float x;
float y;
};
/** Chromaticity coordinates and white point that defines the color gamut */
struct weston_color_gamut {
struct weston_CIExy primary[3]; /* RGB order */
struct weston_CIExy white_point;
};
/** Color primaries known by libweston */
enum weston_color_primaries {
WESTON_PRIMARIES_CICP_SRGB = 0,
WESTON_PRIMARIES_CICP_PAL_M,
WESTON_PRIMARIES_CICP_PAL,
WESTON_PRIMARIES_CICP_NTSC,
WESTON_PRIMARIES_CICP_GENERIC_FILM,
WESTON_PRIMARIES_CICP_BT2020,
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
WESTON_PRIMARIES_CICP_DCI_P3,
WESTON_PRIMARIES_CICP_DISPLAY_P3,
WESTON_PRIMARIES_ADOBE_RGB,
};
/** Transfer functions known by libweston */
enum weston_transfer_function {
WESTON_TF_LINEAR = 0,
WESTON_TF_GAMMA22,
WESTON_TF_GAMMA28,
WESTON_TF_SRGB,
WESTON_TF_EXT_SRGB,
WESTON_TF_BT709,
WESTON_TF_BT1361,
WESTON_TF_ST240,
WESTON_TF_ST428,
WESTON_TF_ST2084_PQ,
WESTON_TF_LOG_100,
WESTON_TF_LOG_316,
WESTON_TF_XVYCC,
WESTON_TF_HLG,
WESTON_TF_POWER,
};
/** Error codes that the color profile parameters functions may return. */
enum weston_color_profile_param_builder_error {
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TARGET_PRIMARIES,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
};
struct weston_color_profile_param_builder *
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
void
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
bool
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
bool
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *primaries);
bool
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries primaries);
bool
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
enum weston_transfer_function tf);
bool
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
float power_exponent);
bool
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *target_primaries);
bool
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
float min_luminance, float max_luminance);
bool
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
float maxFALL);
bool
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
float maxCLL);
struct weston_color_profile *
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
const char *name_part,
enum weston_color_profile_param_builder_error *err,
char **err_msg);
enum weston_color_characteristics_groups {
/** weston_color_characteristics::primary is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
/** weston_color_characteristics::white is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
/** weston_color_characteristics::max_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
/** weston_color_characteristics::min_luminance is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
/** weston_color_characteristics::maxFALL is set */
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
/** all valid bits */
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
};
/** Basic display color characteristics
*
* This is a simple description of a display or output (monitor) color
* characteristics. The parameters can be found in EDID, with caveats. They
* are particularly useful with HDR monitors.
*/
struct weston_color_characteristics {
/** Which fields are valid
*
* A bitmask of values from enum weston_color_characteristics_groups.
*/
uint32_t group_mask;
/* EOTF is tracked externally with enum weston_eotf_mode */
/** Chromaticities of the primaries */
struct weston_CIExy primary[3];
/** White point chromaticity */
struct weston_CIExy white;
/** Display's desired maximum content peak luminance, cd/m² */
float max_luminance;
/** Display's desired minimum content luminance, cd/m² */
float min_luminance;
/** Display's desired maximum frame-average light level, cd/m² */
float maxFALL;
};
/** Represents a head, usually a display connector
*
* \rst
@ -294,10 +516,6 @@ struct weston_head {
* When a client uses this request, we add the wl_resource we create to
* this list. */
struct wl_list cm_output_resource_list;
uint32_t supported_vrr_mode_mask;
uint32_t supported_color_format_mask;
};
enum weston_output_power_state {
@ -307,63 +525,12 @@ enum weston_output_power_state {
WESTON_OUTPUT_POWER_NORMAL
};
enum weston_paint_node_status {
WESTON_PAINT_NODE_CLEAN = 0,
WESTON_PAINT_NODE_OUTPUT_DIRTY = 1 << 0,
WESTON_PAINT_NODE_VIEW_DIRTY = 1 << 1,
WESTON_PAINT_NODE_VISIBILITY_DIRTY = 1 << 2,
WESTON_PAINT_NODE_PLANE_DIRTY = 1 << 3,
WESTON_PAINT_NODE_BUFFER_DIRTY = 1 << 4,
WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY = 1 << 5,
WESTON_PAINT_NODE_ALL_DIRTY = (1 << 6) - 1,
};
enum weston_vrr_mode {
/** No VRR */
WESTON_VRR_MODE_NONE = 0,
/** Game mode VRR */
WESTON_VRR_MODE_GAME = 1 << 0,
};
#define WESTON_VRR_MODE_ALL_MASK \
((uint32_t)(WESTON_VRR_MODE_GAME))
enum weston_color_format {
/** Driver assigned color format automatically */
WESTON_COLOR_FORMAT_AUTO = (1 << 0),
/** Force RGB color format */
WESTON_COLOR_FORMAT_RGB = (1 << 1),
/** Force YUV color format with 4:2:2 susampling */
WESTON_COLOR_FORMAT_YUV422 = (1 << 2),
/** Force YUV color format with no subsampling */
WESTON_COLOR_FORMAT_YUV444 = (1 << 3),
/** Force YUV color format with 4:2:0 subsampling */
WESTON_COLOR_FORMAT_YUV420 = (1 << 4),
};
/** Bitmask of all defined color formats */
#define WESTON_COLOR_FORMAT_ALL_MASK \
((uint32_t)(WESTON_COLOR_FORMAT_AUTO | WESTON_COLOR_FORMAT_RGB | \
WESTON_COLOR_FORMAT_YUV444 | WESTON_COLOR_FORMAT_YUV422 | \
WESTON_COLOR_FORMAT_YUV420))
struct weston_plane {
struct weston_compositor *compositor;
int32_t x, y;
struct wl_list link;
};
/** State of the repaint loop
*
* \ingroup output
*/
enum weston_repaint_status {
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
};
/** Content producer for heads
*
* \rst
@ -375,8 +542,6 @@ struct weston_output {
uint32_t id;
char *name;
void *shell_private;
struct weston_backend *backend;
/** Matches the lifetime from the user perspective */
@ -391,9 +556,6 @@ struct weston_output {
/* struct weston_paint_node::output_link */
struct wl_list paint_node_list;
/** Only valid during repaint: changes for this repaint */
enum weston_paint_node_status paint_node_changes;
/** From global to output buffer coordinates. */
struct weston_matrix matrix;
/** From output buffer to global coordinates. */
@ -403,10 +565,6 @@ struct weston_output {
struct weston_coord_global pos;
int32_t width, height;
uint64_t gpu_track_id;
uint64_t paint_track_id;
uint64_t presentation_track_id;
/** List of paint nodes in z-order, from top to bottom, maybe pruned
*
* struct weston_paint_node::z_order_link
@ -434,34 +592,24 @@ struct weston_output {
bool repaint_only_on_capture;
/** State of the repaint loop */
enum weston_repaint_status repaint_status;
enum {
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
} repaint_status;
/** If repaint_status is REPAINT_SCHEDULED, contains the time the
* next repaint should be run */
struct timespec next_repaint;
/** If repaint_statue is REPAINT_SCHEDULED, contains the time the
* next repaint should be displayed */
struct timespec next_present;
/** commit-timing protocol will set this for the closest requested
* presentation time from a surface on this output. It's only
* valid during weston_repaint_timer_arm. */
struct weston_commit_timing_target requested_present;
/** commit-timing protocol will set this when state containing
* a target time is applied. Weston will try to hit this time if
* VRR is in use.
*/
struct weston_commit_timing_target forced_present;
/** For cancelling the idle_repaint callback on output destruction. */
struct wl_event_source *idle_repaint_source;
struct wl_signal frame_signal;
struct wl_signal post_latch_signal;
struct wl_signal destroy_signal; /**< sent when disabled */
struct weston_coord_global move;
struct timespec frame_time; /* presentation timestamp */
uint32_t frame_flags; /* presentation flags */
uint64_t msc; /* media stream counter */
int disable_planes;
int destroying;
@ -510,6 +658,13 @@ struct weston_output {
void (*set_backlight)(struct weston_output *output, uint32_t value);
void (*set_dpms)(struct weston_output *output, enum dpms_enum level);
uint16_t gamma_size;
void (*set_gamma)(struct weston_output *output,
uint16_t size,
uint16_t *r,
uint16_t *g,
uint16_t *b);
bool enabled; /**< is in the output_list, not pending list */
struct weston_color_profile *color_profile;
@ -521,8 +676,6 @@ struct weston_output {
struct weston_output_color_outcome *color_outcome;
uint64_t color_outcome_serial;
struct weston_output_color_effect *color_effect;
int (*enable)(struct weston_output *output);
int (*disable)(struct weston_output *output);
@ -553,32 +706,11 @@ struct weston_output {
void (*detach_head)(struct weston_output *output,
struct weston_head *head);
/**
* Get the DRM formats supported by a compatible writeback connector.
*/
const struct weston_drm_format_array *(*get_writeback_formats)(struct weston_output *output);
/**
* When set, this output is a mirror-of another output. See
* mirror-of key in [output] section.
*/
struct weston_output *mirror_of;
enum weston_vrr_mode vrr_mode;
enum weston_color_format color_format;
/**
* Set by the shell to indicate there's some content for this
* output to display.
*/
bool ready;
/** Needs to rebuild the paint node z ordered list */
bool paint_node_list_needs_rebuild;
/** fifo_v1 - list of surfaces to clear next repaint */
struct wl_list fifo_barrier_surfaces;
};
enum weston_pointer_motion_mask {
@ -921,18 +1053,6 @@ struct weston_tablet {
const char *path;
};
struct weston_color_representation {
enum weston_alpha_mode alpha_mode;
enum weston_color_matrix_coef matrix_coefficients;
enum weston_color_quant_range quant_range;
enum weston_ycbcr_chroma_location chroma_location;
};
struct weston_color_representation_matrix {
struct weston_mat3f matrix;
struct weston_vec3f offset;
};
struct weston_coord_global
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
struct weston_pointer_motion_event *event);
@ -1103,10 +1223,6 @@ struct weston_xkb_info {
xkb_led_index_t num_led;
xkb_led_index_t caps_led;
xkb_led_index_t scroll_led;
#ifdef HAVE_COMPOSE_AND_KANA
xkb_led_index_t compose_led;
xkb_led_index_t kana_led;
#endif
};
struct weston_keyboard {
@ -1290,9 +1406,6 @@ enum weston_capability {
/* renderer supports color management operations */
WESTON_CAP_COLOR_OPS = 0x0040,
/* renderer supports color representation operations */
WESTON_CAP_COLOR_REP = 0x0080,
};
/* Configuration struct for a backend.
@ -1359,7 +1472,6 @@ struct weston_color_manager;
struct weston_dmabuf_feedback;
struct weston_dmabuf_feedback_format_table;
struct weston_renderer;
struct weston_content_update;
/** Main object, container-like structure which aggregates all other objects.
*
@ -1419,14 +1531,12 @@ struct weston_compositor {
struct wl_list debug_binding_list;
bool view_list_needs_rebuild;
int global_weston_surface_disambiguator; /* surface ids to avoid using PID-reuse */
uint32_t state;
struct wl_event_source *idle_source;
uint32_t idle_inhibit;
int idle_time; /* timeout, s */
int repaint_timer_fd;
struct wl_event_source *repaint_timer_source;
struct wl_event_source *repaint_timer;
const struct weston_pointer_grab_interface *default_pointer_grab;
@ -1482,9 +1592,6 @@ struct weston_compositor {
/* Whether to let the compositor run without any input device. */
bool require_input;
/* Ignore all libinput-based input devices */
bool disable_input;
/* Whether to load multiple backends. */
bool multi_backend;
@ -1508,7 +1615,6 @@ struct weston_compositor {
struct weston_log_scope *debug_scene;
struct weston_log_scope *timeline;
struct weston_log_scope *libseat_debug;
struct weston_log_filtered *advertised_log_scopes;
struct content_protection *content_protection;
@ -1520,34 +1626,6 @@ struct weston_compositor {
struct wl_global *weston_capture_v1;
struct wl_signal ask_auth;
} output_capture;
struct {
/** interval which we divide the amount of frames */
unsigned int frame_counter_interval;
/** fires with frame_counter_interval rate */
struct wl_event_source *frame_counter_timer;
} perf_surface_stats;
/* if set use this placeholder-color to use instead of the default
* grenadier one */
uint32_t placeholder_color;
bool no_xwm_decorations;
/**
* When set the compositor has latched content updates for the
* upcoming repaint, and no more updates may be applied until after
* that repaint occurs.
*/
bool latched;
struct wl_list transaction_queue_list; /* weston_transaction_queue::link */
/** commit_timing_v1 - target repaint time for content updates for
* surfaces with no output
*/
struct weston_commit_timing_target requested_repaint_fallback;
};
struct weston_solid_buffer_values {
@ -1696,6 +1774,7 @@ struct weston_view {
unsigned int click_to_activate_serial;
pixman_region32_t visible; /* Unoccluded region in global space */
float alpha; /* part of geometry, see below */
/* Surface geometry state, mutable.
@ -1759,16 +1838,11 @@ struct weston_view {
struct wl_listener output_destroy_listener;
/*
* A bitfield of outputs this view intersects - though it may not be
* visible on them.
* A more complete representation of all outputs this surface is
* displayed on.
*/
uint32_t output_mask;
/*
* A bitfield of outputs this view is visible (has unoccluded pixels) on.
*/
uint32_t output_visibility_mask;
bool is_mapped;
struct weston_log_pacer subsurface_parent_log_pacer;
};
@ -1793,11 +1867,11 @@ enum weston_surface_status {
};
struct weston_surface_state {
uint64_t flow_id;
enum weston_surface_status status;
/* wl_surface.attach */
struct weston_buffer_reference buffer_ref;
struct weston_buffer *buffer;
struct wl_listener buffer_destroy_listener;
struct weston_coord_surface buf_offset;
@ -1840,18 +1914,6 @@ struct weston_surface_state {
* color_management_surface_v1_interface.unset_image_description */
struct weston_color_profile *color_profile;
const struct weston_render_intent_info *render_intent;
/* wp_color_representation_surface_v1.set_alpha_mode */
/* wp_color_representation_surface_v1.set_coefficients_and_range */
/* wp_color_representation_surface_v1.set_chroma_location */
struct weston_color_representation color_representation;
/* wp_fifo_v1 */
bool fifo_barrier;
bool fifo_wait;
/* commit_timing_v1 */
struct weston_commit_timing_target update_time;
};
struct weston_surface_activation_data {
@ -1981,7 +2043,6 @@ struct weston_surface {
bool is_mapped, is_unmapping, is_mapping;
bool is_opaque;
uint32_t s_id;
/* An list of per seat pointer constraints. */
struct wl_list pointer_constraints;
@ -2007,41 +2068,8 @@ struct weston_surface {
*
* When a client uses this request, we add the wl_resource we create to
* this list. */
struct wl_list cm_surface_feedback_resource_list;
struct wl_list cm_feedback_surface_resource_list;
struct wl_resource *cm_surface;
struct wl_resource *color_representation_resource;
struct weston_color_representation color_representation;
uint64_t damage_track_id;
uint64_t flow_id;
/** increments for each wl_surface::commit,
* reset after each frame counter interval */
unsigned int frame_commit_counter;
/** increments after an output repaint when parsing paint node list;
* reset as frame_commit_counter */
unsigned int painted_frame_counter;
/** computed after each frame_counter_interval */
float frame_commit_fps_counter;
float painted_frame_fps_counter;
/** Visibility won't be calculated until repaint, but we use this to
* track whether we can safely use the last repaint's visibility
* calculations when considering this surface's visibility.
*/
uint32_t output_visibility_dirty_mask;
/** fifo_v1 */
struct weston_fifo *fifo;
bool fifo_barrier; /* Cleared after display */
struct wl_list fifo_barrier_link; /* output::fifo_barrier_surfaces */
/** commit_timing_v1 */
struct weston_commit_timer *commit_timer;
};
struct weston_subsurface {
@ -2062,10 +2090,14 @@ struct weston_subsurface {
bool changed;
} position;
int has_cached_data;
struct weston_surface_state cached;
struct weston_buffer_reference cached_buffer_ref;
bool synchronized;
bool effectively_synchronized;
/* Sub-surface has been reordered; need to apply damage. */
bool reordered;
int synchronized;
/* Used for constructing the view tree */
struct wl_list unused_views;
@ -2154,10 +2186,6 @@ void
weston_view_move_to_layer(struct weston_view *view,
struct weston_layer_entry *layer);
void
weston_view_move_before_layer_entry(struct weston_view *view,
struct weston_layer_entry *layer);
void
weston_layer_init(struct weston_layer *layer,
struct weston_compositor *compositor);
@ -2189,6 +2217,8 @@ void
weston_output_schedule_repaint_reset(struct weston_output *output);
void
weston_output_schedule_repaint_restart(struct weston_output *output);
enum weston_compositor_backend
weston_get_backend_type(struct weston_backend *backend);
void
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
void
@ -2357,6 +2387,12 @@ void
weston_surface_set_size(struct weston_surface *surface,
int32_t width, int32_t height);
void
weston_surface_damage(struct weston_surface *surface);
void
weston_view_damage_below(struct weston_view *view);
void
weston_view_unmap(struct weston_view *view);
@ -2433,15 +2469,12 @@ enum weston_renderer_type {
WESTON_RENDERER_NOOP = 1,
WESTON_RENDERER_PIXMAN = 2,
WESTON_RENDERER_GL = 3,
WESTON_RENDERER_VULKAN = 4,
};
struct weston_backend *
weston_compositor_load_backend(struct weston_compositor *compositor,
enum weston_compositor_backend backend,
struct weston_backend_config *config_base);
enum weston_compositor_backend
weston_get_backend_type(struct weston_backend *backend);
void
weston_compositor_exit(struct weston_compositor *ec);
void *
@ -2666,13 +2699,6 @@ void
weston_output_set_transform(struct weston_output *output,
uint32_t transform);
void
weston_output_color_effect_inversion(struct weston_output *output);
void
weston_output_color_effect_cvd_correction(struct weston_output *output,
enum weston_cvd_correction_type type);
bool
weston_output_set_color_profile(struct weston_output *output,
struct weston_color_profile *cprof);
@ -2759,6 +2785,19 @@ void
weston_timeline_refresh_subscription_objects(struct weston_compositor *wc,
void *object);
struct weston_color_profile *
weston_color_profile_ref(struct weston_color_profile *cprof);
void
weston_color_profile_unref(struct weston_color_profile *cprof);
const char *
weston_color_profile_get_description(struct weston_color_profile *cprof);
struct weston_color_profile *
weston_compositor_load_icc_file(struct weston_compositor *compositor,
const char *path);
/** Describes who is trying to capture and which output */
struct weston_output_capture_client {
struct wl_client *client;
@ -2795,33 +2834,6 @@ int
weston_output_mode_set_native(struct weston_output *output,
struct weston_mode *mode,
int32_t scale);
int
weston_output_set_vrr_mode(struct weston_output *output,
enum weston_vrr_mode vrr_mode);
uint32_t
weston_output_get_supported_vrr_modes(struct weston_output *output);
const struct weston_drm_format_array *
weston_output_get_writeback_formats(struct weston_output *output);
void
weston_compositor_arm_surface_counter_fps(struct weston_compositor *ec);
void
weston_compositor_disarm_surface_counter_fps(struct weston_compositor *ec);
void
weston_output_set_color_format(struct weston_output *output,
enum weston_color_format color_format);
uint32_t
weston_output_get_supported_color_formats(struct weston_output *output);
void
weston_output_set_ready(struct weston_output *output);
#ifdef __cplusplus
}
#endif

View file

@ -1,228 +0,0 @@
/*
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stddef.h>
#include <math.h>
#include <libweston/linalg-types.h>
/* ================= 3-vectors and 3x3 matrices ============== */
/** Construct a column vector from elements */
#define WESTON_VEC3F(x, y, z) ((struct weston_vec3f){ .el = { (x), (y), (z) }})
/** Construct the [0, 0, 0]^T vector */
#define WESTON_VEC3F_ZERO ((struct weston_vec3f){ .el = {}})
/** Construct matrix from elements a{row}{column} */
#define WESTON_MAT3F(a00, a01, a02, \
a10, a11, a12, \
a20, a21, a22) \
((struct weston_mat3f){ .colmaj = { \
a00, a10, a20, \
a01, a11, a21, \
a02, a12, a22, \
}})
/** Construct the identity 3x3 matrix */
#define WESTON_MAT3F_IDENTITY \
((struct weston_mat3f){ .colmaj = { \
1.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 1.0f, \
}})
/** Construct a diagonal matrix */
static inline struct weston_mat3f
weston_m3f_diag(struct weston_vec3f d)
{
return WESTON_MAT3F(
d.x, 0.0f, 0.0f,
0.0f, d.y, 0.0f,
0.0f, 0.0f, d.z);
}
/** Copy the top-left 3x3 from 4x4 */
static inline struct weston_mat3f
weston_m3f_from_m4f_xyz(struct weston_mat4f M)
{
return WESTON_MAT3F(
M.col[0].el[0], M.col[1].el[0], M.col[2].el[0],
M.col[0].el[1], M.col[1].el[1], M.col[2].el[1],
M.col[0].el[2], M.col[1].el[2], M.col[2].el[2]
);
}
/** Drop w from vec4f */
static inline struct weston_vec3f
weston_v3f_from_v4f_xyz(struct weston_vec4f v)
{
return WESTON_VEC3F(v.x, v.y, v.z);
}
/** 3-vector dot product */
static inline float
weston_v3f_dot_v3f(struct weston_vec3f a, struct weston_vec3f b)
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
/**
* Convert an array of vec3f into planar format
*
* Takes an array of RGB triplets and converts it into a planar format where all R
* values come first, then all G values, then all B values.
*
* \param planar The destination array for planar data, must have space for 3 * len floats
* \param arr Array of RGB triplets as vec3f structs
* \param len Number of RGB triplets in the array
*/
static inline void
weston_v3f_array_to_planar(float *planar, const struct weston_vec3f *arr, size_t len)
{
size_t i;
for (i = 0; i < len; i++) {
planar[i ] = arr[i].r;
planar[i + len] = arr[i].g;
planar[i + 2 * len] = arr[i].b;
}
}
/** Clamp each element to the range [a, b], replacing NaN with a. */
static inline struct weston_vec3f
weston_v3f_clamp(struct weston_vec3f v, float a, float b)
{
return WESTON_VEC3F(v.x >= a ? (v.x <= b ? v.x : b) : a,
v.y >= a ? (v.y <= b ? v.y : b) : a,
v.z >= a ? (v.z <= b ? v.z : b) : a);
}
/**
* Matrix infinity-norm
*
* http://www.netlib.org/lapack/lug/node75.html
*/
static inline float
weston_m3f_inf_norm(struct weston_mat3f M)
{
unsigned row;
double infnorm = -1.0;
for (row = 0; row < 3; row++) {
unsigned col;
double sum = 0.0;
for (col = 0; col < 3; col++)
sum += fabsf(M.col[col].el[row]);
if (infnorm < sum)
infnorm = sum;
}
return infnorm;
}
/** Transpose 3x3 matrix */
static inline struct weston_mat3f
weston_m3f_transpose(struct weston_mat3f M)
{
struct weston_mat3f R;
unsigned i, j;
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
R.col[j].el[i] = M.col[i].el[j];
return R;
}
/** Matrix-vector multiplication A * b */
static inline struct weston_vec3f
weston_m3f_mul_v3f(struct weston_mat3f A, struct weston_vec3f b)
{
struct weston_vec3f result;
unsigned r;
for (r = 0; r < 3; r++) {
struct weston_vec3f row =
WESTON_VEC3F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r]);
result.el[r] = weston_v3f_dot_v3f(row, b);
}
return result;
}
/** Matrix multiplication A * B */
static inline struct weston_mat3f
weston_m3f_mul_m3f(struct weston_mat3f A, struct weston_mat3f B)
{
struct weston_mat3f result;
unsigned c;
for (c = 0; c < 3; c++)
result.col[c] = weston_m3f_mul_v3f(A, B.col[c]);
return result;
}
/** Element-wise matrix subtraction A - B */
static inline struct weston_mat3f
weston_m3f_sub_m3f(struct weston_mat3f A, struct weston_mat3f B)
{
struct weston_mat3f R;
unsigned i;
for (i = 0; i < 3 * 3; i++)
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
return R;
}
/** Element-wise scalar multiplication */
static inline struct weston_mat3f
weston_m3f_mul_scalar(struct weston_mat3f M, float scalar)
{
struct weston_mat3f R;
unsigned i;
for (i = 0; i < 3 * 3; i++)
R.colmaj[i] = scalar * M.colmaj[i];
return R;
}
bool
weston_m3f_invert(struct weston_mat3f *out, struct weston_mat3f M);
#ifdef __cplusplus
}
#endif

View file

@ -1,206 +0,0 @@
/*
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <math.h>
#include <libweston/linalg-types.h>
/* ================= 4-vectors and 4x4 matrices ============== */
/** Construct a column vector from elements */
#define WESTON_VEC4F(x, y, z, w) ((struct weston_vec4f){ .el = { (x), (y), (z), (w) }})
/** Construct the [0, 0, 0, 0]^T vector */
#define WESTON_VEC4F_ZERO ((struct weston_vec4f){ .el = {}})
/** Construct matrix from elements a{row}{column} */
#define WESTON_MAT4F(a00, a01, a02, a03, \
a10, a11, a12, a13, \
a20, a21, a22, a23, \
a30, a31, a32, a33) \
((struct weston_mat4f){ .colmaj = { \
a00, a10, a20, a30, \
a01, a11, a21, a31, \
a02, a12, a22, a32, \
a03, a13, a23, a33, \
}})
/** Construct the identity 4x4 matrix */
#define WESTON_MAT4F_IDENTITY \
((struct weston_mat4f){ .colmaj = { \
1.0f, 0.0f, 0.0f, 0.0f, \
0.0f, 1.0f, 0.0f, 0.0f, \
0.0f, 0.0f, 1.0f, 0.0f, \
0.0f, 0.0f, 0.0f, 1.0f, \
}})
/** Construct a translation matrix */
static inline struct weston_mat4f
weston_m4f_translation(float tx, float ty, float tz)
{
return WESTON_MAT4F(
1.0f, 0.0f, 0.0f, tx,
0.0f, 1.0f, 0.0f, ty,
0.0f, 0.0f, 1.0f, tz,
0.0f, 0.0f, 0.0f, 1.0f);
}
/** Construct a scaling matrix */
static inline struct weston_mat4f
weston_m4f_scaling(float sx, float sy, float sz)
{
return WESTON_MAT4F(
sx, 0.0f, 0.0f, 0.0f,
0.0f, sy, 0.0f, 0.0f,
0.0f, 0.0f, sz, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
/** Construct a 2D x-y rotation matrix
*
* \param cos_th Cosine of the counter-clockwise angle.
* \param sin_th Sine of the counter-clockwise angle.
*/
static inline struct weston_mat4f
weston_m4f_rotation_xy(float cos_th, float sin_th)
{
return WESTON_MAT4F(
cos_th, -sin_th, 0.0f, 0.0f,
sin_th, cos_th, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);
}
static inline struct weston_mat4f
weston_m4f_from_m3f_v3f(struct weston_mat3f R, struct weston_vec3f t)
{
return WESTON_MAT4F(
R.col[0].el[0], R.col[1].el[0], R.col[2].el[0], t.el[0],
R.col[0].el[1], R.col[1].el[1], R.col[2].el[1], t.el[1],
R.col[0].el[2], R.col[1].el[2], R.col[2].el[2], t.el[2],
0.0f, 0.0f, 0.0f, 1.0f
);
}
/** 4-vector dot product */
static inline float
weston_v4f_dot_v4f(struct weston_vec4f a, struct weston_vec4f b)
{
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
}
/**
* Matrix infinity-norm
*
* http://www.netlib.org/lapack/lug/node75.html
*/
static inline float
weston_m4f_inf_norm(struct weston_mat4f M)
{
unsigned row;
double infnorm = -1.0;
for (row = 0; row < 4; row++) {
unsigned col;
double sum = 0.0;
for (col = 0; col < 4; col++)
sum += fabsf(M.col[col].el[row]);
if (infnorm < sum)
infnorm = sum;
}
return infnorm;
}
/** Transpose 4x4 matrix */
static inline struct weston_mat4f
weston_m4f_transpose(struct weston_mat4f M)
{
struct weston_mat4f R;
unsigned i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
R.col[j].el[i] = M.col[i].el[j];
return R;
}
/** Matrix-vector multiplication A * b */
static inline struct weston_vec4f
weston_m4f_mul_v4f(struct weston_mat4f A, struct weston_vec4f b)
{
struct weston_vec4f result;
unsigned r;
for (r = 0; r < 4; r++) {
struct weston_vec4f row =
WESTON_VEC4F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r], A.col[3].el[r]);
result.el[r] = weston_v4f_dot_v4f(row, b);
}
return result;
}
/** Matrix multiplication A * B */
static inline struct weston_mat4f
weston_m4f_mul_m4f(struct weston_mat4f A, struct weston_mat4f B)
{
struct weston_mat4f result;
unsigned c;
for (c = 0; c < 4; c++)
result.col[c] = weston_m4f_mul_v4f(A, B.col[c]);
return result;
}
/** Element-wise matrix subtraction A - B */
static inline struct weston_mat4f
weston_m4f_sub_m4f(struct weston_mat4f A, struct weston_mat4f B)
{
struct weston_mat4f R;
unsigned i;
for (i = 0; i < 4 * 4; i++)
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
return R;
}
bool
weston_m4f_invert(struct weston_mat4f *out, struct weston_mat4f M);
#ifdef __cplusplus
}
#endif

View file

@ -1,76 +0,0 @@
/*
* Copyright 2025 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** Column 3-vector */
struct weston_vec3f {
union {
float el[3];
struct {
float x, y, z;
};
struct {
float r, g, b;
};
struct {
float Y, Cb, Cr;
};
};
};
/** 3x3 matrix, column-major */
struct weston_mat3f {
union {
struct weston_vec3f col[3];
float colmaj[3 * 3];
};
};
/** Column 4-vector */
struct weston_vec4f {
union {
float el[4];
struct {
float x, y, z, w;
};
};
};
/** 4x4 matrix, column-major */
struct weston_mat4f {
union {
struct weston_vec4f col[4];
float colmaj[4 * 4];
};
};
#ifdef __cplusplus
}
#endif

View file

@ -31,7 +31,6 @@
#include <stdbool.h>
#include <wayland-server-protocol.h>
#include <libweston/linalg-types.h>
#ifdef __cplusplus
extern "C" {
@ -45,12 +44,12 @@ enum weston_matrix_transform_type {
};
struct weston_matrix {
struct weston_mat4f M;
float d[16];
unsigned int type;
};
struct weston_vector {
struct weston_vec4f v;
float f[4];
};
/** Arbitrary coordinates in any space */
@ -210,7 +209,7 @@ weston_coord_surface_sub(struct weston_coord_surface a,
static inline struct weston_coord __attribute__ ((warn_unused_result))
weston_coord_truncate(struct weston_coord in)
{
return (struct weston_coord){ (double)(int) in.x, (double)(int) in.y };
return (struct weston_coord){ (int)in.x, (int)in.y };
}
static inline struct weston_coord_surface __attribute__ ((warn_unused_result))

View file

@ -1,11 +1,6 @@
install_headers(
'colorimetry.h',
'config-parser.h',
'libweston.h',
'linalg.h',
'linalg-3.h',
'linalg-4.h',
'linalg-types.h',
'desktop.h',
'matrix.h',
'plugin-registry.h',

View file

@ -75,13 +75,6 @@ weston_shell_utils_curtain_destroy(struct weston_curtain *curtain);
enum weston_layer_position
weston_shell_utils_view_get_layer_position(struct weston_view *view);
void
weston_output_set_shell_private(struct weston_output *output,
void *private_data);
void *
weston_output_get_shell_private(struct weston_output *output);
#ifdef __cplusplus
}
#endif

View file

@ -146,12 +146,6 @@ struct weston_log_scope *
weston_log_scopes_iterate(struct weston_log_context *log_ctx,
struct weston_log_scope *nscope);
void
weston_add_scope_to_advertised_list(struct weston_log_context *ctx,
const char *name);
bool
weston_log_scope_to_be_advertised(struct weston_log_context *ctx, const char *name);
#ifdef __cplusplus
}
#endif

View file

@ -32,10 +32,6 @@ extern "C" {
#include <libweston/plugin-registry.h>
#ifndef ARRAY_LENGTH
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
#endif
struct weston_compositor;
struct weston_output;
@ -103,9 +99,8 @@ weston_windowed_output_get_api(struct weston_compositor *compositor,
if (type >= ARRAY_LENGTH(api_names))
return NULL;
return (const struct weston_windowed_output_api *)
weston_plugin_api_get(compositor, api_names[type],
sizeof(struct weston_windowed_output_api));
return weston_plugin_api_get(compositor, api_names[type],
sizeof(struct weston_windowed_output_api));
}
#ifdef __cplusplus

View file

@ -1455,8 +1455,6 @@ ivi_hmi_controller_UI_ready(struct wl_client *client,
hmi_ctrl->interface->commit_changes();
ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
hmi_ctrl->interface->screen_ready(hmi_ctrl->workspace_background_output);
hmi_ctrl->is_initialized = 1;
}

View file

@ -219,17 +219,6 @@ struct ivi_layout_interface {
*/
void (*add_listener_configure_desktop_surface)(struct wl_listener *listener);
/**
* \brief add a listener for desktop_surface ping timeout notification
*
* When a desktop_client fails to respond to compositor pings within
* the configured timeout period, this signal is emitted to registered
* listeners. The void* data argument will contain a pointer to the
* weston_desktop_client associated with the unresponsive surface.
*/
void (*add_listener_desktop_surface_ping_timeout)(struct wl_listener *listener);
/**
* \brief Get all ivi_surfaces which are currently registered and managed
* by the services
@ -647,12 +636,6 @@ struct ivi_layout_interface {
* See add_listener_show_input_panel for more details.
*/
void (*add_listener_update_input_panel)(struct wl_listener *listener);
/**
* \brief Set weston_output ready to be painted
*/
void (*screen_ready)(struct weston_output *output);
};
static inline const struct ivi_layout_interface *

View file

@ -115,7 +115,6 @@ struct ivi_layout {
struct wl_signal removed;
struct wl_signal configure_changed;
struct wl_signal configure_desktop_changed;
struct wl_signal ping_timeout;
} surface_notification;
struct {

View file

@ -46,9 +46,6 @@ void
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
int32_t width, int32_t height);
void
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client);
struct ivi_layout_surface*
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
struct weston_desktop_surface *surface);

View file

@ -63,7 +63,6 @@
#include "frontend/weston.h"
#include <libweston/libweston.h>
#include <libweston/shell-utils.h>
#include "ivi-shell.h"
#include "ivi-layout-export.h"
#include "ivi-layout-private.h"
@ -285,7 +284,7 @@ destroy_screen(struct ivi_layout_screen *iviscrn)
}
static void
output_destroy_iviscreen(struct wl_listener *listener, void *data)
output_destroyed_event(struct wl_listener *listener, void *data)
{
struct weston_output *destroyed_output = data;
struct ivi_layout_screen *iviscrn;
@ -296,8 +295,8 @@ output_destroy_iviscreen(struct wl_listener *listener, void *data)
}
static struct ivi_layout_screen *
create_screen(struct weston_output *output)
static void
add_screen(struct weston_output *output)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn = NULL;
@ -310,24 +309,26 @@ create_screen(struct weston_output *output)
wl_list_init(&iviscrn->pending.layer_list);
wl_list_init(&iviscrn->order.layer_list);
wl_list_insert(&layout->screen_list, &iviscrn->link);
return iviscrn;
}
static void
create_ivi_screen(struct ivi_layout *layout, struct weston_output *output)
output_created_event(struct wl_listener *listener, void *data)
{
create_screen(output);
struct weston_output *created_output = data;
add_screen(created_output);
}
/**
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
* Called by ivi_layout_init.
*/
static void
output_create_iviscreen(struct wl_listener *listener, void *data)
create_screen(struct weston_compositor *ec)
{
struct ivi_layout *layout =
container_of(listener, struct ivi_layout, output_created);
struct weston_output *output = data;
struct weston_output *output = NULL;
create_ivi_screen(layout, output);
wl_list_for_each(output, &ec->output_list, link)
add_screen(output);
}
/**
@ -462,33 +463,33 @@ calc_inverse_matrix_transform(const struct weston_matrix *matrix,
}
/* The vectors and matrices involved will always produce f[3] == 1.0. */
top_left.v.el[0] = rect_input->x;
top_left.v.el[1] = rect_input->y;
top_left.v.el[2] = 0.0f;
top_left.v.el[3] = 1.0f;
top_left.f[0] = rect_input->x;
top_left.f[1] = rect_input->y;
top_left.f[2] = 0.0f;
top_left.f[3] = 1.0f;
bottom_right.v.el[0] = rect_input->x + rect_input->width;
bottom_right.v.el[1] = rect_input->y + rect_input->height;
bottom_right.v.el[2] = 0.0f;
bottom_right.v.el[3] = 1.0f;
bottom_right.f[0] = rect_input->x + rect_input->width;
bottom_right.f[1] = rect_input->y + rect_input->height;
bottom_right.f[2] = 0.0f;
bottom_right.f[3] = 1.0f;
weston_matrix_transform(&m, &top_left);
weston_matrix_transform(&m, &bottom_right);
if (top_left.v.el[0] < bottom_right.v.el[0]) {
rect_output->x = floor(top_left.v.el[0]);
rect_output->width = ceil(bottom_right.v.el[0] - rect_output->x);
if (top_left.f[0] < bottom_right.f[0]) {
rect_output->x = floorf(top_left.f[0]);
rect_output->width = ceilf(bottom_right.f[0] - rect_output->x);
} else {
rect_output->x = floor(bottom_right.v.el[0]);
rect_output->width = ceil(top_left.v.el[0] - rect_output->x);
rect_output->x = floorf(bottom_right.f[0]);
rect_output->width = ceilf(top_left.f[0] - rect_output->x);
}
if (top_left.v.el[1] < bottom_right.v.el[1]) {
rect_output->y = floor(top_left.v.el[1]);
rect_output->height = ceil(bottom_right.v.el[1] - rect_output->y);
if (top_left.f[1] < bottom_right.f[1]) {
rect_output->y = floorf(top_left.f[1]);
rect_output->height = ceilf(bottom_right.f[1] - rect_output->y);
} else {
rect_output->y = floor(bottom_right.v.el[1]);
rect_output->height = ceil(top_left.v.el[1] - rect_output->y);
rect_output->y = floorf(bottom_right.f[1]);
rect_output->height = ceilf(top_left.f[1] - rect_output->y);
}
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
@ -987,16 +988,6 @@ ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener)
wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener);
}
static void
ivi_layout_add_listener_desktop_surface_ping_timeout(struct wl_listener *listener)
{
struct ivi_layout *layout = get_instance();
assert(listener);
wl_signal_add(&layout->surface_notification.ping_timeout, listener);
}
static int32_t
ivi_layout_shell_add_destroy_listener_once(struct wl_listener *listener, wl_notify_func_t destroy_handler)
{
@ -1573,12 +1564,6 @@ ivi_layout_screen_set_render_order(struct weston_output *output,
iviscrn->order.dirty = 1;
}
static void
ivi_layout_set_screen_ready(struct weston_output *output)
{
weston_output_set_ready(output);
}
/**
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
@ -1927,14 +1912,6 @@ ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
ivisurf);
}
void
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client)
{
struct ivi_layout *layout = get_instance();
wl_signal_emit_mutable(&layout->surface_notification.ping_timeout, client);
}
struct ivi_layout_surface*
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
struct weston_desktop_surface *surface)
@ -2121,7 +2098,6 @@ void
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
{
struct ivi_layout *layout = get_instance();
struct weston_output *output;
layout->shell = shell;
@ -2137,7 +2113,6 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
wl_signal_init(&layout->surface_notification.removed);
wl_signal_init(&layout->surface_notification.configure_changed);
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
wl_signal_init(&layout->surface_notification.ping_timeout);
wl_signal_init(&layout->input_panel_notification.configure_changed);
wl_signal_init(&layout->input_panel_notification.show);
@ -2151,13 +2126,12 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
weston_layer_set_position(&layout->layout_layer,
WESTON_LAYER_POSITION_NORMAL);
layout->output_created.notify = output_create_iviscreen;
create_screen(ec);
layout->output_created.notify = output_created_event;
wl_signal_add(&ec->output_created_signal, &layout->output_created);
wl_list_for_each(output, &ec->output_list, link)
create_ivi_screen(layout, output);
layout->output_destroyed.notify = output_destroy_iviscreen;
layout->output_destroyed.notify = output_destroyed_event;
wl_signal_add(&ec->output_destroyed_signal, &layout->output_destroyed);
layout->transitions = ivi_layout_transition_set_create(ec);
@ -2172,10 +2146,6 @@ void
ivi_layout_fini(void)
{
struct ivi_layout *layout = get_instance();
struct ivi_layout_screen *iviscrn, *iviscrn_tmp;
wl_list_for_each_safe(iviscrn, iviscrn_tmp, &layout->screen_list, link)
destroy_screen(iviscrn);
weston_layer_fini(&layout->layout_layer);
@ -2194,33 +2164,32 @@ static struct ivi_layout_interface ivi_layout_interface = {
/**
* surface controller interfaces
*/
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
.add_listener_desktop_surface_ping_timeout = ivi_layout_add_listener_desktop_surface_ping_timeout,
.get_surface = shell_get_ivi_layout_surface,
.get_surfaces = ivi_layout_get_surfaces,
.get_id_of_surface = ivi_layout_get_id_of_surface,
.get_surface_from_id = ivi_layout_get_surface_from_id,
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
.surface_set_visibility = ivi_layout_surface_set_visibility,
.surface_set_opacity = ivi_layout_surface_set_opacity,
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
.surface_add_listener = ivi_layout_surface_add_listener,
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
.surface_set_transition = ivi_layout_surface_set_transition,
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
.surface_set_id = ivi_layout_surface_set_id,
.surface_activate = ivi_layout_surface_activate,
.surface_is_active = ivi_layout_surface_is_active,
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
.get_surface = shell_get_ivi_layout_surface,
.get_surfaces = ivi_layout_get_surfaces,
.get_id_of_surface = ivi_layout_get_id_of_surface,
.get_surface_from_id = ivi_layout_get_surface_from_id,
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
.surface_set_visibility = ivi_layout_surface_set_visibility,
.surface_set_opacity = ivi_layout_surface_set_opacity,
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
.surface_add_listener = ivi_layout_surface_add_listener,
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
.surface_set_transition = ivi_layout_surface_set_transition,
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
.surface_set_id = ivi_layout_surface_set_id,
.surface_activate = ivi_layout_surface_activate,
.surface_is_active = ivi_layout_surface_is_active,
/**
* layer controller interfaces
*/
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
.add_listener_remove_layer = ivi_layout_add_listener_remove_layer,
.layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
.layer_destroy = ivi_layout_layer_destroy,
@ -2247,7 +2216,6 @@ static struct ivi_layout_interface ivi_layout_interface = {
.screen_add_layer = ivi_layout_screen_add_layer,
.screen_remove_layer = ivi_layout_screen_remove_layer,
.screen_set_render_order = ivi_layout_screen_set_render_order,
.screen_ready = ivi_layout_set_screen_ready,
/**
* animation

View file

@ -51,7 +51,6 @@
#include "shared/helpers.h"
#include "shared/xalloc.h"
#include "frontend/weston.h"
#include <libweston/shell-utils.h>
/* Representation of ivi_surface protocol object. */
struct ivi_shell_surface
@ -215,7 +214,7 @@ ivi_shell_surface_get_label(struct weston_surface *surface,
{
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
return snprintf(buf, len, "ivi-surface %u", shell_surf->id_surface);
return snprintf(buf, len, "ivi-surface %#x", shell_surf->id_surface);
}
static void
@ -623,7 +622,7 @@ static void
desktop_surface_ping_timeout(struct weston_desktop_client *client,
void *user_data)
{
ivi_layout_desktop_surface_ping_timeout(client);
/* Not supported */
}
static void
@ -647,8 +646,6 @@ desktop_surface_added(struct weston_desktop_surface *surface,
ivisurf = xzalloc(sizeof *ivisurf);
weston_surface_set_label_func(weston_surf, weston_shell_utils_surface_get_label);
ivisurf->shell = shell;
ivisurf->id_surface = IVI_INVALID_ID;

View file

@ -96,9 +96,3 @@ workspace-id=3
icon-id=4010
icon=@westondatadir@/icon_ivi_smoke.png
path=@bindir@/weston-smoke
[ivi-launcher]
workspace-id=3
icon-id=4011
icon=@westondatadir@/icon_ivi_simple-egl-vertical.png
command=@bindir@/weston-simple-egl -v

View file

@ -137,7 +137,7 @@ xwayland_get_xwayland_name(struct kiosk_shell_surface *shsurf, enum window_atom_
static void
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_output *shoutput);
struct weston_output *output);
static void
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *parent);
@ -147,6 +147,9 @@ kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
static void
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
struct kiosk_shell_surface *shroot);
static struct kiosk_shell_output *
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
struct weston_output *output);
static void
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
@ -180,7 +183,7 @@ kiosk_shell_surface_get_parent_root(struct kiosk_shell_surface *shsurf)
static bool
kiosk_shell_output_has_app_id(char *config_app_ids, const char *app_id);
static struct kiosk_shell_output *
static struct weston_output *
kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *shsurf)
{
struct kiosk_shell_output *shoutput;
@ -205,7 +208,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
if (found_wm_name && found_wm_class) {
shsurf->appid_output_assigned = true;
return shoutput;
return shoutput->output;
}
}
}
@ -216,7 +219,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_name_app_ids,
wm_name)) {
shsurf->appid_output_assigned = true;
return shoutput;
return shoutput->output;
}
}
}
@ -226,7 +229,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_class_app_ids,
wm_class)) {
shsurf->appid_output_assigned = true;
return shoutput;
return shoutput->output;
}
}
}
@ -234,7 +237,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
return NULL;
}
static struct kiosk_shell_output *
static struct weston_output *
kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
{
struct weston_output *output;
@ -252,14 +255,14 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
wl_list_for_each(shoutput, &shsurf->shell->output_list, link) {
if (kiosk_shell_output_has_app_id(shoutput->app_ids, app_id)) {
shsurf->appid_output_assigned = true;
return shoutput;
return shoutput->output;
}
}
}
shoutput = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
if (shoutput)
return shoutput;
output = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
if (output)
return output;
/* Group all related windows in the same output. */
root = kiosk_shell_surface_get_parent_root(shsurf);
@ -268,20 +271,20 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
output = weston_shell_utils_get_focused_output(shsurf->shell->compositor);
if (output)
return weston_output_get_shell_private(output);
return output;
output = weston_shell_utils_get_default_output(shsurf->shell->compositor);
if (output)
return weston_output_get_shell_private(output);
return output;
return NULL;
}
static void
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_output *shoutput)
struct weston_output *output)
{
shsurf->output = shoutput;
shsurf->output = output;
if (shsurf->output_destroy_listener.notify) {
wl_list_remove(&shsurf->output_destroy_listener.link);
@ -293,39 +296,39 @@ kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
shsurf->output_destroy_listener.notify =
kiosk_shell_surface_notify_output_destroy;
wl_signal_add(&shsurf->output->output->destroy_signal,
wl_signal_add(&shsurf->output->destroy_signal,
&shsurf->output_destroy_listener);
}
static void
kiosk_shell_surface_set_fullscreen(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_output *shoutput)
struct weston_output *output)
{
if (!shoutput)
shoutput = kiosk_shell_surface_find_best_output(shsurf);
if (!output)
output = kiosk_shell_surface_find_best_output(shsurf);
kiosk_shell_surface_set_output(shsurf, shoutput);
kiosk_shell_surface_set_output(shsurf, output);
weston_desktop_surface_set_fullscreen(shsurf->desktop_surface, true);
if (shsurf->output)
weston_desktop_surface_set_size(shsurf->desktop_surface,
shsurf->output->output->width,
shsurf->output->output->height);
shsurf->output->width,
shsurf->output->height);
}
static void
kiosk_shell_surface_set_maximized(struct kiosk_shell_surface *shsurf)
{
struct kiosk_shell_output *shoutput =
struct weston_output *output =
kiosk_shell_surface_find_best_output(shsurf);
kiosk_shell_surface_set_output(shsurf, shoutput);
kiosk_shell_surface_set_output(shsurf, output);
weston_desktop_surface_set_maximized(shsurf->desktop_surface, true);
if (shsurf->output)
weston_desktop_surface_set_size(shsurf->desktop_surface,
shsurf->output->output->width,
shsurf->output->output->height);
shsurf->output->width,
shsurf->output->height);
}
static void
@ -379,7 +382,9 @@ static void
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
struct kiosk_shell_surface *parent)
{
struct kiosk_shell_output *shoutput = shsurf->output;
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell,
shsurf->output);
struct kiosk_shell_surface *shroot = parent ?
kiosk_shell_surface_get_parent_root(parent) :
kiosk_shell_surface_get_parent_root(shsurf);
@ -431,22 +436,20 @@ static void
kiosk_shell_surface_reconfigure_for_output(struct kiosk_shell_surface *shsurf)
{
struct weston_desktop_surface *desktop_surface;
struct weston_output *w_output;
if (!shsurf->output)
return;
w_output = shsurf->output->output;
desktop_surface = shsurf->desktop_surface;
if (weston_desktop_surface_get_maximized(desktop_surface) ||
weston_desktop_surface_get_fullscreen(desktop_surface)) {
weston_desktop_surface_set_size(desktop_surface,
w_output->width,
w_output->height);
shsurf->output->width,
shsurf->output->height);
}
weston_shell_utils_center_on_output(shsurf->view, w_output);
weston_shell_utils_center_on_output(shsurf->view, shsurf->output);
weston_view_update_transform(shsurf->view);
}
@ -527,7 +530,8 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
struct weston_surface *surface =
weston_desktop_surface_get_surface(dsurface);
struct kiosk_shell_output *shoutput = shsurf->output;
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
/* keyboard focus */
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
@ -820,11 +824,8 @@ kiosk_shell_output_create(struct kiosk_shell *shell, struct weston_output *outpu
wl_list_insert(shell->output_list.prev, &shoutput->link);
weston_output_set_shell_private(output, shoutput);
kiosk_shell_output_recreate_background(shoutput);
kiosk_shell_output_configure(shoutput);
weston_output_set_ready(output);
return shoutput;
}
@ -869,9 +870,6 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
struct weston_layer *layer;
struct weston_view *view;
if (!shsurf->output)
return NULL;
wl_list_for_each(layer, layers, link) {
struct kiosk_shell *shell = shsurf->shell;
@ -887,7 +885,7 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
continue;
/* pick views only on the same output */
if (view->output != shsurf->output->output)
if (view->output != shsurf->output)
continue;
view_shsurf = get_kiosk_shell_surface(view->surface);
@ -949,7 +947,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
successor = find_focus_successor(shsurf,
kiosk_seat->focused_surface);
shoutput = shsurf->output;
shoutput = kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
if (shoutput && successor) {
enum weston_layer_position succesor_view_layer_pos;
@ -993,17 +991,17 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
return;
if (!shsurf->appid_output_assigned && app_id) {
struct kiosk_shell_output *shoutput = NULL;
struct weston_output *output = NULL;
/* reset previous output being set in _added() as the output is
* being cached */
shsurf->output = NULL;
shoutput = kiosk_shell_surface_find_best_output(shsurf);
output = kiosk_shell_surface_find_best_output(shsurf);
kiosk_shell_surface_set_output(shsurf, shoutput);
kiosk_shell_surface_set_output(shsurf, output);
weston_desktop_surface_set_size(shsurf->desktop_surface,
shoutput->output->width,
shoutput->output->height);
shsurf->output->width,
shsurf->output->height);
/* even if we couldn't find an appid set for a particular
* output still flag the shsurf as to a avoid changing the
* output every time */
@ -1023,7 +1021,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
if (!weston_surface_is_mapped(surface) || (is_resized && is_fullscreen)) {
if (is_fullscreen || !shsurf->xwayland.is_set) {
weston_shell_utils_center_on_output(shsurf->view,
shsurf->output->output);
shsurf->output);
} else {
struct weston_coord_surface offset;
struct weston_geometry geometry =
@ -1042,7 +1040,9 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
if (!weston_surface_is_mapped(surface)) {
struct weston_seat *seat =
get_kiosk_shell_first_seat(shsurf->shell);
struct kiosk_shell_output *shoutput = shsurf->output;
struct kiosk_shell_output *shoutput =
kiosk_shell_find_shell_output(shsurf->shell,
shsurf->output);
struct kiosk_shell_seat *kiosk_seat;
weston_surface_map(surface);
@ -1134,10 +1134,6 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
{
struct kiosk_shell_surface *shsurf =
weston_desktop_surface_get_user_data(desktop_surface);
struct kiosk_shell_output *shoutput = NULL;
if (output)
shoutput = weston_output_get_shell_private(output);
/* We should normally be able to ignore fullscreen requests for
* top-level surfaces, since we set them as fullscreen at creation
@ -1152,7 +1148,7 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
*/
if (!shsurf->parent || fullscreen)
kiosk_shell_surface_set_fullscreen(shsurf, shoutput);
kiosk_shell_surface_set_fullscreen(shsurf, output);
else
kiosk_shell_surface_set_normal(shsurf);
}
@ -1236,6 +1232,20 @@ static const struct weston_desktop_api kiosk_shell_desktop_api = {
* kiosk_shell
*/
static struct kiosk_shell_output *
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
struct weston_output *output)
{
struct kiosk_shell_output *shoutput;
wl_list_for_each(shoutput, &shell->output_list, link) {
if (shoutput->output == output)
return shoutput;
}
return NULL;
}
static void
kiosk_shell_activate_view(struct kiosk_shell *shell,
struct weston_view *view,
@ -1324,7 +1334,7 @@ kiosk_shell_handle_output_resized(struct wl_listener *listener, void *data)
container_of(listener, struct kiosk_shell, output_resized_listener);
struct weston_output *output = data;
struct kiosk_shell_output *shoutput =
weston_output_get_shell_private(output);
kiosk_shell_find_shell_output(shell, output);
struct weston_view *view;
kiosk_shell_output_recreate_background(shoutput);

View file

@ -57,7 +57,7 @@ struct kiosk_shell_surface {
struct kiosk_shell *shell;
struct kiosk_shell_output *output;
struct weston_output *output;
struct wl_listener output_destroy_listener;
struct wl_signal destroy_signal;

View file

@ -199,19 +199,7 @@ weston_view_animation_frame(struct weston_animation *base,
struct weston_compositor *compositor =
animation->view->surface->compositor;
/* Animations are created with timestamp 0, so we need to set a
* real time base on the first repaint.
*
* In some cases, such as when the repaint loop has just started
* for a new display, the time we're given could be 0 for our
* second call - but this is ok because weston_spring_update() will
* do nothing as long as spring.timestamp == time.
*
* We can safely just keep updating the timestamp until we get
* something non-zero, and the spring will start updating after
* that.
*/
if (!timespec_to_msec(&animation->spring.timestamp))
if (base->frame_counter <= 1)
animation->spring.timestamp = *time;
weston_spring_update(&animation->spring, time);
@ -287,6 +275,7 @@ weston_view_animation_run(struct weston_view_animation *animation)
{
struct timespec zero_time = { 0 };
animation->animation.frame_counter = 0;
weston_view_animation_frame(&animation->animation, NULL, &zero_time);
}

View file

@ -40,12 +40,26 @@
#include "pixman-renderer.h"
#include "pixel-formats.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-assert.h"
#include "shared/weston-egl-ext.h"
#include "linux-dmabuf.h"
#include "linux-explicit-synchronization.h"
#include "shared/xalloc.h"
static struct gbm_device *
create_gbm_device(int fd)
{
struct gbm_device *gbm;
/* GBM will load a dri driver, but even though they need symbols from
* libglapi, in some version of Mesa they are not linked to it. Since
* only the gl-renderer module links to it, the call above won't make
* these symbols globally available, and loading the DRI driver fails.
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
gbm = gbm_create_device(fd);
return gbm;
}
/* When initializing EGL, if the preferred buffer format isn't available
* we may be able to substitute an ARGB format for an XRGB one.
@ -85,32 +99,12 @@ drm_backend_create_gl_renderer(struct drm_backend *b)
&options.base);
}
static int
drm_backend_create_vulkan_renderer(struct drm_backend *b)
{
const struct pixel_format_info *format[3] = {
b->format,
fallback_format_for(b->format),
};
struct vulkan_renderer_display_options options = {
.formats = format,
.formats_count = 1,
};
if (format[1])
options.formats_count = 2;
return weston_compositor_init_renderer(b->compositor,
WESTON_RENDERER_VULKAN,
&options.base);
}
int
init_egl(struct drm_backend *b)
{
struct drm_device *device = b->drm;
b->gbm = gbm_create_device(device->drm.fd);
b->gbm = create_gbm_device(device->drm.fd);
if (!b->gbm)
return -1;
@ -123,24 +117,6 @@ init_egl(struct drm_backend *b)
return 0;
}
int
init_vulkan(struct drm_backend *b)
{
struct drm_device *device = b->drm;
b->gbm = gbm_create_device(device->drm.fd);
if (!b->gbm)
return -1;
if (drm_backend_create_vulkan_renderer(b) < 0) {
gbm_device_destroy(b->gbm);
b->gbm = NULL;
return -1;
}
return 0;
}
static void drm_output_fini_cursor_egl(struct drm_output *output)
{
unsigned int i;
@ -154,19 +130,6 @@ static void drm_output_fini_cursor_egl(struct drm_output *output)
}
}
static void drm_output_fini_cursor_vulkan(struct drm_output *output)
{
unsigned int i;
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
/* This cursor does not have a GBM device */
if (output->gbm_cursor_fb[i] && !output->gbm_cursor_fb[i]->bo)
output->gbm_cursor_fb[i]->type = BUFFER_PIXMAN_DUMB;
drm_fb_unref(output->gbm_cursor_fb[i]);
output->gbm_cursor_fb[i] = NULL;
}
}
static int
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
{
@ -216,55 +179,6 @@ err:
return -1;
}
static int
drm_output_init_cursor_vulkan(struct drm_output *output, struct drm_backend *b)
{
struct drm_device *device = output->device;
unsigned int i;
/* No point creating cursors if we don't have a plane for them. */
if (!output->cursor_plane)
return 0;
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
struct gbm_bo *bo;
if (gbm_device_get_fd(b->gbm) != output->device->drm.fd) {
output->gbm_cursor_fb[i] =
drm_fb_create_dumb(output->device,
device->cursor_width,
device->cursor_height,
DRM_FORMAT_ARGB8888);
/* Override buffer type, since we know it is a cursor */
output->gbm_cursor_fb[i]->type = BUFFER_CURSOR;
output->gbm_cursor_handle[i] =
output->gbm_cursor_fb[i]->handles[0];
} else {
bo = gbm_bo_create(b->gbm, device->cursor_width, device->cursor_height,
GBM_FORMAT_ARGB8888,
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
if (!bo)
goto err;
output->gbm_cursor_fb[i] =
drm_fb_get_from_bo(bo, device, false, BUFFER_CURSOR);
if (!output->gbm_cursor_fb[i]) {
gbm_bo_destroy(bo);
goto err;
}
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
}
}
return 0;
err:
weston_log("cursor buffers unavailable, using vulkan cursors\n");
device->cursors_are_broken = true;
drm_output_fini_cursor_vulkan(output);
return -1;
}
static void
create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
{
@ -315,213 +229,26 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
output->gbm_bo_flags);
}
enum format_alpha_required {
FORMAT_ALPHA_REQUIRED = true,
FORMAT_ALPHA_NOT_REQUIRED = false,
};
enum format_component_type {
FORMAT_COMPONENT_TYPE_ANY,
FORMAT_COMPONENT_TYPE_FLOAT_ONLY,
};
static const struct pixel_format_info *
find_compatible_format(struct weston_compositor *compositor,
struct wl_array *formats, int min_bpc,
enum format_component_type component_type,
enum format_alpha_required alpha_required)
{
const struct pixel_format_info **tmp, *p;
const struct pixel_format_info *candidate = NULL;
/**
* Given a format array, this looks for a format respecting a few
* criteria. First of all, this ignores formats that do not contain an
* alpha channel when alpha_required == FORMAT_ALPHA_REQUIRED. Similar
* for formats that are not floating point when component_type ==
* FORMAT_COMPONENT_TYPE_FLOAT_ONLY. Also, it ignores formats that do
* not have bits per color channel (bpc) bigger or equal to min_bpc.
*
* When we have multiple formats matching these criteria, we use the
* following to choose:
*
* 1. a format with lower bytes per pixel (bpp) is favored.
*
* 2. if FORMAT_ALPHA_REQUIRED:
* we prefer the format with more bits on the alpha channel
* else
* we prefer the format with more bits on the color channels
*/
wl_array_for_each(tmp, formats) {
p = *tmp;
/* Skip candidates that do not match minimum criteria. */
if (component_type == FORMAT_COMPONENT_TYPE_FLOAT_ONLY &&
p->component_type != PIXEL_COMPONENT_TYPE_FLOAT)
continue;
if (alpha_required == FORMAT_ALPHA_REQUIRED && p->bits.a == 0)
continue;
if (p->bits.r < min_bpc || p->bits.g < min_bpc || p->bits.b < min_bpc)
continue;
/* No other good candidate so far, so pick this one. */
if (!candidate) {
candidate = p;
continue;
}
/**
* New candidate, let's compare with old and untie.
*/
if (p->bpp > candidate->bpp)
continue;
if (alpha_required == FORMAT_ALPHA_REQUIRED) {
if (p->bits.a <= candidate->bits.a)
continue;
} else {
if (p->bits.r + p->bits.g + p->bits.b <=
candidate->bits.r + candidate->bits.g + candidate->bits.b)
continue;
}
candidate = p;
}
return candidate;
}
static bool
drm_output_pick_format_egl(struct drm_output *output)
{
struct drm_device *device = output->device;
struct drm_backend *b = device->backend;
struct weston_compositor *compositor = b->compositor;
const struct weston_renderer *renderer = compositor->renderer;
const struct pixel_format_info **renderer_formats;
const struct pixel_format_info **f;
unsigned int renderer_formats_count;
struct wl_array supported_formats;
enum format_component_type component_type;
uint32_t min_bpc;
unsigned int i;
bool ret = true;
bool found;
wl_array_init(&supported_formats);
/**
* This computes the intersection between renderer formats supported by
* EGL and the output->scanout_plane supported formats. We need that as
* we want to select a format supported by both.
*/
renderer_formats =
renderer->gl->get_supported_rendering_formats(b->compositor,
&renderer_formats_count);
for (i = 0; i < renderer_formats_count; i++) {
if (!weston_drm_format_array_find_format(&output->scanout_plane->formats,
renderer_formats[i]->format))
continue;
f = wl_array_add(&supported_formats, sizeof(*f));
*f = renderer_formats[i];
}
if (output->base.from_blend_to_output_by_backend) {
component_type = FORMAT_COMPONENT_TYPE_FLOAT_ONLY;
min_bpc = 16;
} else if (output->base.eotf_mode != WESTON_EOTF_MODE_SDR) {
component_type = FORMAT_COMPONENT_TYPE_ANY;
min_bpc = 10;
} else {
/**
* If no requirements, we simply use b->format instead of
* looking for a format with bpc >= min_bpc.
*/
min_bpc = 0;
}
if (min_bpc != 0) {
if (b->has_underlay) {
output->format =
find_compatible_format(compositor, &supported_formats,
min_bpc, component_type,
FORMAT_ALPHA_REQUIRED);
if (output->format)
goto done;
weston_log("Disabling underlay planes: EGL GBM or the primary plane for output '%s'\n" \
"does not support format with min bpc %u and alpha channel.\n",
output->base.name, min_bpc);
b->has_underlay = false;
}
output->format =
find_compatible_format(compositor, &supported_formats,
min_bpc, component_type,
FORMAT_ALPHA_NOT_REQUIRED);
if (output->format)
goto done;
weston_log("Error: EGL GBM or the primary plane for output '%s' does not support format\n" \
"with min bpc %u.\n", output->base.name, min_bpc);
ret = false;
goto done;
}
found = false;
wl_array_for_each(f, &supported_formats) {
if ((*f)->format == b->format->format) {
found = true;
break;
}
}
if (!found) {
weston_log("Error: format %s unsupported by EGL GBM or the primary plane for output '%s'.\n",
b->format->drm_format_name, output->base.name);
ret = false;
goto done;
}
if (b->has_underlay && (b->format->bits.a == 0)) {
weston_log("Disabling underlay planes: b->format %s does not have alpha channel,\n"
"which is required to support underlay planes.\n",
b->format->drm_format_name);
b->has_underlay = false;
}
output->format = b->format;
done:
wl_array_release(&supported_formats);
return ret;
}
/* Init output state that depends on gl or gbm */
int
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
{
const struct weston_renderer *renderer = b->compositor->renderer;
const struct weston_mode *mode = output->base.current_mode;
const struct pixel_format_info *format[2] = { 0 };
struct gl_renderer_output_options options;
if (!output->format && !drm_output_pick_format_egl(output))
return -1;
format[0] = output->format;
if (!b->has_underlay)
format[1] = fallback_format_for(output->format);
options.formats = format;
options.formats_count = format[1] ? 2 : 1;
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
const struct pixel_format_info *format[2] = {
output->format,
fallback_format_for(output->format),
};
struct gl_renderer_output_options options = {
.formats = format,
.formats_count = 1,
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
assert(output->gbm_surface == NULL);
create_gbm_surface(b->gbm, output);
@ -530,6 +257,8 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
return -1;
}
if (options.formats[1])
options.formats_count = 2;
options.window_for_legacy = (EGLNativeWindowType) output->gbm_surface;
options.window_for_platform = output->gbm_surface;
if (renderer->gl->output_window_create(&output->base, &options) < 0) {
@ -544,208 +273,6 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
return 0;
}
static struct gbm_bo *
drm_gbm_create_bo(struct gbm_device *gbm, struct drm_output *output)
{
struct weston_mode *mode = output->base.current_mode;
struct drm_plane *plane = output->scanout_plane;
struct weston_drm_format *fmt;
const uint64_t *modifiers;
unsigned int num_modifiers;
struct gbm_bo *bo = NULL;
/*
* TODO: Currently, this method allocates a buffer based on the list
* of acceptable modifiers received from the DRM backend but does not
* check it against formats renderable by the renderer.
* To support cases where the renderer may not support the same
* modifiers (e.g. Vulkan software renderer) it should match against
* renderer modifiers.
*/
fmt = weston_drm_format_array_find_format(&plane->formats,
output->format->format);
if (!fmt) {
weston_log("format %s not supported by output %s\n",
output->format->drm_format_name,
output->base.name);
return NULL;
}
if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
bo = gbm_bo_create_with_modifiers(gbm, mode->width, mode->height,
output->format->format,
modifiers, num_modifiers);
}
/*
* If we cannot use modifiers to allocate the GBM surface and
* the GBM device differs from the KMS display device, try to
* use linear buffers and hope that the allocated GBM surface
* is correctly displayed on the KMS device.
*/
if (gbm_device_get_fd(gbm) != output->device->drm.fd)
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
if (!bo) {
bo = gbm_bo_create(gbm, mode->width, mode->height,
output->format->format, output->gbm_bo_flags);
}
return bo;
}
struct drm_gbm_dmabuf {
struct linux_dmabuf_memory base;
struct gbm_bo *bo;
};
static void
drm_gbm_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
{
struct dmabuf_attributes *attributes;
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
struct gbm_bo *bo;
drm_gbm_dmabuf = container_of(dmabuf, struct drm_gbm_dmabuf, base);
bo = drm_gbm_dmabuf->bo;
assert(bo);
gbm_bo_destroy(bo);
attributes = dmabuf->attributes;
for (int i = 0; i < attributes->n_planes; ++i)
close(attributes->fd[i]);
free(dmabuf->attributes);
free(dmabuf);
}
static struct drm_gbm_dmabuf *
drm_gbm_bo_get_dmabuf(struct gbm_device *gbm, struct drm_output *output, struct gbm_bo *bo)
{
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
struct dmabuf_attributes *attributes;
attributes = xzalloc(sizeof(*attributes));
attributes->width = gbm_bo_get_width(bo);
attributes->height = gbm_bo_get_height(bo);
attributes->format = gbm_bo_get_format(bo);
attributes->n_planes = gbm_bo_get_plane_count(bo);
for (int i = 0; i < attributes->n_planes; ++i) {
attributes->fd[i] = gbm_bo_get_fd(bo);
attributes->stride[i] = gbm_bo_get_stride_for_plane(bo, i);
attributes->offset[i] = gbm_bo_get_offset(bo, i);
}
attributes->modifier = gbm_bo_get_modifier(bo);
drm_gbm_dmabuf = xzalloc(sizeof(*drm_gbm_dmabuf));
drm_gbm_dmabuf->base.attributes = attributes;
drm_gbm_dmabuf->base.destroy = drm_gbm_dmabuf_destroy;
drm_gbm_dmabuf->bo = bo;
return drm_gbm_dmabuf;
}
static void
create_renderbuffers(struct gbm_device *gbm, struct drm_output *output, unsigned int n)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
for (unsigned int i = 0; i < n; i++) {
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
struct gbm_bo *bo;
bo = drm_gbm_create_bo(gbm, output);
if (!bo) {
weston_log("failed to allocate bo\n");
return;
}
drm_gbm_dmabuf = drm_gbm_bo_get_dmabuf(gbm, output, bo);
if (!drm_gbm_dmabuf) {
weston_log("failed to allocate dmabuf\n");
return;
}
output->renderbuffer[i] =
renderer->create_renderbuffer_dmabuf(&output->base,
&drm_gbm_dmabuf->base,
NULL, NULL);
if (!output->renderbuffer[i]) {
weston_log("failed to allocate renderbuffer\n");
return;
}
output->linux_dmabuf_memory[i] = &drm_gbm_dmabuf->base;
}
}
static bool
drm_output_pick_format_vulkan(struct drm_output *output)
{
struct drm_device *device = output->device;
struct drm_backend *b = device->backend;
/* Any other value of eotf_mode requires color-management, which is not
* yet supported by vulkan-renderer. */
assert(output->base.eotf_mode == WESTON_EOTF_MODE_SDR);
if (!b->format->vulkan_format) {
weston_log("Error: failed to pick format for output '%s', format %s unsupported by vulkan-renderer.\n",
output->base.name, b->format->drm_format_name);
return false;
}
assert(b->format);
output->format = b->format;
if (b->has_underlay && (output->format->bits.a == 0)) {
weston_log("Disabling underlay planes: output '%s' with format %s does not have alpha channel,\n"
"which is required to support underlay planes.\n",
output->base.name, output->format->drm_format_name);
b->has_underlay = false;
}
return true;
}
/* Init output state that depends on vulkan */
int
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
{
const struct weston_mode *mode = output->base.current_mode;
struct weston_renderer *renderer = b->compositor->renderer;
if (!output->format && !drm_output_pick_format_vulkan(output))
return -1;
const struct vulkan_renderer_surfaceless_options options = {
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
weston_log("failed to create vulkan renderer output state\n");
return -1;
}
create_renderbuffers(b->gbm, output, ARRAY_LENGTH(output->renderbuffer));
if (!output->linux_dmabuf_memory[0]) {
weston_log("failed to create dmabufs\n");
return -1;
}
drm_output_init_cursor_vulkan(output, b);
return 0;
}
void
drm_output_fini_egl(struct drm_output *output)
{
@ -766,26 +293,6 @@ drm_output_fini_egl(struct drm_output *output)
drm_output_fini_cursor_egl(output);
}
void
drm_output_fini_vulkan(struct drm_output *output)
{
struct drm_backend *b = output->backend;
const struct weston_renderer *renderer = b->compositor->renderer;
if (!b->compositor->shutting_down &&
output->scanout_plane->state_cur->fb &&
output->scanout_plane->state_cur->fb->type == BUFFER_DMABUF_BACKEND) {
drm_plane_reset_state(output->scanout_plane);
}
for (unsigned int i = 0; i < ARRAY_LENGTH(output->renderbuffer); i++)
renderer->destroy_renderbuffer(output->renderbuffer[i]);
renderer->vulkan->output_destroy(&output->base);
drm_output_fini_cursor_vulkan(output);
}
struct drm_fb *
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
{
@ -817,36 +324,3 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
return ret;
}
struct drm_fb *
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
{
struct drm_output *output = state->output;
struct drm_device *device = output->device;
struct linux_dmabuf_memory *dmabuf;
struct drm_fb *ret;
output->base.compositor->renderer->repaint_output(&output->base,
damage,
output->renderbuffer[output->current_image]);
dmabuf = output->linux_dmabuf_memory[output->current_image];
if (!dmabuf) {
weston_log("failed to get dmabuf\n");
return NULL;
}
/* Output transparent/opaque image according to the format required by
* the client. */
ret = drm_fb_get_from_dmabuf_attributes(dmabuf->attributes, device,
!output->format->opaque_substitute,
false, true, NULL);
if (!ret) {
weston_log("failed to get drm_fb for dmabuf\n");
return NULL;
}
output->current_image = (output->current_image + 1) % ARRAY_LENGTH(output->renderbuffer);
return ret;
}

View file

@ -78,10 +78,6 @@
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
#endif
#ifndef MAX_DMABUF_PLANES
#define MAX_DMABUF_PLANES 4
#endif
/**
* A small wrapper to print information into the 'drm-backend' debug scope.
*
@ -153,6 +149,27 @@ struct drm_property_info {
uint64_t range_values[2];
};
/**
* Reasons why placing a view on a plane failed. Needed by the dma-buf feedback.
*/
enum try_view_on_plane_failure_reasons {
FAILURE_REASONS_NONE = 0,
FAILURE_REASONS_FORCE_RENDERER = 1 << 0,
FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = 1 << 1,
FAILURE_REASONS_DMABUF_MODIFIER_INVALID = 1 << 2,
FAILURE_REASONS_ADD_FB_FAILED = 1 << 3,
FAILURE_REASONS_NO_PLANES_AVAILABLE = 1 << 4,
FAILURE_REASONS_PLANES_REJECTED = 1 << 5,
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION = 1 << 6,
FAILURE_REASONS_INCOMPATIBLE_TRANSFORM = 1 << 7,
FAILURE_REASONS_NO_BUFFER = 1 << 8,
FAILURE_REASONS_BUFFER_TYPE = 1 << 9,
FAILURE_REASONS_GLOBAL_ALPHA = 1 << 10,
FAILURE_REASONS_NO_GBM = 1 << 11,
FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 12,
FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 13,
};
/**
* We use this to keep track of actions we need to do with the dma-buf feedback
* in order to keep it up-to-date with the info we get from the DRM-backend.
@ -163,12 +180,6 @@ enum actions_needed_dmabuf_feedback {
ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
};
enum drm_plane_subtype {
PLANE_SUBTYPE_OVERLAY_ONLY = 0,
PLANE_SUBTYPE_UNDERLAY_ONLY = 1,
PLANE_SUBTYPE_BOTH = 2,
};
struct drm_device {
struct drm_backend *backend;
@ -221,9 +232,6 @@ struct drm_device {
/* drm_backend::kms_list */
struct wl_list link;
/* struct drm_colorop_3x1d_lut::link */
struct wl_list drm_colorop_3x1d_lut_list;
};
struct drm_backend {
@ -245,8 +253,6 @@ struct drm_backend {
bool use_pixman_shadow;
bool offload_blend_to_output;
struct udev_input input;
uint32_t pageflip_timeout;
@ -255,15 +261,6 @@ struct drm_backend {
bool has_underlay;
struct weston_log_scope *debug;
struct {
uint32_t frame_counter_interval;
struct wl_event_source *pageflip_timer_counter;
bool timer_armed;
} perf_page_flips_stats;
/* True if we need a workaround for some very old kernels */
bool stale_timestamp_workaround;
};
struct drm_mode {
@ -276,7 +273,6 @@ enum drm_fb_type {
BUFFER_INVALID = 0, /**< never used */
BUFFER_CLIENT, /**< directly sourced from client */
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
BUFFER_DMABUF_BACKEND, /**< imported from dmabuf renderbuffer */
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
BUFFER_CURSOR, /**< internal cursor buffer */
@ -291,9 +287,9 @@ struct drm_fb {
int refcnt;
uint32_t fb_id, size;
uint32_t handles[MAX_DMABUF_PLANES];
uint32_t strides[MAX_DMABUF_PLANES];
uint32_t offsets[MAX_DMABUF_PLANES];
uint32_t handles[4];
uint32_t strides[4];
uint32_t offsets[4];
int num_planes;
const struct pixel_format_info *format;
uint64_t modifier;
@ -306,12 +302,6 @@ struct drm_fb {
struct gbm_bo *bo;
struct gbm_surface *gbm_surface;
/* Used when direct-display extension is turned on for that dmabuf */
bool direct_display;
int fds[MAX_DMABUF_PLANES];
/* tracks how many fds we've dup'ed */
int num_duped_fds;
/* Used by dumb fbs */
void *map;
};
@ -339,15 +329,6 @@ struct drm_pending_state {
struct wl_list output_list;
};
enum drm_output_propose_state_mode {
DRM_OUTPUT_PROPOSE_STATE_INVALID = 0, /**< Invalid state */
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR, /**< only assign to renderer & cursor plane */
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer */
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
DRM_OUTPUT_PROPOSE_STATE_REUSE = 128, /**< bit indicates reuse prior state with new buffers */
};
/*
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
@ -361,13 +342,11 @@ enum drm_output_propose_state_mode {
struct drm_output_state {
struct drm_pending_state *pending_state;
struct drm_output *output;
enum drm_output_propose_state_mode mode;
struct wl_list link;
enum dpms_enum dpms;
enum weston_hdcp_protection protection;
struct wl_list plane_list;
bool tear;
bool planes_enabled;
};
/**
@ -400,9 +379,6 @@ struct drm_plane_state {
uint64_t zpos;
uint16_t alpha;
enum wdrm_plane_color_encoding color_encoding;
enum wdrm_plane_color_range color_range;
bool complete;
/* We don't own the fd, so we shouldn't close it */
@ -434,8 +410,6 @@ struct drm_plane {
struct drm_device *device;
enum wdrm_plane_type type;
/* Whether this plane supports overlay, underlay, or both */
enum drm_plane_subtype subtype;
uint32_t possible_crtcs;
uint32_t plane_id;
@ -443,6 +417,8 @@ struct drm_plane {
uint32_t crtc_id;
struct drm_property_info props[WDRM_PLANE__COUNT];
/* True if the plane's zpos_max < primary plane's zpos_min. */
bool is_underlay;
/* The last state submitted to the kernel for this plane. */
struct drm_plane_state *state_cur;
@ -516,19 +492,6 @@ struct drm_writeback {
struct weston_drm_format_array formats;
};
struct drm_colorop_3x1d_lut {
/* drm_device::drm_colorop_3x1d_lut_list */
struct wl_list link;
struct drm_device *device;
uint64_t lut_size;
struct weston_color_transform *xform;
struct wl_listener destroy_listener;
uint32_t blob_id;
};
struct drm_head {
struct weston_head base;
struct drm_connector connector;
@ -559,9 +522,6 @@ struct drm_crtc {
/* Holds the properties for the CRTC */
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
/* CRTC prop WDRM_CRTC_GAMMA_LUT_SIZE */
uint32_t lut_size;
};
struct drm_output {
@ -588,7 +548,6 @@ struct drm_output {
int current_cursor;
struct gbm_surface *gbm_surface;
struct linux_dmabuf_memory *linux_dmabuf_memory[2];
const struct pixel_format_info *format;
uint32_t gbm_bo_flags;
@ -598,9 +557,8 @@ struct drm_output {
unsigned max_bpc;
enum wdrm_colorspace connector_colorspace;
bool deprecated_gamma_is_set;
bool legacy_gamma_not_supported;
uint16_t legacy_gamma_size;
struct drm_colorop_3x1d_lut *blend_to_output_xform;
/* Plane being displayed directly on the CRTC */
struct drm_plane *scanout_plane;
@ -615,7 +573,7 @@ struct drm_output {
struct drm_writeback_state *wb_state;
struct drm_fb *dumb[2];
weston_renderbuffer_t renderbuffer[2];
struct weston_renderbuffer *renderbuffer[2];
int current_image;
struct vaapi_recorder *recorder;
@ -623,12 +581,6 @@ struct drm_output {
struct wl_event_source *pageflip_timer;
/* how many page flips */
uint32_t page_flips_counted;
/* how many page flips / interval */
float page_flips_per_timer_interval;
bool is_virtual;
void (*virtual_destroy)(struct weston_output *base);
@ -704,18 +656,7 @@ drm_output_get_plane_type_name(struct drm_plane *p)
case WDRM_PLANE_TYPE_CURSOR:
return "cursor";
case WDRM_PLANE_TYPE_OVERLAY:
switch (p->subtype) {
case PLANE_SUBTYPE_OVERLAY_ONLY:
return "overlay";
case PLANE_SUBTYPE_UNDERLAY_ONLY:
return "underlay";
case PLANE_SUBTYPE_BOTH:
return "over/underlay";
default:
assert(0);
break;
}
// fall through
return p->is_underlay ? "underlay" : "overlay";
default:
assert(0);
break;
@ -807,6 +748,10 @@ drm_pending_state_apply(struct drm_pending_state *pending_state);
int
drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
void
drm_output_set_gamma(struct weston_output *output_base,
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
void
drm_output_update_msc(struct drm_output *output, unsigned int seq);
void
@ -823,11 +768,6 @@ drm_fb_unref(struct drm_fb *fb);
struct drm_fb *
drm_fb_create_dumb(struct drm_device *device, int width, int height,
uint32_t format);
struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_device *device, bool is_opaque,
uint32_t *try_view_on_plane_failure_reasons);
struct drm_fb *
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
bool is_opaque, enum drm_fb_type type);
@ -844,23 +784,15 @@ wdrm_colorspace_from_output(struct weston_output *output);
#ifdef BUILD_DRM_GBM
extern struct drm_fb *
drm_fb_get_from_paint_node(struct drm_output_state *state,
struct weston_paint_node *pnode,
uint32_t *try_view_on_plane_failure_reasons);
struct weston_paint_node *pnode);
extern bool
drm_can_scanout_dmabuf(struct weston_backend *backend,
struct linux_dmabuf_buffer *dmabuf);
struct drm_fb *
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
struct drm_device *device, bool is_opaque,
bool direct_display, bool is_internal,
uint32_t *try_view_on_plane_failure_reasons);
#else
static inline struct drm_fb *
drm_fb_get_from_paint_node(struct drm_output_state *state,
struct weston_paint_node *pnode,
uint32_t *try_view_on_plane_failure_reasons)
struct weston_paint_node *pnode)
{
return NULL;
}
@ -917,7 +849,7 @@ void
drm_plane_state_free(struct drm_plane_state *state, bool force);
void
drm_plane_state_put_back(struct drm_plane_state *state);
void
bool
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
struct weston_paint_node *node,
uint64_t zpos);
@ -930,14 +862,6 @@ drm_assign_planes(struct weston_output *output_base);
bool
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
bool
drm_plane_supports_color_encoding(struct drm_plane *plane,
enum wdrm_plane_color_encoding encoding);
bool
drm_plane_supports_color_range(struct drm_plane *plane,
enum wdrm_plane_color_range range);
void
drm_output_render(struct drm_output_state *state);
@ -969,18 +893,6 @@ drm_output_fini_egl(struct drm_output *output);
struct drm_fb *
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
int
init_vulkan(struct drm_backend *b);
int
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b);
void
drm_output_fini_vulkan(struct drm_output *output);
struct drm_fb *
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage);
#else
inline static int
init_egl(struct drm_backend *b)
@ -1005,29 +917,4 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
{
return NULL;
}
inline static int
init_vulkan(struct drm_backend *b)
{
weston_log("Compiled without GBM support\n");
return -1;
}
inline static int
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
{
return -1;
}
inline static void
drm_output_fini_vulkan(struct drm_output *output)
{
}
inline static struct drm_fb *
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
{
return NULL;
}
#endif

View file

@ -56,8 +56,6 @@ enum wdrm_plane_property {
WDRM_PLANE_ZPOS,
WDRM_PLANE_ROTATION,
WDRM_PLANE_ALPHA,
WDRM_PLANE_COLOR_ENCODING,
WDRM_PLANE_COLOR_RANGE,
WDRM_PLANE__COUNT
};
@ -84,27 +82,6 @@ enum wdrm_plane_rotation {
WDRM_PLANE_ROTATION__COUNT,
};
/**
* Possible values for the WDRM_PLANE_COLOR_ENCODING property.
*/
enum wdrm_plane_color_encoding {
WDRM_PLANE_COLOR_ENCODING_BT601 = 0,
WDRM_PLANE_COLOR_ENCODING_BT709,
WDRM_PLANE_COLOR_ENCODING_BT2020,
WDRM_PLANE_COLOR_ENCODING__COUNT
};
#define WDRM_PLANE_COLOR_ENCODING_DEFAULT WDRM_PLANE_COLOR_ENCODING_BT709
/**
* Possible values for the WDRM_PLANE_COLOR_RANGE property.
*/
enum wdrm_plane_color_range {
WDRM_PLANE_COLOR_RANGE_LIMITED = 0,
WDRM_PLANE_COLOR_RANGE_FULL,
WDRM_PLANE_COLOR_RANGE__COUNT
};
#define WDRM_PLANE_COLOR_RANGE_DEFAULT WDRM_PLANE_COLOR_RANGE_LIMITED
/**
* List of properties attached to a DRM connector
*/
@ -123,7 +100,6 @@ enum wdrm_connector_property {
WDRM_CONNECTOR_MAX_BPC,
WDRM_CONNECTOR_CONTENT_TYPE,
WDRM_CONNECTOR_COLORSPACE,
WDRM_CONNECTOR_VRR_CAPABLE,
WDRM_CONNECTOR__COUNT
};

View file

@ -38,7 +38,6 @@
#include "drm-internal.h"
#include "pixel-formats.h"
#include "renderer-gl/gl-renderer.h"
#include "shared/weston-assert.h"
#define POISON_PTR ((void *)8)
@ -206,7 +205,6 @@ static int
drm_virtual_output_repaint(struct weston_output *output_base)
{
struct drm_output_state *state = NULL;
struct weston_compositor *compositor = output_base->compositor;
struct drm_output *output = to_drm_output(output_base);
struct drm_plane *scanout_plane = output->scanout_plane;
struct drm_plane_state *scanout_state;
@ -229,10 +227,14 @@ drm_virtual_output_repaint(struct weston_output *output_base)
assert(!output->state_last);
/* assign_planes() is always called before a repaint, so we must have a
* valid output state here. */
/* If planes have been disabled in the core, we might not have
* hit assign_planes at all, so might not have valid output state
* here. */
state = drm_pending_state_get_output(pending_state, output);
weston_assert_ptr_not_null(compositor, state);
if (!state)
state = drm_output_state_duplicate(output->state_cur,
pending_state,
DRM_OUTPUT_STATE_CLEAR_PLANES);
drm_output_render(state);
scanout_state = drm_output_state_get_plane(state, scanout_plane);
@ -316,6 +318,8 @@ drm_virtual_output_enable(struct weston_output *output_base)
output->base.assign_planes = drm_assign_planes;
output->base.set_dpms = NULL;
output->base.switch_mode = NULL;
output->base.gamma_size = 0;
output->base.set_gamma = NULL;
weston_compositor_stack_plane(b->compositor,
&output->scanout_plane->base,
@ -339,13 +343,6 @@ drm_virtual_output_disable(struct weston_output *base)
return 0;
}
static void
drm_virtual_prepare_repaint(struct weston_output *base)
{
struct drm_output *output = to_drm_output(base);
output->device->will_repaint = true;
}
static struct weston_output *
drm_virtual_output_create(struct weston_compositor *c, char *name,
void (*destroy_func)(struct weston_output *))
@ -375,11 +372,9 @@ drm_virtual_output_create(struct weston_compositor *c, char *name,
output->base.enable = drm_virtual_output_enable;
output->base.destroy = drm_virtual_output_destroy;
output->base.disable = drm_virtual_output_disable;
output->base.prepare_repaint = drm_virtual_prepare_repaint;
output->base.attach_head = NULL;
output->backend = b;
output->base.backend = &b->base;
output->state_cur = drm_output_state_alloc(output);
weston_compositor_add_pending_output(&output->base, c);

File diff suppressed because it is too large Load diff

View file

@ -114,21 +114,13 @@ static void gem_handle_put(struct drm_device *device, int handle)
static int
drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
{
int bo_fd = -1;
int bo_fd;
uint32_t handle;
int ret;
/* neither a BO nor a direct-display means we shouldn't be calling this */
assert(!!fb->bo ^ fb->direct_display);
if (fb->bo) {
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
if (bo_fd < 0)
return bo_fd;
}
if (fb->direct_display)
bo_fd = fb->fds[plane];
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
if (bo_fd < 0)
return bo_fd;
/*
* drmPrimeFDToHandle is dangerous, because the GEM handles are
@ -155,10 +147,7 @@ drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
fb->handles[plane] = gem_handle_get(device, handle);
out:
/* on the direct-display path the dup'ed fds will be closed by
* drm_fb_destroy_dmabuf */
if (fb->bo)
close(bo_fd);
close(bo_fd);
return ret;
}
#endif
@ -182,32 +171,23 @@ drm_fb_maybe_import(struct drm_device *device, struct drm_fb *fb)
struct gbm_device *gbm_device;
int ret = 0;
int plane;
int num_planes;
/* No import possible, if there is no gbm bo or fb is not using
* direct-display */
if (!fb->bo && !fb->direct_display)
/* No import possible, if there is no gbm bo */
if (!fb->bo)
return 0;
if (fb->bo) {
/* No import necessary, if the gbm bo and the fb use the same device */
gbm_device = gbm_bo_get_device(fb->bo);
if (gbm_device_get_fd(gbm_device) == fb->fd)
return 0;
/* No import necessary, if the gbm bo and the fb use the same device */
gbm_device = gbm_bo_get_device(fb->bo);
if (gbm_device_get_fd(gbm_device) == fb->fd)
return 0;
if (fb->fd != device->drm.fd) {
weston_log("fb was not allocated for scanout device %s\n",
device->drm.filename);
return -1;
}
num_planes = gbm_bo_get_plane_count(fb->bo);
if (fb->fd != device->drm.fd) {
weston_log("fb was not allocated for scanout device %s\n",
device->drm.filename);
return -1;
}
if (fb->direct_display)
num_planes = fb->num_planes;
for (plane = 0; plane < num_planes; plane++) {
for (plane = 0; plane < gbm_bo_get_plane_count(fb->bo); plane++) {
ret = drm_fb_import_plane(device, fb, plane);
if (ret)
goto err;
@ -384,35 +364,27 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb)
* If we imported the dmabuf into a scanout device, we are responsible
* for closing the GEM handle.
*/
for (i = 0; i < MAX_DMABUF_PLANES; i++) {
if (fb->scanout_device && fb->handles[i] != 0) {
for (i = 0; i < 4; i++)
if (fb->scanout_device && fb->handles[i] != 0)
gem_handle_put(fb->scanout_device, fb->handles[i]);
fb->handles[i] = 0;
}
}
for (i = 0; i < fb->num_duped_fds; i++)
close(fb->fds[i]);
drm_fb_destroy(fb);
}
struct drm_fb *
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
struct drm_device *device, bool is_opaque,
bool direct_display, bool is_internal,
uint32_t *try_view_on_plane_failure_reasons)
static struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_device *device, bool is_opaque,
uint32_t *try_view_on_plane_failure_reasons)
{
struct drm_backend *backend = device->backend;
struct drm_fb *fb;
int i;
struct gbm_import_fd_modifier_data import_mod = {
.width = attributes->width,
.height = attributes->height,
.format = attributes->format,
.num_fds = attributes->n_planes,
.modifier = attributes->modifier,
.width = dmabuf->attributes.width,
.height = dmabuf->attributes.height,
.format = dmabuf->attributes.format,
.num_fds = dmabuf->attributes.n_planes,
.modifier = dmabuf->attributes.modifier,
};
/* We should not import to KMS a buffer that has been allocated using no
@ -422,7 +394,7 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
* KMS driver can't know. So giving the buffer to KMS is not safe, as
* not knowing its layout can result in garbage being displayed. In
* short, importing a buffer to KMS requires explicit modifiers. */
if (attributes->modifier == DRM_FORMAT_MOD_INVALID) {
if (dmabuf->attributes.modifier == DRM_FORMAT_MOD_INVALID) {
if (try_view_on_plane_failure_reasons)
*try_view_on_plane_failure_reasons |=
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
@ -438,7 +410,7 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
* these types of buffers should be handled through buffer
* transforms and not as spot-checks requiring specific
* knowledge. */
if (attributes->flags)
if (dmabuf->attributes.flags)
return NULL;
fb = zalloc(sizeof *fb);
@ -446,30 +418,12 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
return NULL;
fb->refcnt = 1;
fb->type = is_internal ? BUFFER_DMABUF_BACKEND : BUFFER_DMABUF;
fb->type = BUFFER_DMABUF;
fb->backend = device->backend;
ARRAY_COPY(import_mod.fds, attributes->fd);
ARRAY_COPY(import_mod.strides, attributes->stride);
ARRAY_COPY(import_mod.offsets, attributes->offset);
/* skip bo import if dmabuf is using direct-display extension */
if (direct_display) {
fb->direct_display = true;
/* we're making a dup of the fds from attributes->fd as
* opposed to just copying the fds with ARRAY_COPY() */
for (i = 0; i < attributes->n_planes; i++) {
fb->fds[i] = dup(attributes->fd[i]);
if (fb->fds[i] == -1) {
weston_log("failed to dup dmabuf attribute fd: %s\n",
strerror(errno));
goto err_free;
}
fb->num_duped_fds++;
}
goto bo_import_skip;
}
ARRAY_COPY(import_mod.fds, dmabuf->attributes.fd);
ARRAY_COPY(import_mod.strides, dmabuf->attributes.stride);
ARRAY_COPY(import_mod.offsets, dmabuf->attributes.offset);
fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
&import_mod, GBM_BO_USE_SCANOUT);
@ -480,20 +434,19 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
goto err_free;
}
bo_import_skip:
fb->width = attributes->width;
fb->height = attributes->height;
fb->modifier = attributes->modifier;
fb->width = dmabuf->attributes.width;
fb->height = dmabuf->attributes.height;
fb->modifier = dmabuf->attributes.modifier;
fb->size = 0;
fb->fd = device->drm.fd;
ARRAY_COPY(fb->strides, attributes->stride);
ARRAY_COPY(fb->offsets, attributes->offset);
ARRAY_COPY(fb->strides, dmabuf->attributes.stride);
ARRAY_COPY(fb->offsets, dmabuf->attributes.offset);
fb->format = pixel_format_get_info(attributes->format);
fb->format = pixel_format_get_info(dmabuf->attributes.format);
if (!fb->format) {
weston_log("couldn't look up format info for 0x%lx\n",
(unsigned long) attributes->format);
(unsigned long) dmabuf->attributes.format);
goto err_free;
}
@ -508,8 +461,8 @@ bo_import_skip:
goto err_free;
}
fb->num_planes = attributes->n_planes;
for (i = 0; fb->bo && i < attributes->n_planes; i++) {
fb->num_planes = dmabuf->attributes.n_planes;
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
union gbm_bo_handle handle;
handle = gbm_bo_get_handle_for_plane(fb->bo, i);
@ -535,18 +488,6 @@ err_free:
return NULL;
}
struct drm_fb *
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
struct drm_device *device, bool is_opaque,
uint32_t *try_view_on_plane_failure_reasons)
{
return drm_fb_get_from_dmabuf_attributes(&dmabuf->attributes,
device, is_opaque,
dmabuf->direct_display,
false,
try_view_on_plane_failure_reasons);
}
struct drm_fb *
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
bool is_opaque, enum drm_fb_type type)
@ -641,7 +582,6 @@ drm_fb_unref(struct drm_fb *fb)
gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
break;
case BUFFER_DMABUF:
case BUFFER_DMABUF_BACKEND:
drm_fb_destroy_dmabuf(fb);
break;
#endif
@ -734,8 +674,7 @@ drm_fb_handle_buffer_destroy(struct wl_listener *listener, void *data)
struct drm_fb *
drm_fb_get_from_paint_node(struct drm_output_state *state,
struct weston_paint_node *pnode,
uint32_t *try_view_on_plane_failure_reasons)
struct weston_paint_node *pnode)
{
struct drm_output *output = state->output;
struct drm_backend *b = output->backend;
@ -750,13 +689,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
ev->surface->desired_protection > output->base.current_protection) {
*try_view_on_plane_failure_reasons |=
pnode->try_view_on_plane_failure_reasons |=
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION;
return NULL;
}
if (!buffer) {
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
return NULL;
}
@ -772,7 +711,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
wl_list_for_each(buf_fb, &private->buffer_fb_list, link) {
if (buf_fb->device == device) {
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
return buf_fb->fb ? drm_fb_ref(buf_fb->fb) : NULL;
}
}
@ -783,7 +722,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
/* GBM is used for dmabuf import as well as from client wl_buffer. */
if (!b->gbm) {
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
goto unsuitable;
}
@ -802,13 +741,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
if (!fb) {
*try_view_on_plane_failure_reasons |=
FAILURE_REASONS_ADD_FB_FAILED;
pnode->try_view_on_plane_failure_reasons |=
(1 << FAILURE_REASONS_ADD_FB_FAILED);
gbm_bo_destroy(bo);
goto unsuitable;
}
} else {
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
goto unsuitable;
}
@ -837,7 +776,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
return fb;
unsuitable:
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
return NULL;
}
#endif

View file

@ -79,27 +79,6 @@ struct drm_property_enum_info plane_rotation_enums[] = {
},
};
struct drm_property_enum_info plane_color_encoding_enums[] = {
[WDRM_PLANE_COLOR_ENCODING_BT601] = {
.name = "ITU-R BT.601 YCbCr",
},
[WDRM_PLANE_COLOR_ENCODING_BT709] = {
.name = "ITU-R BT.709 YCbCr",
},
[WDRM_PLANE_COLOR_ENCODING_BT2020] = {
.name = "ITU-R BT.2020 YCbCr",
},
};
struct drm_property_enum_info plane_color_range_enums[] = {
[WDRM_PLANE_COLOR_RANGE_LIMITED] = {
.name = "YCbCr limited range",
},
[WDRM_PLANE_COLOR_RANGE_FULL] = {
.name = "YCbCr full range",
},
};
const struct drm_property_info plane_props[] = {
[WDRM_PLANE_TYPE] = {
.name = "type",
@ -124,18 +103,8 @@ const struct drm_property_info plane_props[] = {
.name = "rotation",
.enum_values = plane_rotation_enums,
.num_enum_values = WDRM_PLANE_ROTATION__COUNT,
},
},
[WDRM_PLANE_ALPHA] = { .name = "alpha" },
[WDRM_PLANE_COLOR_ENCODING] = {
.name = "COLOR_ENCODING",
.enum_values = plane_color_encoding_enums,
.num_enum_values = WDRM_PLANE_COLOR_ENCODING__COUNT,
},
[WDRM_PLANE_COLOR_RANGE] = {
.name = "COLOR_RANGE",
.enum_values = plane_color_range_enums,
.num_enum_values = WDRM_PLANE_COLOR_RANGE__COUNT,
},
};
struct drm_property_enum_info dpms_state_enums[] = {
@ -249,9 +218,6 @@ const struct drm_property_info connector_props[] = {
.enum_values = colorspace_enums,
.num_enum_values = WDRM_COLORSPACE__COUNT,
},
[WDRM_CONNECTOR_VRR_CAPABLE] = {
.name = "vrr_capable",
},
};
const struct drm_property_info crtc_props[] = {
@ -429,17 +395,6 @@ drm_rotation_from_output_transform(struct drm_plane *plane,
return out;
}
static int
wdrm_vrr_enabled_from_output(struct drm_output *drm_output)
{
struct weston_output *output = &drm_output->base;
if (output->vrr_mode == WESTON_VRR_MODE_GAME)
return 1;
return 0;
}
/**
* Cache DRM property values
*
@ -671,36 +626,26 @@ fallback:
return 0;
}
bool
drm_plane_supports_color_encoding(struct drm_plane *plane,
enum wdrm_plane_color_encoding encoding)
void
drm_output_set_gamma(struct weston_output *output_base,
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
{
const struct drm_property_info *info;
const struct drm_property_enum_info *enum_info;
int rc;
struct drm_output *output = to_drm_output(output_base);
struct drm_device *device = output->device;
assert(encoding >= 0);
assert(encoding < WDRM_PLANE_COLOR_ENCODING__COUNT);
assert(output);
info = &plane->props[WDRM_PLANE_COLOR_ENCODING];
enum_info = &info->enum_values[encoding];
/* check */
if (output_base->gamma_size != size)
return;
return enum_info->valid;
}
bool
drm_plane_supports_color_range(struct drm_plane *plane,
enum wdrm_plane_color_range range)
{
const struct drm_property_info *info;
const struct drm_property_enum_info *enum_info;
assert(range >= 0);
assert(range < WDRM_PLANE_COLOR_RANGE__COUNT);
info = &plane->props[WDRM_PLANE_COLOR_RANGE];
enum_info = &info->enum_values[range];
return enum_info->valid;
output->deprecated_gamma_is_set = true;
rc = drmModeCrtcSetGamma(device->drm.fd,
output->crtc->crtc_id,
size, r, g, b);
if (rc)
weston_log("set gamma failed: %s\n", strerror(errno));
}
/**
@ -820,7 +765,7 @@ err:
static void
drm_output_reset_legacy_gamma(struct drm_output *output)
{
uint32_t len = output->legacy_gamma_size;
uint32_t len = output->base.gamma_size;
uint16_t *lut;
uint32_t i;
int ret;
@ -875,6 +820,18 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
connectors[n_conn++] = head->connector.connector_id;
}
/* If disable_planes is set then assign_planes() wasn't
* called for this render, so we could still have a stale
* cursor plane set up.
*/
if (output->base.disable_planes) {
drm_output_set_cursor_view(output, NULL);
if (output->cursor_plane) {
output->cursor_plane->base.x = INT32_MIN;
output->cursor_plane->base.y = INT32_MIN;
}
}
if (state->dpms != WESTON_DPMS_ON) {
if (output->cursor_plane) {
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,
@ -933,7 +890,8 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
goto err;
}
drm_output_reset_legacy_gamma(output);
if (!output->deprecated_gamma_is_set)
drm_output_reset_legacy_gamma(output);
}
pinfo = scanout_state->fb->format;
@ -1239,47 +1197,6 @@ drm_connector_set_colorspace(struct drm_connector *connector,
WDRM_CONNECTOR_COLORSPACE, enum_info->value);
}
static int
drm_plane_set_color_encoding(struct drm_plane *plane,
enum wdrm_plane_color_encoding color_encoding,
drmModeAtomicReq *req)
{
if (color_encoding == WDRM_PLANE_COLOR_ENCODING__COUNT)
return 0;
if (plane->props[WDRM_PLANE_COLOR_ENCODING].prop_id == 0) {
if (color_encoding == WDRM_PLANE_COLOR_ENCODING_DEFAULT)
return 0;
return -1;
}
assert(drm_plane_supports_color_encoding(plane, color_encoding));
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_ENCODING,
color_encoding);
}
static int
drm_plane_set_color_range(struct drm_plane *plane,
enum wdrm_plane_color_range color_range,
drmModeAtomicReq *req)
{
if (color_range == WDRM_PLANE_COLOR_RANGE__COUNT)
return 0;
if (plane->props[WDRM_PLANE_COLOR_RANGE].prop_id == 0) {
if (color_range == WDRM_PLANE_COLOR_RANGE_DEFAULT)
return 0;
return -1;
}
assert(drm_plane_supports_color_range(plane, color_range));
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_RANGE, color_range);
}
static int
drm_output_apply_state_atomic(struct drm_output_state *state,
drmModeAtomicReq *req,
@ -1321,18 +1238,14 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
current_mode->blob_id);
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
if (output->base.from_blend_to_output_by_backend &&
output->blend_to_output_xform)
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_GAMMA_LUT,
output->blend_to_output_xform->blob_id);
else
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_GAMMA_LUT, 0);
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_DEGAMMA_LUT, 0);
if (!output->deprecated_gamma_is_set) {
ret |= crtc_add_prop_zero_ok(req, crtc,
WDRM_CRTC_GAMMA_LUT, 0);
ret |= crtc_add_prop_zero_ok(req, crtc,
WDRM_CRTC_DEGAMMA_LUT, 0);
}
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_CTM, 0);
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED,
wdrm_vrr_enabled_from_output(output));
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED, 0);
/* No need for the DPMS property, since it is implicit in
* routing and CRTC activity. */
@ -1352,11 +1265,6 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
ret |= connector_add_prop(req, &wb_state->wb->connector,
WDRM_CONNECTOR_WRITEBACK_OUT_FENCE_PTR,
(uintptr_t)&wb_state->out_fence_fd);
drm_debug(b, "\t\t\t[CONN:%lu] FORMAT: %s\n",
(unsigned long) wb_state->wb->connector.connector_id,
wb_state->fb->format->drm_format_name);
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY))
wb_state->state = DRM_OUTPUT_WB_SCREENSHOT_CHECK_FENCE;
}
@ -1374,13 +1282,11 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
wl_list_for_each(head, &output->base.head_list, base.output_link)
ret |= connector_add_prop(req, &head->connector,
WDRM_CONNECTOR_CRTC_ID, 0);
}
wl_list_for_each_safe(head, tmp, &output->disable_head, disable_head_link) {
ret |= connector_add_prop(req, &head->connector,
WDRM_CONNECTOR_CRTC_ID, 0);
*flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
wl_list_for_each_safe(head, tmp, &output->disable_head,
disable_head_link) {
ret |= connector_add_prop(req, &head->connector,
WDRM_CONNECTOR_CRTC_ID, 0);
wl_list_remove(&head->disable_head_link);
wl_list_init(&head->disable_head_link);
}
@ -1467,13 +1373,6 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
WDRM_PLANE_ALPHA,
plane_state->alpha);
ret |= drm_plane_set_color_encoding(plane,
plane_state->color_encoding,
req);
ret |= drm_plane_set_color_range(plane,
plane_state->color_range, req);
if (ret != 0) {
weston_log("couldn't set plane state\n");
return ret;
@ -1625,10 +1524,7 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
if (ret != 0) {
weston_log("atomic: couldn't compile atomic state\n");
if (mode == DRM_STATE_TEST_ONLY)
goto out_test_only;
else
goto out;
goto out;
}
if (may_tear)
tear_flag = DRM_MODE_PAGE_FLIP_ASYNC;
@ -1646,8 +1542,12 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
if (ret == 0)
drm_pending_state_clear_tearing(pending_state);
}
if (mode == DRM_STATE_TEST_ONLY)
goto out_test_only;
/* Test commits do not take ownership of the state; return
* without freeing here. */
if (mode == DRM_STATE_TEST_ONLY) {
drmModeAtomicFree(req);
return ret;
}
if (ret != 0) {
wl_list_for_each(output_state, &pending_state->output_list, link)
@ -1668,11 +1568,8 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
assert(wl_list_empty(&pending_state->output_list));
out:
drm_pending_state_free(pending_state);
/* Test commits do not take ownership of the state; return
* without freeing here. */
out_test_only:
drmModeAtomicFree(req);
drm_pending_state_free(pending_state);
return ret;
}
@ -1768,9 +1665,6 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
if (b->compositor->renderer->type == WESTON_RENDERER_GL) {
drm_output_fini_egl(output);
drm_output_init_egl(output, b);
} else if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
drm_output_fini_vulkan(output);
drm_output_init_vulkan(output, b);
}
}
}
@ -1864,7 +1758,6 @@ page_flip_handler(int fd, unsigned int frame,
assert(output->page_flip_pending);
output->page_flip_pending = false;
output->page_flips_counted++;
drm_output_update_complete(output, flags, sec, usec);
}
@ -1878,8 +1771,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
struct drm_crtc *crtc;
struct drm_output *output;
struct timespec now;
float page_flips_per_timer_interval;
uint32_t frame_counter_interval;
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
@ -1895,14 +1786,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
if (!output || !output->base.enabled)
return;
output->page_flips_counted++;
/* store them temporarily as drm_output_update_complete might destroy
* the output */
page_flips_per_timer_interval = output->page_flips_per_timer_interval;
frame_counter_interval =
output->backend->perf_page_flips_stats.frame_counter_interval;
drm_output_update_msc(output, frame);
if (output->state_cur->tear) {
@ -1923,8 +1806,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
drm_output_update_complete(output, flags, sec, usec);
drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
drm_debug(b, "[atomic][CRTC:%u] %.2f page flips computed in %d seconds\n",
crtc_id, page_flips_per_timer_interval, frame_counter_interval);
}
int
@ -1994,29 +1875,10 @@ init_kms_caps(struct drm_device *device)
return -1;
}
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
if (ret != 0)
cap = 0;
/* Between Linux 3.16 and Linux 4.1 there was a bug that
* could result in a stale timestamp being returned.
*
* The workaround for this has can make it impossible
* to display images with precise timing.
*
* It's somewhat difficult to determine whether we need
* that workaround or not, but we know that the
* DRM_CAP_CRTC_IN_VBLANK_EVENT drm cap exists in 4.12
* and on. We'll use its presence to gate the workaround.
*/
if (!cap) {
weston_log("DRM Warning: stale timestamp workaround for Kernel older than 4.12\n");
device->backend->stale_timestamp_workaround = true;
} else {
device->backend->stale_timestamp_workaround = false;
}
if (!getenv("WESTON_DISABLE_ATOMIC")) {
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
if (ret != 0)
cap = 0;
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
device->atomic_modeset = ((ret == 0) && (cap == 1));
}

View file

@ -2,6 +2,20 @@ if not get_option('backend-drm')
subdir_done()
endif
dep_libdisplay_info = dependency(
'libdisplay-info',
version: ['>= 0.1.1', '< 0.3.0'],
fallback: ['display-info', 'di_dep'],
default_options: [
'werror=false',
],
required: true,
not_found_message: 'Required by DRM-backend.',
)
if dep_libdisplay_info.version().version_compare('>= 0.2.0')
config_h.set('HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY', '1')
endif
lib_backlight = static_library(
'backlight',
'libbacklight.c',
@ -34,7 +48,6 @@ srcs_drm = [
deps_drm = [
dep_egl, # optional
dep_vulkan, # optional
dep_libm,
dep_libdl,
dep_libshared,
@ -56,17 +69,7 @@ if get_option('renderer-gl')
config_h.set('BUILD_DRM_GBM', '1')
endif
if get_option('renderer-vulkan')
if not dep_gbm.found()
error('drm-backend with Vulkan renderer requires gbm which was not found. Or, you can use \'-Drenderer-vulkan=false\'.')
endif
deps_drm += dep_gbm
srcs_drm += 'drm-gbm.c'
config_h.set('BUILD_DRM_GBM', '1')
endif
if get_option('deprecated-backend-drm-screencast-vaapi')
warning('deprecated-backend-drm-screencast-vaapi enabled. This option will be removed in future versions.')
if get_option('backend-drm-screencast-vaapi')
foreach name : [ 'libva', 'libva-drm' ]
d = dependency(name, version: '>= 0.34.0', required: false)
if not d.found()

View file

@ -31,8 +31,6 @@
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <libdisplay-info/cta.h>
#include <libdisplay-info/edid.h>
#include <libdisplay-info/info.h>
#include "drm-internal.h"
@ -53,10 +51,6 @@ struct drm_head_info {
* enum weston_colorimetry_mode bits.
*/
uint32_t colorimetry_mask;
/* The monitor supported color foramts, combination of
* enum_weston_color_format bits. */
uint32_t color_format_mask;
};
static void
@ -233,6 +227,8 @@ parse_modeline(const char *s, drmModeModeInfo *mode)
return 0;
}
#ifdef HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY
static uint32_t
get_eotf_mask(const struct di_info *info)
{
@ -288,76 +284,22 @@ get_colorimetry_mask(const struct di_info *info)
return mask;
}
static bool
has_yuv420_cap_map(const struct di_edid_cta *cta)
#else /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
static uint32_t
get_eotf_mask(const struct di_info *info)
{
const struct di_cta_data_block *const *data_blocks;
enum di_cta_data_block_tag db_tag;
int i;
data_blocks = di_edid_cta_get_data_blocks(cta);
for (i = 0; data_blocks[i] != NULL; i++) {
db_tag = di_cta_data_block_get_tag(data_blocks[i]);
if (db_tag == DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP)
return true;
}
return false;
return WESTON_EOTF_MODE_SDR;
}
static uint32_t
get_color_format_mask(const struct di_info *info)
get_colorimetry_mask(const struct di_info *info)
{
const struct di_edid *edid = di_info_get_edid(info);
const struct di_edid_color_encoding_formats *fmts =
di_edid_get_color_encoding_formats(edid);
const struct di_edid_ext *const *exts = di_edid_get_extensions(edid);
uint32_t mask = WESTON_COLOR_FORMAT_AUTO;
int i;
if (fmts) {
if (fmts->rgb444)
mask |= WESTON_COLOR_FORMAT_RGB;
if (fmts->ycrcb444)
mask |= WESTON_COLOR_FORMAT_YUV444;
if (fmts->ycrcb422)
mask |= WESTON_COLOR_FORMAT_YUV422;
}
for (i = 0; exts[i] ; i++) {
const struct di_edid_cta *cta;
const struct di_edid_cta_flags *cta_flags;
switch (di_edid_ext_get_tag(exts[i])) {
case DI_EDID_EXT_CEA:
cta = di_edid_ext_get_cta(exts[i]);
cta_flags = di_edid_cta_get_flags(cta);
mask |= WESTON_COLOR_FORMAT_RGB;
if (cta_flags->ycc444)
mask |= WESTON_COLOR_FORMAT_YUV444;
if (cta_flags->ycc422)
mask |= WESTON_COLOR_FORMAT_YUV422;
/* FIXME: YUV420 detection is really complicated,
* do it properly at some point...
*/
if (has_yuv420_cap_map(cta))
mask |= WESTON_COLOR_FORMAT_YUV420;
break;
default:
break;
}
}
return mask;
return WESTON_COLORIMETRY_MODE_DEFAULT;
}
#endif /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
static struct di_info *
drm_head_info_from_edid(struct drm_head_info *dhi,
const uint8_t *data,
@ -383,7 +325,6 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
dhi->serial_number = di_info_get_serial(di_ctx);
dhi->eotf_mask = get_eotf_mask(di_ctx);
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
dhi->color_format_mask = get_color_format_mask(di_ctx);
return di_ctx;
}
@ -656,46 +597,26 @@ void
update_head_from_connector(struct drm_head *head)
{
struct drm_connector *connector = &head->connector;
struct drm_backend *b = head->connector.device->backend;
drmModeObjectProperties *props = connector->props_drm;
drmModeConnector *conn = connector->conn;
int vrr_capable;
uint32_t vrr_mode_mask = 0;
uint32_t conn_id = head->connector.connector_id;
bool ret;
ret = weston_head_set_non_desktop(&head->base,
weston_head_set_non_desktop(&head->base,
check_non_desktop(connector, props));
if (ret)
drm_debug(b, "\t[CONN:%d] non-desktop property changed\n", conn_id);
ret = weston_head_set_subpixel(&head->base,
weston_head_set_subpixel(&head->base,
drm_subpixel_to_wayland(conn->subpixel));
if (ret)
drm_debug(b, "\t[CONN:%d] subpixel property changed\n", conn_id);
ret = weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
if (ret)
drm_debug(b, "\t[CONN:%d] physical size changed\n", conn_id);
weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
ret = weston_head_set_transform(&head->base,
weston_head_set_transform(&head->base,
get_panel_orientation(connector, props));
if (ret)
drm_debug(b, "\t[CONN:%d] transform property changed\n", conn_id);
/* Unknown connection status is assumed disconnected. */
ret = weston_head_set_connection_status(&head->base,
weston_head_set_connection_status(&head->base,
conn->connection == DRM_MODE_CONNECTED);
if (ret)
drm_debug(b, "\t[CONN:%d] connection status changed\n", conn_id);
/* If EDID did not change, skip everything about it */
if (!drm_head_maybe_update_display_data(head, props)) {
if (!ret)
drm_debug(b, "\t[CONN:%d] Hot-plug event received "
"but no connector changes detected\n", conn_id);
if (!drm_head_maybe_update_display_data(head, props))
return;
}
struct drm_head_info dhi;
@ -709,18 +630,11 @@ update_head_from_connector(struct drm_head *head)
dhi.serial_number);
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
dhi.colorimetry_mask &= drm_head_get_kms_colorimetry_modes(head);
weston_head_set_supported_colorimetry_mask(&head->base, dhi.colorimetry_mask);
vrr_capable = drm_property_get_value(&head->connector.props[WDRM_CONNECTOR_VRR_CAPABLE],
head->connector.props_drm, 0);
if (vrr_capable)
vrr_mode_mask = WESTON_VRR_MODE_GAME;
weston_head_set_supported_vrr_modes_mask(&head->base, vrr_mode_mask);
drm_head_info_fini(&dhi);
}
@ -998,7 +912,7 @@ drm_output_set_mode(struct weston_output *base,
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
/* Set native_ fields, so weston_output_mode_switch_to_native() works */
weston_output_copy_native_mode(&output->base, output->base.current_mode);
output->base.native_mode = output->base.current_mode;
output->base.native_scale = output->base.current_scale;
return 0;

View file

@ -55,9 +55,6 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
state->alpha = (plane->alpha_max < DRM_PLANE_ALPHA_OPAQUE) ?
plane->alpha_max : DRM_PLANE_ALPHA_OPAQUE;
state->color_encoding = WDRM_PLANE_COLOR_ENCODING__COUNT;
state->color_range = WDRM_PLANE_COLOR_RANGE__COUNT;
/* Here we only add the plane state to the desired link, and not
* set the member. Having an output pointer set means that the
* plane will be displayed on the output; this won't be the case
@ -216,7 +213,7 @@ drm_plane_state_put_back(struct drm_plane_state *state)
* Given a weston_view, fill the drm_plane_state's co-ordinates to display on
* a given plane.
*/
void
bool
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
struct weston_paint_node *node,
uint64_t zpos)
@ -231,11 +228,8 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
uint16_t min_alpha = state->plane->alpha_min;
uint16_t max_alpha = state->plane->alpha_max;
/* The caller has already checked supported transforms when creating
* a list of candidate planes, so we should only ever get here with
* a supported transform.
*/
assert(drm_paint_node_transform_supported(node, state->plane));
if (!drm_paint_node_transform_supported(node, state->plane))
return false;
assert(node->valid_transform);
state->rotation = drm_rotation_from_output_transform(state->plane, node->transform);
@ -318,6 +312,8 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
* never exceed max_alpha if ev->alpha <= 1.0.
*/
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
return true;
}
/**
@ -407,9 +403,6 @@ drm_output_state_duplicate(struct drm_output_state *src,
assert(dst);
/* The reuse bit isn't stored in the state */
assert(!(src->mode & DRM_OUTPUT_PROPOSE_STATE_REUSE));
/* Copy the whole structure, then individually modify the
* pending_state, as well as the list link into our pending
* state. */

File diff suppressed because it is too large Load diff

View file

@ -42,8 +42,7 @@
#include "pixel-formats.h"
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "renderer-borders.h"
#include "gl-borders.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/weston-egl-ext.h"
#include "shared/cairo-util.h"
@ -70,8 +69,6 @@ struct headless_backend {
int refresh;
bool repaint_only_on_capture;
bool use_fake_seat;
};
struct headless_head {
@ -84,10 +81,12 @@ struct headless_output {
struct weston_mode mode;
struct wl_event_source *finish_frame_timer;
weston_renderbuffer_t renderbuffer;
struct weston_renderbuffer *renderbuffer;
struct frame *frame;
struct weston_renderer_borders borders;
struct {
struct weston_gl_borders borders;
} gl;
};
static const uint32_t headless_formats[] = {
@ -145,15 +144,15 @@ finish_frame_handler(void *data)
}
static void
headless_output_update_renderer_border(struct headless_output *output)
headless_output_update_gl_border(struct headless_output *output)
{
if (!output->frame)
return;
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
return;
weston_renderer_borders_update(&output->borders, output->frame,
&output->base);
weston_gl_borders_update(&output->gl.borders, output->frame,
&output->base);
}
static int
@ -162,12 +161,13 @@ headless_output_repaint(struct weston_output *output_base)
struct headless_output *output = to_headless_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
int delay_msec;
assert(output);
ec = output->base.compositor;
headless_output_update_renderer_border(output);
headless_output_update_gl_border(output);
pixman_region32_init(&damage);
@ -178,7 +178,8 @@ headless_output_repaint(struct weston_output *output_base)
pixman_region32_fini(&damage);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
delay_msec = millihz_to_nsec(output->mode.refresh) / 1000000;
wl_event_source_timer_update(output->finish_frame_timer, delay_msec);
return 0;
}
@ -189,9 +190,9 @@ headless_output_disable_gl(struct headless_output *output)
struct weston_compositor *compositor = output->base.compositor;
const struct weston_renderer *renderer = compositor->renderer;
weston_renderer_borders_fini(&output->borders, &output->base);
weston_gl_borders_fini(&output->gl.borders, &output->base);
renderer->destroy_renderbuffer(output->renderbuffer);
weston_renderbuffer_unref(output->renderbuffer);
output->renderbuffer = NULL;
renderer->gl->output_destroy(&output->base);
@ -201,30 +202,12 @@ headless_output_disable_gl(struct headless_output *output)
}
}
static void
headless_output_disable_vulkan(struct headless_output *output)
{
struct weston_compositor *compositor = output->base.compositor;
const struct weston_renderer *renderer = compositor->renderer;
weston_renderer_borders_fini(&output->borders, &output->base);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
renderer->vulkan->output_destroy(&output->base);
if (output->frame) {
frame_destroy(output->frame);
output->frame = NULL;
}
}
static void
headless_output_disable_pixman(struct headless_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
renderer->destroy_renderbuffer(output->renderbuffer);
weston_renderbuffer_unref(output->renderbuffer);
output->renderbuffer = NULL;
renderer->pixman->output_destroy(&output->base);
}
@ -248,9 +231,6 @@ headless_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
headless_output_disable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
headless_output_disable_vulkan(output);
break;
case WESTON_RENDERER_PIXMAN:
headless_output_disable_pixman(output);
break;
@ -321,8 +301,9 @@ headless_output_enable_gl(struct headless_output *output)
}
output->renderbuffer =
renderer->create_renderbuffer(&output->base, b->formats[0],
NULL, 0, NULL, NULL);
renderer->gl->create_fbo(&output->base, b->formats[0],
options.fb_size.width,
options.fb_size.height, NULL);
if (!output->renderbuffer)
goto err_renderbuffer;
@ -334,67 +315,10 @@ err_renderbuffer:
return -1;
}
static int
headless_output_enable_vulkan(struct headless_output *output)
{
struct headless_backend *b = output->backend;
const struct weston_renderer *renderer = b->compositor->renderer;
const struct weston_mode *mode = output->base.current_mode;
struct vulkan_renderer_surfaceless_options options = { 0 };
if (b->decorate) {
/*
* Start with a dummy exterior size and then resize, because
* there is no frame_create() with interior size.
*/
output->frame = frame_create(b->theme, 100, 100,
FRAME_BUTTON_CLOSE, NULL, NULL);
if (!output->frame) {
weston_log("failed to create frame for output\n");
return -1;
}
frame_resize_inside(output->frame, mode->width, mode->height);
options.fb_size.width = frame_width(output->frame);
options.fb_size.height = frame_height(output->frame);
frame_interior(output->frame, &options.area.x, &options.area.y,
&options.area.width, &options.area.height);
} else {
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
}
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
weston_log("failed to create vulkan renderer output state\n");
if (output->frame) {
frame_destroy(output->frame);
output->frame = NULL;
}
return -1;
}
output->renderbuffer =
renderer->create_renderbuffer(&output->base, b->formats[0],
NULL, 0, NULL, NULL);
if (!output->renderbuffer)
goto err_renderbuffer;
return 0;
err_renderbuffer:
renderer->vulkan->output_destroy(&output->base);
return -1;
}
static int
headless_output_enable_pixman(struct headless_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
const struct pixman_renderer_interface *pixman;
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
@ -404,19 +328,22 @@ headless_output_enable_pixman(struct headless_output *output)
.format = pixel_format_get_info(headless_formats[0])
};
if (renderer->pixman->output_create(&output->base, &options) < 0)
pixman = output->base.compositor->renderer->pixman;
if (pixman->output_create(&output->base, &options) < 0)
return -1;
output->renderbuffer =
renderer->create_renderbuffer(&output->base, options.format,
NULL, 0, NULL, NULL);
pixman->create_image(&output->base, options.format,
output->base.current_mode->width,
output->base.current_mode->height);
if (!output->renderbuffer)
goto err_renderer;
return 0;
err_renderer:
renderer->pixman->output_destroy(&output->base);
pixman->output_destroy(&output->base);
return -1;
}
@ -446,9 +373,6 @@ headless_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL:
ret = headless_output_enable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
ret = headless_output_enable_vulkan(output);
break;
case WESTON_RENDERER_PIXMAN:
ret = headless_output_enable_pixman(output);
break;
@ -466,19 +390,6 @@ headless_output_enable(struct weston_output *base)
return 0;
}
static void
headless_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct headless_output *output = to_headless_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
headless_output_set_size(struct weston_output *base,
int width, int height)
@ -520,7 +431,7 @@ headless_output_set_size(struct weston_output *base,
output->base.repaint = headless_output_repaint;
output->base.assign_planes = NULL;
output->base.set_backlight = NULL;
output->base.set_dpms = headless_set_dpms;
output->base.set_dpms = NULL;
output->base.switch_mode = NULL;
return 0;
@ -600,25 +511,6 @@ headless_head_destroy(struct weston_head *base)
free(head);
}
static bool
headless_input_create(struct headless_backend *b)
{
weston_seat_init(&b->fake_seat, b->compositor, "default");
weston_seat_init_pointer(&b->fake_seat);
if (weston_seat_init_keyboard(&b->fake_seat, NULL) < 0)
return false;
return true;
}
static void
headless_input_destroy(struct headless_backend *b)
{
weston_seat_release(&b->fake_seat);
}
static void
headless_destroy(struct weston_backend *backend)
{
@ -636,9 +528,6 @@ headless_destroy(struct weston_backend *backend)
if (b->theme)
theme_destroy(b->theme);
if (b->use_fake_seat)
headless_input_destroy(b);
free(b->formats);
free(b);
@ -670,12 +559,6 @@ headless_backend_create(struct weston_compositor *compositor,
b->base.supported_presentation_clocks =
WESTON_PRESENTATION_CLOCKS_SOFTWARE;
if (config->fake_seat) {
b->use_fake_seat = headless_input_create(b);
if (!b->use_fake_seat)
goto err_free;
}
b->base.destroy = headless_destroy;
b->base.create_output = headless_output_create;
@ -717,16 +600,6 @@ headless_backend_create(struct weston_compositor *compositor,
&options.base);
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
ret = weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base);
break;
}
case WESTON_RENDERER_PIXMAN:
if (config->decorate) {
weston_log("Error: Pixman renderer does not support decorations.\n");
@ -774,8 +647,6 @@ err_input:
if (b->theme)
theme_destroy(b->theme);
err_free:
if (b->use_fake_seat)
headless_input_destroy(b);
wl_list_remove(&b->base.link);
free(b);
return NULL;
@ -785,7 +656,6 @@ static void
config_init_to_defaults(struct weston_headless_backend_config *config)
{
config->refresh = DEFAULT_OUTPUT_REPAINT_REFRESH;
config->fake_seat = false;
}
WL_EXPORT int

View file

@ -17,7 +17,7 @@ plugin_headless = shared_library(
dep_libweston_private,
dep_libdrm_headers,
dep_lib_cairo_shared,
dep_lib_renderer_borders,
dep_lib_gl_borders,
],
name_prefix: '',
install: true,

View file

@ -56,11 +56,9 @@
#include <libweston/backend-pipewire.h>
#include <libweston/linux-dmabuf.h>
#include <libweston/weston-log.h>
#include "output-capture.h"
#include "pixel-formats.h"
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-egl-ext.h"
struct pipewire_backend {
@ -103,7 +101,7 @@ struct pipewire_head {
};
struct pipewire_frame_data {
weston_renderbuffer_t renderbuffer;
struct weston_renderbuffer *renderbuffer;
struct pipewire_memfd *memfd;
struct pipewire_dmabuf *dmabuf;
};
@ -268,16 +266,14 @@ pipewire_output_connect(struct pipewire_output *output)
/* TODO: Add support for modifier discovery and negotiation. */
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
params[i++] = spa_pod_build_format(&builder,
output->base.current_mode->width,
output->base.current_mode->height,
output->base.width, output->base.height,
output->base.current_mode->refresh / 1000,
output->pixel_format->format,
modifier);
}
params[i++] = spa_pod_build_format(&builder,
output->base.current_mode->width,
output->base.current_mode->height,
output->base.width, output->base.height,
output->base.current_mode->refresh / 1000,
output->pixel_format->format, NULL);
@ -311,8 +307,8 @@ pipewire_output_enable_pixman(struct pipewire_output *output)
const struct pixman_renderer_output_options options = {
.use_shadow = true,
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
.width = output->base.width,
.height = output->base.height,
},
.format = output->pixel_format,
};
@ -351,29 +347,6 @@ pipewire_output_enable_gl(struct pipewire_output *output)
return renderer->gl->output_fbo_create(&output->base, &options);
}
static int
pipewire_output_enable_vulkan(struct pipewire_output *output)
{
struct pipewire_backend *b = output->backend;
struct weston_renderer *renderer = b->compositor->renderer;
const struct weston_size fb_size = {
output->base.current_mode->width,
output->base.current_mode->height
};
const struct weston_geometry area = {
.x = 0,
.y = 0,
.width = fb_size.width,
.height = fb_size.height
};
const struct vulkan_renderer_surfaceless_options options = {
.fb_size = fb_size,
.area = area,
};
return renderer->vulkan->output_surfaceless_create(&output->base, &options);
}
static void
pipewire_output_disable_gl(struct pipewire_output *output)
{
@ -382,14 +355,6 @@ pipewire_output_disable_gl(struct pipewire_output *output)
renderer->gl->output_destroy(&output->base);
}
static void
pipewire_output_disable_vulkan(struct pipewire_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
renderer->vulkan->output_destroy(&output->base);
}
static int
pipewire_output_enable(struct weston_output *base)
{
@ -408,9 +373,6 @@ pipewire_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL:
ret = pipewire_output_enable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
ret = pipewire_output_enable_vulkan(output);
break;
default:
unreachable("Valid renderer should have been selected");
}
@ -436,9 +398,6 @@ err:
case WESTON_RENDERER_GL:
pipewire_output_disable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
pipewire_output_disable_vulkan(output);
break;
default:
unreachable("Valid renderer should have been selected");
}
@ -467,9 +426,6 @@ pipewire_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
pipewire_output_disable_gl(output);
break;
case WESTON_RENDERER_VULKAN:
pipewire_output_disable_vulkan(output);
break;
default:
unreachable("Valid renderer should have been selected");
}
@ -534,8 +490,8 @@ pipewire_output_create_dmabuf(struct pipewire_output *output)
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
format = output->pixel_format;
width = output->base.current_mode->width;
height = output->base.current_mode->height;
width = output->base.width;
height = output->base.height;
linux_dmabuf_memory = renderer->dmabuf_alloc(renderer, width, height,
format->format,
@ -637,6 +593,59 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
pw_stream_update_params(output->stream, params, 2);
}
static struct weston_renderbuffer *
pipewire_output_stream_add_buffer_pixman(struct pipewire_output *output,
struct pw_buffer *buffer)
{
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
struct spa_buffer *buf = buffer->buffer;
struct spa_data *d = buf->datas;
const struct pixel_format_info *format;
unsigned int width;
unsigned int height;
unsigned int stride;
void *ptr;
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
stride = width * format->bpp / 8;
ptr = d[0].data;
return renderer->pixman->create_image_from_ptr(&output->base,
format, width, height,
ptr, stride);
}
static struct weston_renderbuffer *
pipewire_output_stream_add_buffer_gl(struct pipewire_output *output,
struct pw_buffer *buffer)
{
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
struct spa_buffer *buf = buffer->buffer;
struct spa_data *d = buf->datas;
const struct pixel_format_info *format;
unsigned int width;
unsigned int height;
void *ptr;
struct pipewire_frame_data *frame_data = buffer->user_data;
struct pipewire_dmabuf *dmabuf = frame_data->dmabuf;
if (dmabuf)
return renderer->create_renderbuffer_dmabuf(&output->base,
dmabuf->linux_dmabuf_memory);
format = output->pixel_format;
width = output->base.width;
height = output->base.height;
ptr = d[0].data;
return renderer->gl->create_fbo(&output->base,
format, width, height, ptr);
}
struct pipewire_memfd {
int fd;
unsigned int size;
@ -656,8 +665,8 @@ pipewire_output_create_memfd(struct pipewire_output *output)
memfd = xzalloc(sizeof *memfd);
format = output->pixel_format;
width = output->base.current_mode->width;
height = output->base.current_mode->height;
width = output->base.width;
height = output->base.height;
stride = width * format->bpp / 8;
size = height * stride;
@ -746,15 +755,8 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
return;
}
pipewire_output_setup_dmabuf(output, buffer, dmabuf);
frame_data->renderbuffer =
renderer->create_renderbuffer_dmabuf(&output->base,
dmabuf->linux_dmabuf_memory,
NULL, NULL);
frame_data->dmabuf = dmabuf;
} else if (buffertype & (1u << SPA_DATA_MemFd)) {
const struct pixel_format_info *format = output->pixel_format;
int stride = output->base.current_mode->width * format->bpp / 8;
struct pipewire_memfd *memfd;
memfd = pipewire_output_create_memfd(output);
@ -764,13 +766,19 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
return;
}
pipewire_output_setup_memfd(output, buffer, memfd);
frame_data->renderbuffer =
renderer->create_renderbuffer(&output->base, format,
d[0].data, stride, NULL,
NULL);
frame_data->memfd = memfd;
}
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN:
frame_data->renderbuffer = pipewire_output_stream_add_buffer_pixman(output, buffer);
break;
case WESTON_RENDERER_GL:
frame_data->renderbuffer = pipewire_output_stream_add_buffer_gl(output, buffer);
break;
default:
unreachable("Valid renderer should have been selected");
}
}
struct pipewire_fence_data {
@ -792,20 +800,21 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
pipewire_output_debug(output, "remove buffer: %p", buffer);
if (frame_data->dmabuf)
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
if (frame_data->dmabuf) {
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
renderer->remove_renderbuffer_dmabuf(&output->base,
frame_data->renderbuffer);
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
}
if (frame_data->memfd) {
munmap(d[0].data, d[0].maxsize);
pipewire_destroy_memfd(output, frame_data->memfd);
}
if (frame_data->renderbuffer) {
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
renderer->destroy_renderbuffer(frame_data->renderbuffer);
}
if (frame_data->renderbuffer)
weston_renderbuffer_unref(frame_data->renderbuffer);
wl_list_for_each(fence_data, &output->fence_list, link) {
if (fence_data->buffer == buffer)
fence_data->buffer = NULL;
@ -946,7 +955,7 @@ pipewire_submit_buffer(struct pipewire_output *output,
if (dmabuf)
stride = dmabuf->linux_dmabuf_memory->attributes->stride[0];
else
stride = output->base.current_mode->width * pixel_format->bpp / 8;
stride = output->base.width * pixel_format->bpp / 8;
size = output->base.height * stride;
spa_buffer = buffer->buffer;
@ -999,20 +1008,9 @@ pipewire_schedule_submit_buffer(struct pipewire_output *output,
struct wl_event_loop *loop;
int fence_sync_fd;
switch (renderer->type) {
case WESTON_RENDERER_GL:
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
if (fence_sync_fd == -1)
return -1;
break;
case WESTON_RENDERER_VULKAN:
fence_sync_fd = renderer->vulkan->create_fence_fd(&output->base);
if (fence_sync_fd == -1)
return -1;
break;
default:
unreachable("invalid renderer");
}
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
if (fence_sync_fd == -1)
return -1;
fence_data = zalloc(sizeof *fence_data);
if (!fence_data) {
@ -1044,7 +1042,6 @@ pipewire_output_repaint(struct weston_output *base)
struct pipewire_frame_data *frame_data;
pixman_region32_t damage;
bool submit_scheduled = false;
bool rendered = false;
assert(output);
@ -1055,8 +1052,7 @@ pipewire_output_repaint(struct weston_output *base)
weston_output_flush_damage_for_primary_plane(base, &damage);
if (!pixman_region32_not_empty(&damage) &&
!weston_output_has_renderer_capture_tasks(base))
if (!pixman_region32_not_empty(&damage))
goto out;
buffer = pw_stream_dequeue_buffer(output->stream);
@ -1067,10 +1063,9 @@ pipewire_output_repaint(struct weston_output *base)
pipewire_output_debug(output, "dequeued buffer: %p", buffer);
frame_data = buffer->user_data;
if (frame_data->renderbuffer) {
if (frame_data->renderbuffer)
ec->renderer->repaint_output(&output->base, &damage, frame_data->renderbuffer);
rendered = true;
} else
else
output->base.full_repaint_needed = true;
if (buffer->buffer->datas[0].type == SPA_DATA_DmaBuf) {
@ -1081,21 +1076,6 @@ pipewire_output_repaint(struct weston_output *base)
pipewire_submit_buffer(output, buffer);
out:
/* We didn't have anywhere to render to, so capture tasks could be
* left dangling. Shoot them down.
*/
if (!rendered && weston_output_has_renderer_capture_tasks(base)) {
int width = base->current_mode->width;
int height = base->current_mode->height;
struct weston_capture_task *ct;
while ((ct = weston_output_pull_capture_task(base,
WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER,
width, height,
ec->read_format,
NULL)))
weston_capture_task_retire_failed(ct, "No pipewire buffer");
}
pixman_region32_fini(&damage);
@ -1136,19 +1116,6 @@ pipewire_ensure_matching_mode(struct weston_output *output, struct weston_mode *
target->refresh);
}
static void
pipewire_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct pipewire_output *output = to_pipewire_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
{
@ -1162,8 +1129,7 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode
base->current_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
base->current_mode = local_mode;
weston_output_copy_native_mode(base, local_mode);
base->current_mode = base->native_mode = local_mode;
base->current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
fb_size.width = target_mode->width;
@ -1175,13 +1141,14 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode
}
static int
pipewire_output_set_size(struct weston_output *base, int width, int height, int framerate)
pipewire_output_set_size(struct weston_output *base, int width, int height)
{
struct pipewire_output *output = to_pipewire_output(base);
struct weston_head *head;
struct pipewire_head *pw_head;
struct weston_mode *current_mode;
struct weston_mode init_mode;
int framerate = -1;
/* We can only be called once. */
assert(!output->base.current_mode);
@ -1193,8 +1160,7 @@ pipewire_output_set_size(struct weston_output *base, int width, int height, int
width = pw_head->config.width;
if (height == -1)
height = pw_head->config.height;
if (framerate == -1)
framerate = pw_head->config.framerate;
framerate = pw_head->config.framerate;
}
if (framerate == -1 || width == -1 || height == -1)
return -1;
@ -1206,13 +1172,13 @@ pipewire_output_set_size(struct weston_output *base, int width, int height, int
current_mode = pipewire_ensure_matching_mode(&output->base, &init_mode);
current_mode->flags = WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
output->base.current_mode = current_mode;
weston_output_copy_native_mode(base, current_mode);
output->base.current_mode = output->base.native_mode = current_mode;
output->base.start_repaint_loop = pipewire_output_start_repaint_loop;
output->base.repaint = pipewire_output_repaint;
output->base.assign_planes = NULL;
output->base.set_backlight = NULL;
output->base.set_dpms = pipewire_set_dpms;
output->base.set_dpms = NULL;
output->base.switch_mode = pipewire_switch_mode;
return 0;
@ -1385,16 +1351,6 @@ pipewire_backend_create(struct weston_compositor *compositor,
&options.base);
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = backend->formats,
.formats_count = backend->formats_count,
};
ret = weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base);
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_compositor;
@ -1460,7 +1416,6 @@ weston_backend_init(struct weston_compositor *compositor,
switch (compositor->renderer->type) {
case WESTON_RENDERER_PIXMAN:
case WESTON_RENDERER_GL:
case WESTON_RENDERER_VULKAN:
break;
default:
weston_log("Renderer not supported by PipeWire backend\n");

View file

@ -9,7 +9,6 @@ dep_frdp2 = dependency('freerdp2', version: '>= 2.3.0', required: false)
if dep_frdp3.found()
config_h.set('USE_FREERDP_VERSION', '3')
config_h.set('WITHOUT_FREERDP_3x_DEPRECATED', '1')
dep_frdp = dep_frdp3
dep_frdp_server = dependency('freerdp-server3', version: '>= 3.0.0', required: false)
if not dep_frdp_server.found()

View file

@ -46,7 +46,6 @@
#include <libweston/pixel-formats.h>
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-egl-ext.h"
/* These can be removed when we bump FreeRDP dependency past 3.0.0 in the future */
@ -59,12 +58,6 @@
extern PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
static struct rdp_buffer *
rdp_buffer_create(struct rdp_output *output);
static void
rdp_buffer_destroy(struct rdp_buffer *buffer);
static BOOL
xf_peer_adjust_monitor_layout(freerdp_peer *client);
@ -268,11 +261,11 @@ rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
rdpSettings *settings = peer->context->settings;
if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec))
rdp_peer_refresh_rfx(region, output->buffer->shadow_surface, peer);
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
else if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
rdp_peer_refresh_nsc(region, output->buffer->shadow_surface, peer);
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
else
rdp_peer_refresh_raw(region, output->buffer->shadow_surface, peer);
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
}
static int
@ -302,7 +295,7 @@ rdp_output_repaint(struct weston_output *output_base)
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(&output->base, &damage,
output->buffer->rb);
output->renderbuffer);
if (pixman_region32_not_empty(&damage)) {
pixman_region32_t transformed_damage;
@ -353,15 +346,53 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
struct weston_output *output = base;
struct rdp_peers_item *rdpPeer;
rdpSettings *settings;
struct weston_renderbuffer *new_renderbuffer;
mode->refresh = b->rdp_monitor_refresh_rate;
weston_output_set_single_mode(base, mode);
if (base->enabled)
if (base->enabled) {
const struct weston_renderer *renderer;
pixman_image_t *new_image;
weston_renderer_resize_output(output, &(struct weston_size){
.width = output->current_mode->width,
.height = output->current_mode->height }, NULL);
new_image = pixman_image_create_bits(b->formats[0]->pixman_format,
mode->width, mode->height,
NULL, mode->width * 4);
renderer = b->compositor->renderer;
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_interface *pixman;
pixman = renderer->pixman;
new_renderbuffer =
pixman->create_image_from_ptr(output, b->formats[0],
mode->width, mode->height,
pixman_image_get_data(new_image),
mode->width * 4);
break;
}
case WESTON_RENDERER_GL:
new_renderbuffer =
renderer->gl->create_fbo(output, b->formats[0],
mode->width, mode->height,
pixman_image_get_data(new_image));
break;
default:
unreachable("cannot have auto renderer at runtime");
}
pixman_image_composite32(PIXMAN_OP_SRC, rdpOutput->shadow_surface,
0, new_image, 0, 0, 0, 0, 0, 0,
mode->width, mode->height);
weston_renderbuffer_unref(rdpOutput->renderbuffer);
rdpOutput->renderbuffer = new_renderbuffer;
pixman_image_unref(rdpOutput->shadow_surface);
rdpOutput->shadow_surface = new_image;
}
/* Apparently settings->DesktopWidth is supposed to be primary only.
* For now we only work with a single monitor, so we don't need to
* check that we're primary here.
@ -384,19 +415,6 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
}
}
static void
rdp_output_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct rdp_output *output = to_rdp_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
rdp_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
{
@ -418,88 +436,11 @@ rdp_head_get_monitor(struct weston_head *base,
monitor->desktop_scale = h->config.attributes.desktopScaleFactor;
}
static bool
rdp_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
{
struct rdp_buffer *buffer = (struct rdp_buffer *) data;
struct rdp_output *output = buffer->output;
rdp_buffer_destroy(buffer);
output->buffer = rdp_buffer_create(output);
if (output->buffer == NULL)
return false;
return true;
}
static struct rdp_buffer *
rdp_buffer_create(struct rdp_output *output)
{
const struct pixel_format_info *format = output->backend->formats[0];
struct weston_renderer *rdr = output->base.compositor->renderer;
pixman_image_t *shadow_surface;
weston_renderbuffer_t rb;
struct rdp_buffer *buffer;
shadow_surface = pixman_image_create_bits(format->pixman_format,
output->base.current_mode->width,
output->base.current_mode->height,
NULL,
output->base.current_mode->width * 4);
buffer = xmalloc(sizeof *buffer);
rb = rdr->create_renderbuffer(&output->base, format,
pixman_image_get_data(shadow_surface),
output->base.current_mode->width * 4,
rdp_rb_discarded_cb, buffer);
if (rb == NULL) {
weston_log("Failed to create offscreen renderbuffer.\n");
pixman_image_unref(shadow_surface);
free(buffer);
return NULL;
}
buffer->output = output;
buffer->shadow_surface = shadow_surface;
buffer->rb = rb;
return buffer;
}
static void
rdp_buffer_destroy(struct rdp_buffer *buffer)
{
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
pixman_image_unref(buffer->shadow_surface);
rdr->destroy_renderbuffer(buffer->rb);
free(buffer);
}
static void
rdp_renderer_output_destroy(struct weston_output *base)
{
struct weston_renderer *rdr = base->compositor->renderer;
switch (rdr->type) {
case WESTON_RENDERER_PIXMAN:
rdr->pixman->output_destroy(base);
break;
case WESTON_RENDERER_GL:
rdr->gl->output_destroy(base);
break;
case WESTON_RENDERER_VULKAN:
rdr->vulkan->output_destroy(base);
break;
default:
unreachable("cannot have auto renderer at runtime");
}
}
static int
rdp_output_enable(struct weston_output *base)
{
const struct weston_renderer *renderer = base->compositor->renderer;
const struct pixman_renderer_interface *pixman = renderer->pixman;
struct rdp_output *output = to_rdp_output(base);
struct rdp_backend *b;
struct wl_event_loop *loop;
@ -508,6 +449,12 @@ rdp_output_enable(struct weston_output *base)
b = output->backend;
output->shadow_surface = pixman_image_create_bits(b->formats[0]->pixman_format,
output->base.current_mode->width,
output->base.current_mode->height,
NULL,
output->base.current_mode->width * 4);
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_output_options options = {
@ -518,8 +465,23 @@ rdp_output_enable(struct weston_output *base)
.format = b->formats[0],
};
if (renderer->pixman->output_create(&output->base, &options) < 0)
if (renderer->pixman->output_create(&output->base, &options) < 0) {
return -1;
}
output->renderbuffer =
pixman->create_image_from_ptr(&output->base, options.format,
output->base.current_mode->width,
output->base.current_mode->height,
pixman_image_get_data(output->shadow_surface),
output->base.current_mode->width * 4);
if (output->renderbuffer == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
renderer->pixman->output_destroy(&output->base);
pixman_image_unref(output->shadow_surface);
output->shadow_surface = NULL;
return -1;
}
break;
}
case WESTON_RENDERER_GL: {
@ -534,24 +496,19 @@ rdp_output_enable(struct weston_output *base)
},
};
if (renderer->gl->output_fbo_create(&output->base, &options) < 0) {
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
return -1;
}
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_surfaceless_options options = {
.area = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
};
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
output->renderbuffer =
renderer->gl->create_fbo(&output->base, b->formats[0],
output->base.current_mode->width,
output->base.current_mode->height,
pixman_image_get_data(output->shadow_surface));
if (output->renderbuffer == NULL) {
weston_log("Failed to create surface for frame buffer.\n");
renderer->pixman->output_destroy(&output->base);
pixman_image_unref(output->shadow_surface);
output->shadow_surface = NULL;
return -1;
}
break;
@ -560,12 +517,6 @@ rdp_output_enable(struct weston_output *base)
unreachable("cannot have auto renderer at runtime");
}
output->buffer = rdp_buffer_create(output);
if (output->buffer == NULL) {
rdp_renderer_output_destroy(base);
return -1;
}
loop = wl_display_get_event_loop(b->compositor->wl_display);
output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
@ -575,6 +526,7 @@ rdp_output_enable(struct weston_output *base)
static int
rdp_output_disable(struct weston_output *base)
{
struct weston_renderer *renderer = base->compositor->renderer;
struct rdp_output *output = to_rdp_output(base);
assert(output);
@ -582,9 +534,21 @@ rdp_output_disable(struct weston_output *base)
if (!output->base.enabled)
return 0;
rdp_buffer_destroy(output->buffer);
output->buffer = NULL;
rdp_renderer_output_destroy(base);
weston_renderbuffer_unref(output->renderbuffer);
output->renderbuffer = NULL;
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN:
renderer->pixman->output_destroy(&output->base);
break;
case WESTON_RENDERER_GL:
renderer->gl->output_destroy(&output->base);
break;
default:
unreachable("cannot have auto renderer at runtime");
}
pixman_image_unref(output->shadow_surface);
output->shadow_surface = NULL;
wl_event_source_remove(output->finish_frame_timer);
return 0;
@ -620,7 +584,6 @@ rdp_output_create(struct weston_backend *backend, const char *name)
output->base.start_repaint_loop = rdp_output_start_repaint_loop;
output->base.repaint = rdp_output_repaint;
output->base.set_dpms = rdp_output_set_dpms;
output->base.switch_mode = rdp_output_switch_mode;
output->backend = b;
@ -1022,9 +985,6 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
{KBD_IRISH, 0, 0},
{KBD_BOSNIAN_CYRILLIC, "ba", "us"},
{KBD_UNITED_STATES_DVORAK, "us", "dvorak"},
{KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND, "us", "dvorak-l"},
{KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND, "us", "dvorak-r"},
{KBD_UNITED_STATES_DVORAK_PROGRAMMER, "us", "dvp"},
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "abnt2"},
{KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"},
{KBD_GAELIC, "ie", "CloGaelach"},
@ -2029,18 +1989,6 @@ rdp_backend_create(struct weston_compositor *compositor,
goto err_compositor;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0)
goto err_compositor;
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_free_strings;
@ -2165,7 +2113,6 @@ weston_backend_init(struct weston_compositor *compositor,
switch (compositor->renderer->type) {
case WESTON_RENDERER_PIXMAN:
case WESTON_RENDERER_GL:
case WESTON_RENDERER_VULKAN:
break;
default:
weston_log("Renderer not supported by RDP backend\n");

View file

@ -27,6 +27,14 @@
#ifndef RDP_H
#define RDP_H
/* Workaround an issue with clang and freerdp 3 headers. Another
* option would be to build with --std=c11 but weston itself isn't
* quite ready for that
*/
#if USE_FREERDP_VERSION >= 3 && defined(__clang__)
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
#endif
#include <freerdp/version.h>
#include <freerdp/freerdp.h>
@ -47,7 +55,6 @@
#include <winpr/string.h>
#include "backend.h"
#include "libweston-internal.h"
#include "shared/helpers.h"
#include "shared/string-helpers.h"
@ -138,17 +145,12 @@ struct rdp_head {
rdpMonitor config;
};
struct rdp_buffer {
struct rdp_output *output;
pixman_image_t *shadow_surface;
weston_renderbuffer_t rb;
};
struct rdp_output {
struct weston_output base;
struct rdp_backend *backend;
struct wl_event_source *finish_frame_timer;
struct rdp_buffer *buffer;
struct weston_renderbuffer *renderbuffer;
pixman_image_t *shadow_surface;
};
struct rdp_peer_context {

View file

@ -3,7 +3,7 @@ if not get_option('backend-vnc')
endif
config_h.set('BUILD_VNC_COMPOSITOR', '1')
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.10.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.9.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
if not dep_neatvnc.found()
error('VNC backend requires neatvnc which was not found. Or, you can use \'-Dbackend-vnc=false\'.')
endif

View file

@ -56,7 +56,6 @@
#include "pixel-formats.h"
#include "pixman-renderer.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-egl-ext.h"
#define DEFAULT_AXIS_STEP_DISTANCE 10
@ -109,18 +108,9 @@ struct vnc_head {
struct weston_head base;
};
struct vnc_buffer {
weston_renderbuffer_t rb;
struct nvnc_fb *fb;
struct vnc_output *output;
};
static void
vnc_output_destroy(struct weston_output *base);
static void
vnc_buffer_destroy(struct vnc_buffer *buffer);
static inline struct vnc_output *
to_vnc_output(struct weston_output *base)
{
@ -663,7 +653,8 @@ vnc_log_scope_print_region(struct weston_log_scope *log, pixman_region32_t *regi
}
static void
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
pixman_region32_t *update_damage)
{
char timestr[128];
@ -672,51 +663,15 @@ vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
weston_log_scope_timestamp(backend->debug, timestr, sizeof timestr);
weston_log_scope_printf(backend->debug, "%s damage:", timestr);
vnc_log_scope_print_region(backend->debug, damage);
weston_log_scope_printf(backend->debug, "%s buffer damage:", timestr);
vnc_log_scope_print_region(backend->debug, buffer_damage);
weston_log_scope_printf(backend->debug, "\n");
weston_log_scope_printf(backend->debug, "%s update damage:", timestr);
vnc_log_scope_print_region(backend->debug, update_damage);
weston_log_scope_printf(backend->debug, "\n\n");
}
static bool
vnc_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
{
struct vnc_buffer *buffer = (struct vnc_buffer *) data;
assert(nvnc_get_userdata(buffer->fb) == buffer);
nvnc_set_userdata(buffer->fb, NULL, NULL);
vnc_buffer_destroy(buffer);
return true;
}
static struct vnc_buffer *
vnc_buffer_create(struct nvnc_fb* fb, struct vnc_output *output)
{
const struct pixel_format_info *pfmt =
pixel_format_get_info(DRM_FORMAT_XRGB8888);
struct weston_renderer *rdr = output->base.compositor->renderer;
struct vnc_buffer *buffer = xmalloc(sizeof *buffer);
buffer->rb = rdr->create_renderbuffer(&output->base, pfmt,
nvnc_fb_get_addr(fb),
output->base.current_mode->width * 4,
vnc_rb_discarded_cb, buffer);
buffer->fb = fb;
buffer->output = output;
return buffer;
}
static void
vnc_buffer_destroy(struct vnc_buffer *buffer)
{
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
rdr->destroy_renderbuffer(buffer->rb);
free(buffer);
}
static void
vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
{
@ -724,7 +679,7 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
struct vnc_backend *backend = nvnc_get_userdata(server);
struct vnc_output *output = backend->output;
struct weston_compositor *ec = output->base.compositor;
struct vnc_buffer *buffer;
struct weston_renderbuffer *renderbuffer;
pixman_region32_t local_damage;
pixman_region16_t nvnc_damage;
struct nvnc_fb *fb;
@ -732,16 +687,49 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
fb = nvnc_fb_pool_acquire(output->fb_pool);
assert(fb);
buffer = nvnc_get_userdata(fb);
if (!buffer) {
buffer = vnc_buffer_create(fb, output);
nvnc_set_userdata(fb, buffer,
(nvnc_cleanup_fn) vnc_buffer_destroy);
renderbuffer = nvnc_get_userdata(fb);
if (!renderbuffer) {
const struct pixel_format_info *pfmt;
pfmt = pixel_format_get_info(DRM_FORMAT_XRGB8888);
switch (ec->renderer->type) {
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_interface *pixman;
pixman = ec->renderer->pixman;
renderbuffer =
pixman->create_image_from_ptr(&output->base, pfmt,
output->base.width,
output->base.height,
nvnc_fb_get_addr(fb),
output->base.width * 4);
break;
}
case WESTON_RENDERER_GL: {
renderbuffer =
ec->renderer->gl->create_fbo(&output->base, pfmt,
output->base.width,
output->base.height,
nvnc_fb_get_addr(fb));
break;
}
default:
unreachable("cannot have auto renderer at runtime");
}
/* This is a new buffer, so the whole surface is damaged. */
pixman_region32_copy(&renderbuffer->damage,
&output->base.region);
nvnc_set_userdata(fb, renderbuffer,
(nvnc_cleanup_fn)weston_renderbuffer_unref);
}
vnc_log_damage(backend, damage);
vnc_log_damage(backend, &renderbuffer->damage, damage);
ec->renderer->repaint_output(&output->base, damage, buffer->rb);
ec->renderer->repaint_output(&output->base, damage, renderbuffer);
/* Convert to local coordinates */
pixman_region32_init(&local_damage);
@ -821,8 +809,8 @@ vnc_output_enable(struct weston_output *base)
case WESTON_RENDERER_PIXMAN: {
const struct pixman_renderer_output_options options = {
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
.width = output->base.width,
.height = output->base.height,
},
.format = backend->formats[0],
};
@ -833,33 +821,18 @@ vnc_output_enable(struct weston_output *base)
case WESTON_RENDERER_GL: {
const struct gl_renderer_fbo_options options = {
.area = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
.width = output->base.width,
.height = output->base.height,
},
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
.width = output->base.width,
.height = output->base.height,
},
};
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
return -1;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_surfaceless_options options = {
.area = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
.fb_size = {
.width = output->base.current_mode->width,
.height = output->base.current_mode->height,
},
};
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0)
return -1;
break;
}
default:
unreachable("cannot have auto renderer at runtime");
}
@ -869,10 +842,10 @@ vnc_output_enable(struct weston_output *base)
finish_frame_handler,
output);
output->fb_pool = nvnc_fb_pool_new(output->base.current_mode->width,
output->base.current_mode->height,
output->fb_pool = nvnc_fb_pool_new(output->base.width,
output->base.height,
backend->formats[0]->format,
output->base.current_mode->width);
output->base.width);
output->display = nvnc_display_new(0, 0);
@ -906,9 +879,6 @@ vnc_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
renderer->gl->output_destroy(&output->base);
break;
case WESTON_RENDERER_VULKAN:
renderer->vulkan->output_destroy(&output->base);
break;
default:
unreachable("cannot have auto renderer at runtime");
}
@ -1082,9 +1052,6 @@ vnc_output_assign_planes(struct weston_output *base)
assert(output);
if (output->base.disable_planes)
return;
if (wl_list_empty(&output->peers))
return;
@ -1093,19 +1060,6 @@ vnc_output_assign_planes(struct weston_output *base)
vnc_output_assign_cursor_plane(output);
}
static void
vnc_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct vnc_output *output = to_vnc_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
{
@ -1119,14 +1073,7 @@ vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
fb_size.width = target_mode->width;
fb_size.height = target_mode->height;
/* vnc_buffers are stored as user data pointers into the renderbuffers
* for the discarded callback. weston_renderer_resize_output(), which
* triggers the renderbuffer's discarded callbacks, must be called
* before nvnc_fb_pool_resize(), which destroys all the nvnc_fbs and
* their associated vnc_buffers, so that the vnc_buffers are valid at
* callback. */
if (!weston_renderer_resize_output(base, &fb_size, NULL))
return -1;
weston_renderer_resize_output(base, &fb_size, NULL);
nvnc_fb_pool_resize(output->fb_pool, target_mode->width,
target_mode->height, DRM_FORMAT_XRGB8888,
@ -1158,7 +1105,7 @@ vnc_output_set_size(struct weston_output *base, int width, int height,
output->base.repaint = vnc_output_repaint;
output->base.assign_planes = vnc_output_assign_planes;
output->base.set_backlight = NULL;
output->base.set_dpms = vnc_set_dpms;
output->base.set_dpms = NULL;
output->base.switch_mode = vnc_switch_mode;
output->resizeable = resizeable;
@ -1236,17 +1183,6 @@ vnc_backend_create(struct weston_compositor *compositor,
goto err_compositor;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = backend->formats,
.formats_count = backend->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0)
goto err_compositor;
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_compositor;
@ -1388,7 +1324,6 @@ weston_backend_init(struct weston_compositor *compositor,
switch (compositor->renderer->type) {
case WESTON_RENDERER_PIXMAN:
case WESTON_RENDERER_GL:
case WESTON_RENDERER_VULKAN:
break;
default:
weston_log("Renderer not supported by VNC backend\n");

View file

@ -6,6 +6,8 @@ config_h.set('BUILD_WAYLAND_COMPOSITOR', '1')
srcs_wlwl = [
'wayland.c',
fullscreen_shell_unstable_v1_client_protocol_h,
fullscreen_shell_unstable_v1_protocol_c,
presentation_time_protocol_c,
presentation_time_server_protocol_h,
xdg_shell_client_protocol_h,
@ -19,7 +21,7 @@ deps_wlwl = [
dep_libweston_private,
dep_libdrm_headers,
dep_lib_cairo_shared,
dep_lib_renderer_borders,
dep_lib_gl_borders,
]
if get_option('renderer-gl')
@ -31,10 +33,6 @@ if get_option('renderer-gl')
deps_wlwl += dep_egl # for gl-renderer.h
endif
if get_option('renderer-vulkan')
deps_wlwl += dep_vulkan # for vulkan-renderer.h
endif
plugin_wlwl = shared_library(
'wayland-backend',
srcs_wlwl,

View file

@ -48,8 +48,7 @@
#include <libweston/libweston.h>
#include <libweston/backend-wayland.h>
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "renderer-borders.h"
#include "gl-borders.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/weston-egl-ext.h"
#include "pixman-renderer.h"
@ -59,6 +58,7 @@
#include "shared/cairo-util.h"
#include "shared/timespec-util.h"
#include "shared/xalloc.h"
#include "fullscreen-shell-unstable-v1-client-protocol.h"
#include "xdg-shell-client-protocol.h"
#include "presentation-time-server-protocol.h"
#include "linux-dmabuf.h"
@ -86,6 +86,7 @@ struct wayland_backend {
struct wl_registry *registry;
struct wl_compositor *compositor;
struct xdg_wm_base *xdg_wm_base;
struct zwp_fullscreen_shell_v1 *fshell;
struct wl_shm *shm;
struct wl_list output_list;
@ -98,6 +99,7 @@ struct wayland_backend {
bool fullscreen;
struct theme *theme;
cairo_device_t *frame_device;
struct wl_cursor_theme *cursor_theme;
struct wl_cursor *cursor;
@ -133,6 +135,7 @@ struct wayland_output {
struct {
struct wl_egl_window *egl_window;
struct weston_gl_borders borders;
} gl;
struct {
@ -140,8 +143,6 @@ struct wayland_output {
struct wl_list free_buffers;
} shm;
struct weston_renderer_borders borders;
struct weston_mode mode;
struct weston_mode native_mode;
@ -191,7 +192,7 @@ struct wayland_shm_buffer {
int height;
int frame_damaged;
weston_renderbuffer_t renderbuffer;
struct weston_renderbuffer *renderbuffer;
cairo_surface_t *c_surface;
};
@ -265,14 +266,9 @@ to_wayland_backend(struct weston_backend *base)
static void
wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
{
struct wayland_output *output = buffer->output;
const struct weston_renderer *renderer;
cairo_surface_destroy(buffer->c_surface);
if (output) {
renderer = output->base.compositor->renderer;
renderer->destroy_renderbuffer(buffer->renderbuffer);
}
if (buffer->output)
weston_renderbuffer_unref(buffer->renderbuffer);
wl_buffer_destroy(buffer->buffer);
munmap(buffer->data, buffer->size);
@ -294,22 +290,6 @@ buffer_release(void *data, struct wl_buffer *buffer)
}
}
static bool
wayland_rb_discarded_cb(weston_renderbuffer_t renderbuffer, void *data)
{
struct wayland_shm_buffer *sb = data;
const struct weston_renderer *renderer;
if (sb->renderbuffer) {
renderer = sb->output->backend->compositor->renderer;
renderer->destroy_renderbuffer(sb->renderbuffer);
sb->renderbuffer = NULL;
}
sb->output = NULL;
return true;
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
};
@ -318,6 +298,7 @@ static struct wayland_shm_buffer *
wayland_output_get_shm_buffer(struct wayland_output *output)
{
const struct weston_renderer *renderer;
const struct pixman_renderer_interface *pixman;
struct wayland_backend *b = output->backend;
const struct pixel_format_info *pfmt = b->formats[0];
uint32_t shm_format = pixel_format_get_shm_format(pfmt);
@ -403,23 +384,26 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
if (output->frame) {
frame_interior(output->frame, &area.x, &area.y,
&area.width, &area.height);
assert(area.width == output->base.current_mode->width);
assert(area.height == output->base.current_mode->height);
} else {
area.x = 0;
area.y = 0;
area.width = output->base.current_mode->width;
area.height = output->base.current_mode->height;
}
renderer = b->compositor->renderer;
pixman = renderer->pixman;
/* Address only the interior, excluding output decorations */
if (renderer->type == WESTON_RENDERER_PIXMAN)
if (renderer->type == WESTON_RENDERER_PIXMAN) {
sb->renderbuffer =
renderer->create_renderbuffer(&output->base, pfmt,
pixman->create_image_from_ptr(&output->base, pfmt,
area.width, area.height,
(uint32_t *)(data + area.y * stride) + area.x,
stride,
wayland_rb_discarded_cb,
sb);
stride);
pixman_region32_copy(&sb->renderbuffer->damage,
&output->base.region);
}
return sb;
}
@ -451,17 +435,34 @@ static const struct wl_callback_listener frame_listener = {
frame_done
};
#if defined(ENABLE_EGL) || defined(ENABLE_VULKAN)
static void
wayland_output_update_renderer_border(struct wayland_output *output)
draw_initial_frame(struct wayland_output *output)
{
struct wayland_shm_buffer *sb;
sb = wayland_output_get_shm_buffer(output);
/* If we are rendering with GL, then orphan it so that it gets
* destroyed immediately */
if (output->gl.egl_window)
sb->output = NULL;
wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
wl_surface_damage(output->parent.surface, 0, 0,
sb->width, sb->height);
}
#ifdef ENABLE_EGL
static void
wayland_output_update_gl_border(struct wayland_output *output)
{
if (!output->frame)
return;
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
return;
weston_renderer_borders_update(&output->borders, output->frame,
&output->base);
weston_gl_borders_update(&output->gl.borders, output->frame,
&output->base);
}
#endif
@ -501,36 +502,7 @@ wayland_output_repaint_gl(struct weston_output *output_base)
output->frame_cb = wl_surface_frame(output->parent.surface);
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
wayland_output_update_renderer_border(output);
ec->renderer->repaint_output(&output->base, &damage, NULL);
pixman_region32_fini(&damage);
return 0;
}
#endif
#ifdef ENABLE_VULKAN
static int
wayland_output_repaint_vulkan(struct weston_output *output_base)
{
struct wayland_output *output = to_wayland_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
ec = output->base.compositor;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
output->frame_cb = wl_surface_frame(output->parent.surface);
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
wayland_output_update_renderer_border(output);
wayland_output_update_gl_border(output);
ec->renderer->repaint_output(&output->base, &damage, NULL);
@ -693,6 +665,14 @@ wayland_output_destroy_shm_buffers(struct wayland_output *output)
/* Throw away any remaining SHM buffers */
wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
wayland_shm_buffer_destroy(buffer);
/* These will get thrown away when they get released */
wl_list_for_each(buffer, &output->shm.buffers, link) {
if (buffer->renderbuffer) {
weston_renderbuffer_unref(buffer->renderbuffer);
buffer->renderbuffer = NULL;
}
buffer->output = NULL;
}
}
static int
@ -714,18 +694,11 @@ wayland_output_disable(struct weston_output *base)
break;
#ifdef ENABLE_EGL
case WESTON_RENDERER_GL:
weston_renderer_borders_fini(&output->borders, &output->base);
weston_gl_borders_fini(&output->gl.borders, &output->base);
renderer->gl->output_destroy(&output->base);
wl_egl_window_destroy(output->gl.egl_window);
break;
#endif
#ifdef ENABLE_VULKAN
case WESTON_RENDERER_VULKAN:
weston_renderer_borders_fini(&output->borders, &output->base);
renderer->vulkan->output_destroy(&output->base);
break;
#endif
default:
unreachable("invalid renderer");
@ -807,47 +780,6 @@ cleanup_window:
}
#endif
#ifdef ENABLE_VULKAN
static int
wayland_output_init_vulkan_renderer(struct wayland_output *output)
{
const struct weston_mode *mode = output->base.current_mode;
struct wayland_backend *b = output->backend;
const struct weston_renderer *renderer;
struct vulkan_renderer_surface_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (output->frame) {
frame_interior(output->frame, &options.area.x, &options.area.y,
&options.area.width, &options.area.height);
options.fb_size.width = frame_width(output->frame);
options.fb_size.height = frame_height(output->frame);
} else {
options.area.x = 0;
options.area.y = 0;
options.area.width = mode->width;
options.area.height = mode->height;
options.fb_size.width = mode->width;
options.fb_size.height = mode->height;
}
options.wayland_display = b->parent.wl_display;
options.wayland_surface = output->parent.surface;
renderer = output->base.compositor->renderer;
if (renderer->vulkan->output_surface_create(&output->base, &options) < 0)
goto cleanup_window;
return 0;
cleanup_window:
return -1;
}
#endif
static int
wayland_output_init_pixman_renderer(struct wayland_output *output)
{
@ -882,9 +814,6 @@ wayland_output_resize_surface(struct wayland_output *output)
struct weston_geometry opa = area;
struct wl_region *region;
assert(b->compositor);
assert(b->compositor->renderer);
if (output->frame) {
frame_resize_inside(output->frame, area.width, area.height);
frame_interior(output->frame, &area.x, &area.y, NULL, NULL);
@ -920,15 +849,7 @@ wayland_output_resize_surface(struct wayland_output *output)
weston_renderer_resize_output(&output->base, &fb_size, &area);
/* These will need to be re-created due to the resize */
weston_renderer_borders_fini(&output->borders, &output->base);
} else
#endif
#ifdef ENABLE_VULKAN
if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
weston_renderer_resize_output(&output->base, &fb_size, &area);
/* These will need to be re-created due to the resize */
weston_renderer_borders_fini(&output->borders, &output->base);
weston_gl_borders_fini(&output->gl.borders, &output->base);
} else
#endif
{
@ -996,6 +917,104 @@ wayland_output_set_fullscreen(struct wayland_output *output,
}
}
static struct weston_mode *
wayland_output_choose_mode(struct wayland_output *output,
struct weston_mode *ref_mode)
{
struct weston_mode *mode;
/* First look for an exact match */
wl_list_for_each(mode, &output->base.mode_list, link)
if (mode->width == ref_mode->width &&
mode->height == ref_mode->height &&
mode->refresh == ref_mode->refresh)
return mode;
/* If we can't find an exact match, ignore refresh and try again */
wl_list_for_each(mode, &output->base.mode_list, link)
if (mode->width == ref_mode->width &&
mode->height == ref_mode->height)
return mode;
/* Yeah, we failed */
return NULL;
}
enum mode_status {
MODE_STATUS_UNKNOWN,
MODE_STATUS_SUCCESS,
MODE_STATUS_FAIL,
MODE_STATUS_CANCEL,
};
static void
mode_feedback_successful(void *data,
struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
{
enum mode_status *value = data;
printf("Mode switch successful\n");
*value = MODE_STATUS_SUCCESS;
}
static void
mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
{
enum mode_status *value = data;
printf("Mode switch failed\n");
*value = MODE_STATUS_FAIL;
}
static void
mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
{
enum mode_status *value = data;
printf("Mode switch cancelled\n");
*value = MODE_STATUS_CANCEL;
}
struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
mode_feedback_successful,
mode_feedback_failed,
mode_feedback_cancelled,
};
static enum mode_status
wayland_output_fullscreen_shell_mode_feedback(struct wayland_output *output,
struct weston_mode *mode)
{
struct wayland_backend *b = output->backend;
struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
enum mode_status mode_status;
int ret = 0;
mode_feedback =
zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
output->parent.surface,
output->parent.output,
mode->refresh);
zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
&mode_feedback_listener,
&mode_status);
draw_initial_frame(output);
wl_surface_commit(output->parent.surface);
mode_status = MODE_STATUS_UNKNOWN;
while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
ret = wl_display_dispatch(b->parent.wl_display);
zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
return mode_status;
}
static int
wayland_output_switch_mode_finish(struct wayland_output *output)
{
@ -1014,13 +1033,6 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
if (wayland_output_init_gl_renderer(output) < 0)
return -1;
break;
#endif
#ifdef ENABLE_VULKAN
case WESTON_RENDERER_VULKAN:
renderer->vulkan->output_destroy(&output->base);
if (wayland_output_init_vulkan_renderer(output) < 0)
return -1;
break;
#endif
default:
unreachable("invalid renderer");
@ -1031,6 +1043,56 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
return 0;
}
static int
wayland_output_switch_mode_fshell(struct wayland_output *output,
struct weston_mode *mode)
{
struct wayland_backend *b;
struct wl_surface *old_surface;
struct weston_mode *old_mode;
enum mode_status mode_status;
b = output->backend;
mode = wayland_output_choose_mode(output, mode);
if (mode == NULL)
return -1;
if (output->base.current_mode == mode)
return 0;
old_mode = output->base.current_mode;
old_surface = output->parent.surface;
output->base.current_mode = mode;
output->parent.surface =
wl_compositor_create_surface(b->parent.compositor);
wl_surface_set_user_data(output->parent.surface, output);
/* Blow the old buffers because we changed size/surfaces */
wayland_output_resize_surface(output);
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, mode);
/* This should kick-start things again */
wayland_output_start_repaint_loop(&output->base);
if (mode_status == MODE_STATUS_FAIL) {
output->base.current_mode = old_mode;
wl_surface_destroy(output->parent.surface);
output->parent.surface = old_surface;
wayland_output_resize_surface(output);
return -1;
}
old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
wl_surface_destroy(old_surface);
return wayland_output_switch_mode_finish(output);
}
static int
wayland_output_switch_mode_xdg(struct wayland_output *output,
struct weston_mode *mode)
@ -1074,6 +1136,8 @@ wayland_output_switch_mode(struct weston_output *output_base,
if (output->parent.xdg_surface)
return wayland_output_switch_mode_xdg(output, mode);
if (output->backend->parent.fshell)
return wayland_output_switch_mode_fshell(output, mode);
return -1;
}
@ -1193,6 +1257,7 @@ wayland_output_enable(struct weston_output *base)
const struct weston_renderer *renderer = base->compositor->renderer;
struct wayland_output *output = to_wayland_output(base);
struct wayland_backend *b;
enum mode_status mode_status;
int ret = 0;
assert(output);
@ -1228,14 +1293,6 @@ wayland_output_enable(struct weston_output *base)
output->base.repaint = wayland_output_repaint_gl;
break;
#endif
#ifdef ENABLE_VULKAN
case WESTON_RENDERER_VULKAN:
if (wayland_output_init_vulkan_renderer(output) < 0)
goto err_output;
output->base.repaint = wayland_output_repaint_vulkan;
break;
#endif
default:
unreachable("invalid renderer");
@ -1247,7 +1304,20 @@ wayland_output_enable(struct weston_output *base)
output->base.set_dpms = NULL;
output->base.switch_mode = wayland_output_switch_mode;
if (b->fullscreen) {
if (b->sprawl_across_outputs) {
if (b->parent.fshell) {
wayland_output_resize_surface(output);
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, &output->mode);
if (mode_status == MODE_STATUS_FAIL)
zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
output->parent.surface,
ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
output->parent.output);
}
} else if (b->fullscreen) {
wayland_output_set_fullscreen(output, 0, NULL);
} else {
wayland_output_set_windowed(output);
@ -2620,6 +2690,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
&xdg_wm_base_interface, 1);
xdg_wm_base_add_listener(b->parent.xdg_wm_base,
&wm_base_listener, b);
} else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
b->parent.fshell =
wl_registry_bind(registry, name,
&zwp_fullscreen_shell_v1_interface, 1);
} else if (strcmp(interface, "wl_seat") == 0) {
display_start_add_seat(b, name, version);
} else if (strcmp(interface, "wl_output") == 0) {
@ -2717,12 +2791,18 @@ wayland_destroy(struct weston_backend *backend)
if (b->parent.xdg_wm_base)
xdg_wm_base_destroy(b->parent.xdg_wm_base);
if (b->parent.fshell)
zwp_fullscreen_shell_v1_release(b->parent.fshell);
if (b->parent.compositor)
wl_compositor_destroy(b->parent.compositor);
if (b->theme)
theme_destroy(b->theme);
if (b->frame_device)
cairo_device_destroy(b->frame_device);
wl_cursor_theme_destroy(b->cursor_theme);
free(b->formats);
@ -2871,22 +2951,6 @@ wayland_backend_create(struct weston_compositor *compositor,
goto err_display;
}
break;
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0) {
weston_log("Failed to initialize the Vulkan renderer\n");
goto err_display;
}
/* For now Vulkan does not fall back to anything automatically,
* like GL renderer does. */
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_display;
@ -2926,6 +2990,8 @@ wayland_backend_destroy(struct wayland_backend *b)
if (b->theme)
theme_destroy(b->theme);
if (b->frame_device)
cairo_device_destroy(b->frame_device);
wl_cursor_theme_destroy(b->cursor_theme);
wl_list_remove(&b->base.link);
@ -2973,7 +3039,7 @@ weston_backend_init(struct weston_compositor *compositor,
if (!b)
return -1;
if (new_config.sprawl) {
if (new_config.sprawl || b->parent.fshell) {
b->sprawl_across_outputs = true;
wl_display_roundtrip(b->parent.wl_display);

View file

@ -57,7 +57,6 @@
#include "shared/timespec-util.h"
#include "shared/file-util.h"
#include "renderer-gl/gl-renderer.h"
#include "renderer-vulkan/vulkan-renderer.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/weston-egl-ext.h"
#include "shared/xalloc.h"
@ -141,7 +140,7 @@ struct x11_output {
xcb_gc_t gc;
xcb_shm_seg_t segment;
weston_renderbuffer_t renderbuffer;
struct weston_renderbuffer *renderbuffer;
int shm_id;
void *buf;
uint8_t depth;
@ -169,10 +168,6 @@ to_x11_head(struct weston_head *base)
static void
x11_output_destroy(struct weston_output *base);
static int
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
const struct pixel_format_info *pfmt);
static inline struct x11_output *
to_x11_output(struct weston_output *base)
{
@ -456,29 +451,6 @@ x11_output_repaint_gl(struct weston_output *output_base)
return 0;
}
static int
x11_output_repaint_vulkan(struct weston_output *output_base)
{
struct x11_output *output = to_x11_output(output_base);
struct weston_compositor *ec;
pixman_region32_t damage;
assert(output);
ec = output->base.compositor;
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
ec->renderer->repaint_output(output_base, &damage, NULL);
pixman_region32_fini(&damage);
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
return 0;
}
static void
set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region)
{
@ -535,6 +507,8 @@ static int
x11_output_repaint_shm(struct weston_output *output_base)
{
struct x11_output *output = to_x11_output(output_base);
const struct weston_renderer *renderer;
pixman_image_t *image;
struct weston_compositor *ec;
struct x11_backend *b;
xcb_void_cookie_t cookie;
@ -544,8 +518,11 @@ x11_output_repaint_shm(struct weston_output *output_base)
assert(output);
ec = output->base.compositor;
renderer = ec->renderer;
b = output->backend;
image = renderer->pixman->renderbuffer_get_image(output->renderbuffer);
pixman_region32_init(&damage);
weston_output_flush_damage_for_primary_plane(output_base, &damage);
@ -557,13 +534,13 @@ x11_output_repaint_shm(struct weston_output *output_base)
pixman_region32_fini(&damage);
cookie = xcb_shm_put_image_checked(b->conn, output->window, output->gc,
output_base->current_mode->width,
output_base->current_mode->height,
0, 0,
output_base->current_mode->width,
output_base->current_mode->height,
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
0, output->segment, 0);
pixman_image_get_width(image),
pixman_image_get_height(image),
0, 0,
pixman_image_get_width(image),
pixman_image_get_height(image),
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
0, output->segment, 0);
err = xcb_request_check(b->conn, cookie);
if (err != NULL) {
weston_log("Failed to put shm image, err: %d\n", err->error_code);
@ -591,7 +568,7 @@ x11_output_deinit_shm(struct x11_backend *b, struct x11_output *output)
xcb_generic_error_t *err;
xcb_free_gc(b->conn, output->gc);
b->compositor->renderer->destroy_renderbuffer(output->renderbuffer);
weston_renderbuffer_unref(output->renderbuffer);
output->renderbuffer = NULL;
cookie = xcb_shm_detach_checked(b->conn, output->segment);
err = xcb_request_check(b->conn, cookie);
@ -816,40 +793,17 @@ x11_output_get_shm_pixel_format(struct x11_output *output)
}
}
static bool
x11_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
{
struct x11_output *output = (struct x11_output *) data;
const struct pixel_format_info *pfmt;
if (output->base.compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
x11_output_deinit_shm(output->backend, output);
pfmt = x11_output_get_shm_pixel_format(output);
if (!pfmt)
return false;
if (x11_output_init_shm(output->backend, output, pfmt) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
return false;
}
}
return true;
}
static int
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
const struct pixel_format_info *pfmt)
const struct pixel_format_info *pfmt, int width, int height)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
int bitsperpixel = pfmt->bpp;
size_t size = output->base.current_mode->width *
output->base.current_mode->height * (bitsperpixel / 8);
int stride = output->base.current_mode->width * (bitsperpixel / 8);
xcb_void_cookie_t cookie;
xcb_generic_error_t *err;
/* Create SHM segment and attach it */
output->shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRWXU);
output->shm_id = shmget(IPC_PRIVATE, width * height * (bitsperpixel / 8), IPC_CREAT | S_IRWXU);
if (output->shm_id == -1) {
weston_log("x11shm: failed to allocate SHM segment\n");
return -1;
@ -873,9 +827,10 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
/* Now create pixman image */
output->renderbuffer =
renderer->create_renderbuffer(&output->base, pfmt, output->buf,
stride, x11_rb_discarded_cb,
output);
renderer->pixman->create_image_from_ptr(&output->base,
pfmt, width, height,
output->buf,
width * (bitsperpixel / 8));
output->gc = xcb_generate_id(b->conn);
xcb_create_gc(b->conn, output->gc, output->window, 0, NULL);
@ -883,19 +838,6 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
return 0;
}
static void
x11_set_dpms(struct weston_output *base, enum dpms_enum level)
{
struct x11_output *output = to_x11_output(base);
if (level == WESTON_DPMS_ON)
weston_output_schedule_repaint(base);
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
wl_event_source_timer_update(output->finish_frame_timer, 0);
weston_output_schedule_repaint_reset(base);
}
}
static int
x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
{
@ -933,8 +875,20 @@ x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
fb_size.width = output->mode.width = mode->width;
fb_size.height = output->mode.height = mode->height;
if (!weston_renderer_resize_output(&output->base, &fb_size, NULL))
return -1;
weston_renderer_resize_output(&output->base, &fb_size, NULL);
if (base->compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
const struct pixel_format_info *pfmt;
x11_output_deinit_shm(b, output);
pfmt = x11_output_get_shm_pixel_format(output);
if (!pfmt)
return -1;
if (x11_output_init_shm(b, output, pfmt,
fb_size.width, fb_size.height) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
return -1;
}
}
output->resize_pending = false;
output->window_resized = false;
@ -966,9 +920,6 @@ x11_output_disable(struct weston_output *base)
case WESTON_RENDERER_GL:
renderer->gl->output_destroy(&output->base);
break;
case WESTON_RENDERER_VULKAN:
renderer->vulkan->output_destroy(&output->base);
break;
default:
unreachable("invalid renderer");
}
@ -1117,7 +1068,8 @@ x11_output_enable(struct weston_output *base)
weston_log("Failed to create pixman renderer for output\n");
goto err;
}
if (x11_output_init_shm(b, output, options.format) < 0) {
if (x11_output_init_shm(b, output, options.format,
mode->width, mode->height) < 0) {
weston_log("Failed to initialize SHM for the X11 output\n");
renderer->pixman->output_destroy(&output->base);
goto err;
@ -1150,29 +1102,6 @@ x11_output_enable(struct weston_output *base)
output->base.repaint = x11_output_repaint_gl;
break;
}
case WESTON_RENDERER_VULKAN: {
struct vulkan_renderer_surface_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
.area.x = 0,
.area.y = 0,
.area.width = mode->width,
.area.height = mode->height,
.fb_size.width = mode->width,
.fb_size.height = mode->height,
};
options.xcb_connection = b->conn;
options.xcb_visualid = screen->root_visual;
options.xcb_window = output->window;
ret = renderer->vulkan->output_surface_create(base, &options);
if (ret < 0)
goto err;
output->base.repaint = x11_output_repaint_vulkan;
break;
}
default:
unreachable("invalid renderer");
}
@ -1180,7 +1109,7 @@ x11_output_enable(struct weston_output *base)
output->base.start_repaint_loop = x11_output_start_repaint_loop;
output->base.assign_planes = NULL;
output->base.set_backlight = NULL;
output->base.set_dpms = x11_set_dpms;
output->base.set_dpms = NULL;
output->base.switch_mode = x11_output_switch_mode;
loop = wl_display_get_event_loop(b->compositor->wl_display);
@ -1253,7 +1182,7 @@ x11_output_set_size(struct weston_output *base, int width, int height)
wl_list_insert(&output->base.mode_list, &output->mode.link);
output->base.current_mode = &output->mode;
weston_output_copy_native_mode(&output->base, &output->mode);
output->base.native_mode = &output->native;
output->base.native_scale = output->base.current_scale;
return 0;
@ -2023,17 +1952,6 @@ x11_backend_create(struct weston_compositor *compositor,
goto err_xdisplay;
break;
}
case WESTON_RENDERER_VULKAN: {
const struct vulkan_renderer_display_options options = {
.formats = b->formats,
.formats_count = b->formats_count,
};
if (weston_compositor_init_renderer(compositor,
WESTON_RENDERER_VULKAN,
&options.base) < 0)
goto err_xdisplay;
break;
}
default:
weston_log("Unsupported renderer requested\n");
goto err_xdisplay;

View file

@ -144,29 +144,29 @@ weston_head_init(struct weston_head *head, const char *name);
void
weston_head_release(struct weston_head *head);
bool
void
weston_head_set_connection_status(struct weston_head *head, bool connected);
void
weston_head_set_internal(struct weston_head *head);
bool
void
weston_head_set_monitor_strings(struct weston_head *head,
const char *make,
const char *model,
const char *serialno);
bool
void
weston_head_set_non_desktop(struct weston_head *head, bool non_desktop);
bool
void
weston_head_set_physical_size(struct weston_head *head,
int32_t mm_width, int32_t mm_height);
bool
void
weston_head_set_subpixel(struct weston_head *head,
enum wl_output_subpixel sp);
bool
void
weston_head_set_transform(struct weston_head *head, uint32_t transform);
void
@ -177,9 +177,6 @@ void
weston_head_set_supported_colorimetry_mask(struct weston_head *head,
uint32_t colorimetry_mask);
void
weston_head_set_supported_vrr_modes_mask(struct weston_head *head,
uint32_t vrr_modes_mask);
/* weston_output */
void
@ -343,7 +340,7 @@ void
notify_tablet_tool_frame(struct weston_tablet_tool *tool,
const struct timespec *time);
void
bool
weston_output_flush_damage_for_plane(struct weston_output *output,
struct weston_plane *plane,
pixman_region32_t *damage);

Some files were not shown because too many files have changed in this diff Show more