mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-16 09:28:07 +02:00
Compare commits
No commits in common. "main" and "13.0.91" have entirely different histories.
385 changed files with 25088 additions and 60646 deletions
215
.gitlab-ci.yml
215
.gitlab-ci.yml
|
|
@ -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: '2026-04-01-mesa-26.0.4'
|
||||
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
|
||||
|
|
@ -292,12 +281,18 @@ aarch64-debian-container_prep:
|
|||
.build-and-test:
|
||||
extends:
|
||||
- .default-rules
|
||||
variables:
|
||||
SANITIZE: "-Db_sanitize=address"
|
||||
script:
|
||||
- "${CI_PROJECT_DIR}/.gitlab-ci/build.sh"
|
||||
- "${CI_PROJECT_DIR}/.gitlab-ci/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
|
||||
|
|
@ -308,14 +303,18 @@ 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:
|
||||
extends:
|
||||
- .default-rules
|
||||
script:
|
||||
- "${CI_PROJECT_DIR}/.gitlab-ci/build.sh"
|
||||
- cd "$BUILDDIR"
|
||||
- meson --prefix="$PREFIX" --wrap-mode=nofallback ${MESON_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
- ninja install
|
||||
- ninja clean
|
||||
artifacts:
|
||||
name: weston-$CI_COMMIT_SHA
|
||||
when: always
|
||||
|
|
@ -426,81 +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
|
||||
-Ddeprecated-remoting=true
|
||||
-Ddeprecated-pipewire=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.
|
||||
|
|
@ -514,88 +499,62 @@ 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
|
||||
-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
|
||||
-Drenderer-gl=false
|
||||
-Dremoting=false
|
||||
-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
|
||||
-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.
|
||||
|
|
@ -607,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/
|
||||
|
|
|
|||
|
|
@ -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 drm-misc-next-2026-03-20 https://gitlab.freedesktop.org/drm/misc/kernel.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,87 +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
|
||||
|
||||
git clone --branch mesa-26.0.4 --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
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -xe
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
fdo_log_section_start_collapsed build_weston "build_weston"
|
||||
cd "$BUILDDIR"
|
||||
meson --prefix="$PREFIX" --wrap-mode=nofallback $SANITIZE ${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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -xe
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
cd "$BUILDDIR"
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
610
clients/color.c
610
clients/color.c
|
|
@ -1,610 +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;
|
||||
|
||||
bool unmanaged;
|
||||
|
||||
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 bool opt_unmanaged = false;
|
||||
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_BOOLEAN, "unmanaged", 'u', &opt_unmanaged },
|
||||
{ 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 struct color *color,
|
||||
const char *option, uint32_t *dest,
|
||||
const struct valid_enum *valid_options,
|
||||
int count, uint32_t fallback)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (color->unmanaged && option) {
|
||||
fprintf(stderr, "Option '%s' not valid in unmanaged mode\n", option);
|
||||
return false;
|
||||
}
|
||||
|
||||
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 struct color *color,
|
||||
const char *c, float *dest, float fallback)
|
||||
{
|
||||
char *end;
|
||||
float value;
|
||||
|
||||
if (color->unmanaged && c) {
|
||||
fprintf(stderr, "Luminance not valid in unmanaged mode.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
color->unmanaged = opt_unmanaged;
|
||||
|
||||
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(color, opt_primaries, &color->primaries,
|
||||
valid_primaries,
|
||||
ARRAY_LENGTH(valid_primaries),
|
||||
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
|
||||
validate_option(color, opt_transfer_function, &color->transfer_function,
|
||||
valid_transfer_functions,
|
||||
ARRAY_LENGTH(valid_transfer_functions),
|
||||
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
|
||||
validate_luminance(color, opt_min_lum, &color->min_lum, -1.f) &&
|
||||
validate_luminance(color, opt_max_lum, &color->max_lum, -1.f) &&
|
||||
validate_luminance(color, 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, " Mode of operation may be:\n");
|
||||
fprintf(stderr, " --unmanaged or -u: do not use color-management\n");
|
||||
fprintf(stderr, " Or use the following:\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_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);
|
||||
}
|
||||
|
||||
if (color->unmanaged)
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 (!color->unmanaged && !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 (color->unmanaged || set_image_description(color, color->widget))
|
||||
display_run(color->display);
|
||||
|
||||
color_destroy(color);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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, §ion, &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",
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -42,7 +40,10 @@ dep_toytoolkit = declare_dependency(
|
|||
link_with: lib_toytoolkit,
|
||||
dependencies: deps_toytoolkit,
|
||||
)
|
||||
dep_gbm = dependency('gbm', required: false, version: '>= 21.3')
|
||||
dep_gbm = dependency('gbm', required: false, version: '>= 21.1.1')
|
||||
if dep_gbm.found() and dep_gbm.version().version_compare('>= 21.3')
|
||||
config_h.set('HAVE_GBM_BO_CREATE_WITH_MODIFIERS2', '1')
|
||||
endif
|
||||
|
||||
simple_clients_enabled = get_option('simple-clients')
|
||||
simple_build_all = simple_clients_enabled.contains('all')
|
||||
|
|
@ -160,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': [
|
||||
|
|
@ -186,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')
|
||||
|
|
@ -366,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': [
|
||||
|
|
@ -497,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('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',
|
||||
|
|
@ -505,7 +399,6 @@ if get_option('shell-desktop') or get_option('shell-kiosk') or get_option('shell
|
|||
weston_output_capture_protocol_c,
|
||||
include_directories: common_inc,
|
||||
dependencies: [
|
||||
dep_client_buffer,
|
||||
dep_toytoolkit,
|
||||
dep_libweston_private, # for pixel-formats.h
|
||||
dep_pixman,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,177 +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, ®istry_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.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;
|
||||
|
|
@ -707,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);
|
||||
}
|
||||
|
|
@ -716,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");
|
||||
}
|
||||
|
|
@ -730,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer,
|
|||
buffer->release_fence_fd = -1;
|
||||
|
||||
if (display->modifiers_count > 0) {
|
||||
#ifdef HAVE_GBM_BO_CREATE_WITH_MODIFIERS2
|
||||
buffer->bo = gbm_bo_create_with_modifiers2(display->gbm.device,
|
||||
buffer->width,
|
||||
buffer->height,
|
||||
|
|
@ -347,6 +348,14 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer,
|
|||
display->modifiers,
|
||||
display->modifiers_count,
|
||||
GBM_BO_USE_RENDERING);
|
||||
#else
|
||||
buffer->bo = gbm_bo_create_with_modifiers(display->gbm.device,
|
||||
buffer->width,
|
||||
buffer->height,
|
||||
buffer->format,
|
||||
display->modifiers,
|
||||
display->modifiers_count);
|
||||
#endif
|
||||
if (buffer->bo)
|
||||
buffer->modifier = gbm_bo_get_modifier(buffer->bo);
|
||||
}
|
||||
|
|
@ -806,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);
|
||||
|
|
@ -855,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);
|
||||
|
|
@ -1101,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);
|
||||
|
||||
|
|
|
|||
|
|
@ -547,11 +547,18 @@ create_dmabuf_buffer(struct window *window, struct buffer *buf, uint32_t width,
|
|||
buf->format = format;
|
||||
|
||||
if (count_modifiers > 0) {
|
||||
#ifdef HAVE_GBM_BO_CREATE_WITH_MODIFIERS2
|
||||
buf->bo = gbm_bo_create_with_modifiers2(display->gbm_device,
|
||||
buf->width, buf->height,
|
||||
format, modifiers,
|
||||
count_modifiers,
|
||||
bo_flags);
|
||||
#else
|
||||
buf->bo = gbm_bo_create_with_modifiers(display->gbm_device,
|
||||
buf->width, buf->height,
|
||||
format, modifiers,
|
||||
count_modifiers);
|
||||
#endif
|
||||
if (buf->bo)
|
||||
buf->modifier = gbm_bo_get_modifier(buf->bo);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ simple_im_key_handler(struct simple_im *keyboard,
|
|||
|
||||
if (keyboard->compose_state == state_compose) {
|
||||
uint32_t i = 0;
|
||||
const struct compose_seq *cs;
|
||||
struct compose_seq *cs;
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
®istry_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;
|
||||
|
|
|
|||
|
|
@ -1,880 +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 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 don’t 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->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-timing");
|
||||
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
||||
"org.freedesktop.weston.simple-timing");
|
||||
|
||||
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;
|
||||
|
||||
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,
|
||||
®istry_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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
196
clients/window.c
196
clients/window.c
|
|
@ -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
|
||||
|
|
@ -3909,7 +3889,7 @@ input_set_pointer_image_index(struct input *input, int index)
|
|||
struct wl_cursor_image *image;
|
||||
int dx = 0, dy = 0;
|
||||
|
||||
if (!input->pointer || !input->pointer_surface)
|
||||
if (!input->pointer)
|
||||
return;
|
||||
|
||||
cursor = input->display->cursors[input->current_cursor];
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -5946,19 +5898,6 @@ display_destroy_output(struct display *d, uint32_t id)
|
|||
|
||||
wl_list_for_each(output, &d->output_list, link) {
|
||||
if (output->server_output_id == id) {
|
||||
struct window *window;
|
||||
|
||||
/* If a window was on a destroyed output, we need to
|
||||
* make sure the output doesn't linger on the window's
|
||||
* output list.
|
||||
* surface_leave does nothing if the output isn't on
|
||||
* the list, so we can call it for all windows to remove
|
||||
* this output.
|
||||
*/
|
||||
wl_list_for_each(window, &d->window_list, link) {
|
||||
surface_leave(window, NULL, output->output);
|
||||
}
|
||||
|
||||
output_destroy(output);
|
||||
break;
|
||||
}
|
||||
|
|
@ -6732,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;
|
||||
|
|
@ -6741,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;
|
||||
|
|
@ -6750,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
|
||||
|
|
@ -6845,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)
|
||||
|
|
@ -7078,10 +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);
|
||||
|
||||
if (display->single_pixel_buffer_manager)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(display->single_pixel_buffer_manager);
|
||||
xx_color_manager_v4_destroy(display->color_manager);
|
||||
|
||||
if (display->shm)
|
||||
wl_shm_destroy(display->shm);
|
||||
|
|
@ -7147,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
prog_gcovr = find_program('gcovr', required: false, disabler: true)
|
||||
|
||||
# Configure the build:
|
||||
# $ meson configure -Db_sanitize=none -Db_coverage=true -Dwerror=true
|
||||
#
|
||||
# Ensure there are no stale .gcno or .gcda files around:
|
||||
# $ meson setup --wipe ~/git/weston
|
||||
#
|
||||
# Run the test suite:
|
||||
# $ meson compile
|
||||
# $ meson test
|
||||
#
|
||||
# Generate the reports:
|
||||
# $ meson compile gcovr-report
|
||||
|
||||
run_target(
|
||||
'gcovr-report',
|
||||
command: [
|
||||
prog_gcovr,
|
||||
'--root', '@SOURCE_ROOT@',
|
||||
'--cobertura', meson.current_build_dir() / 'cobertura.xml',
|
||||
'--html', meson.current_build_dir() / 'index.html',
|
||||
'--html-nested',
|
||||
'--html-theme', 'github.green',
|
||||
'--html-title', 'Weston test suite coverage',
|
||||
'--print-summary',
|
||||
meson.project_build_root(),
|
||||
],
|
||||
)
|
||||
|
|
@ -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 |
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -180,6 +180,12 @@ update_input_panels(struct wl_listener *listener, void *data)
|
|||
memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
|
||||
}
|
||||
|
||||
static int
|
||||
input_panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "input panel");
|
||||
}
|
||||
|
||||
static void
|
||||
input_panel_committed(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -208,7 +214,7 @@ destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
|
|||
wl_list_remove(&input_panel_surface->link);
|
||||
|
||||
input_panel_surface->surface->committed = NULL;
|
||||
weston_surface_set_label(input_panel_surface->surface, NULL);
|
||||
weston_surface_set_label_func(input_panel_surface->surface, NULL);
|
||||
weston_view_destroy(input_panel_surface->view);
|
||||
|
||||
free(input_panel_surface);
|
||||
|
|
@ -250,7 +256,7 @@ create_input_panel_surface(struct desktop_shell *shell,
|
|||
|
||||
surface->committed = input_panel_committed;
|
||||
surface->committed_private = input_panel_surface;
|
||||
weston_surface_set_label_static(surface, "input panel");
|
||||
weston_surface_set_label_func(surface, input_panel_get_label);
|
||||
|
||||
input_panel_surface->shell = shell;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,14 +42,174 @@
|
|||
#include <libweston/config-parser.h>
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "shared/string-helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
#include <libweston/desktop.h>
|
||||
|
||||
#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 surface’s layer is modified on configuring the surface, in
|
||||
* set_surface_type() (which is only called when the surface’s type change is
|
||||
* _committed_). If a surface’s 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 surface’s 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);
|
||||
|
|
@ -75,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)
|
||||
{
|
||||
|
|
@ -95,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 */
|
||||
|
|
@ -163,8 +337,6 @@ desktop_shell_destroy_surface(struct shell_surface *shsurf)
|
|||
shsurf->output_destroy_listener.notify = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&shsurf->surface_label_update.link);
|
||||
|
||||
free(shsurf);
|
||||
}
|
||||
|
||||
|
|
@ -197,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;
|
||||
|
|
@ -348,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);
|
||||
|
|
@ -361,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");
|
||||
|
|
@ -398,6 +567,13 @@ shell_configuration(struct desktop_shell *shell)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
focus_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "focus highlight effect for output %s",
|
||||
(surface->output ? surface->output->name : "NULL"));
|
||||
}
|
||||
|
||||
/* no-op func for checking focus surface */
|
||||
static void
|
||||
focus_surface_committed(struct weston_surface *es,
|
||||
|
|
@ -421,6 +597,7 @@ create_focus_surface(struct weston_compositor *ec,
|
|||
.pos = output->pos,
|
||||
.width = output->width, .height = output->height,
|
||||
.surface_committed = focus_surface_committed,
|
||||
.get_label = focus_surface_get_label,
|
||||
.surface_private = NULL,
|
||||
.capture_input = false,
|
||||
};
|
||||
|
|
@ -430,11 +607,8 @@ create_focus_surface(struct weston_compositor *ec,
|
|||
return NULL;
|
||||
|
||||
curtain_params.surface_private = fsurf;
|
||||
str_printf(&curtain_params.label, "focus highlight effect for output %s",
|
||||
output->name);
|
||||
|
||||
fsurf->curtain = weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||
|
||||
weston_view_set_output(fsurf->curtain->view, output);
|
||||
|
||||
return fsurf;
|
||||
|
|
@ -887,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);
|
||||
|
||||
|
|
@ -1533,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);
|
||||
|
|
@ -1563,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);
|
||||
}
|
||||
|
||||
|
|
@ -1654,6 +1812,34 @@ shell_surface_get_shell(struct shell_surface *shsurf)
|
|||
return shsurf->shell;
|
||||
}
|
||||
|
||||
static int
|
||||
black_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
struct weston_view *fs_view = surface->committed_private;
|
||||
struct weston_surface *fs_surface = fs_view->surface;
|
||||
int n;
|
||||
int rem;
|
||||
int ret;
|
||||
|
||||
n = snprintf(buf, len, "black background surface for ");
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
rem = (int)len - n;
|
||||
if (rem < 0)
|
||||
rem = 0;
|
||||
|
||||
if (fs_surface->get_label)
|
||||
ret = fs_surface->get_label(fs_surface, buf + n, rem);
|
||||
else
|
||||
ret = snprintf(buf + n, rem, "<unknown>");
|
||||
|
||||
if (ret < 0)
|
||||
return n;
|
||||
|
||||
return n + ret;
|
||||
}
|
||||
|
||||
static void
|
||||
black_surface_committed(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -1681,18 +1867,13 @@ 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,
|
||||
.width = output->width, .height = output->height,
|
||||
.surface_committed = black_surface_committed,
|
||||
.get_label = black_surface_get_label,
|
||||
.surface_private = shsurf->view,
|
||||
.capture_input = true,
|
||||
};
|
||||
|
|
@ -1701,16 +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) {
|
||||
str_printf(&curtain_params.label, "black background surface for %s",
|
||||
surface->label);
|
||||
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);
|
||||
|
||||
|
|
@ -1876,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 *
|
||||
|
|
@ -1891,18 +2070,6 @@ get_shell_surface(struct weston_surface *surface)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_update_label(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface = data;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
}
|
||||
|
||||
/*
|
||||
* libweston-desktop
|
||||
*/
|
||||
|
|
@ -1919,7 +2086,6 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
struct shell_surface *shsurf;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
view = weston_desktop_surface_create_view(desktop_surface);
|
||||
if (!view)
|
||||
|
|
@ -1934,6 +2100,8 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
return;
|
||||
}
|
||||
|
||||
weston_surface_set_label_func(surface, weston_shell_utils_surface_get_label);
|
||||
|
||||
shsurf->shell = (struct desktop_shell *) shell;
|
||||
shsurf->unresponsive = 0;
|
||||
shsurf->saved_position_valid = false;
|
||||
|
|
@ -1961,14 +2129,6 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
wl_list_insert(&shsurf->shell->shsurf_list, &shsurf->link);
|
||||
|
||||
weston_desktop_surface_set_user_data(desktop_surface, shsurf);
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
|
||||
/* client-controllable from xdg-shell */
|
||||
shsurf->surface_label_update.notify = desktop_surface_update_label;
|
||||
weston_desktop_surface_add_metadata_listener(desktop_surface,
|
||||
&shsurf->surface_label_update);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2001,9 +2161,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
|
|||
shsurf->fullscreen.black_view = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&shsurf->surface_label_update.link);
|
||||
wl_list_init(&shsurf->surface_label_update.link);
|
||||
|
||||
weston_surface_set_label_func(surface, NULL);
|
||||
weston_desktop_surface_set_user_data(shsurf->desktop_surface, NULL);
|
||||
shsurf->desktop_surface = NULL;
|
||||
|
||||
|
|
@ -2111,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) {
|
||||
|
|
@ -2223,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;
|
||||
|
|
@ -2616,19 +2765,19 @@ static const struct weston_desktop_api shell_desktop_api = {
|
|||
/* ************************ *
|
||||
* end of libweston-desktop *
|
||||
* ************************ */
|
||||
static int
|
||||
background_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "background for output %s",
|
||||
(surface->output ? surface->output->name : "NULL"));
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
|
|
@ -2644,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
|
||||
|
|
@ -2664,11 +2812,11 @@ 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;
|
||||
struct weston_head *head = weston_head_from_resource(output_resource);
|
||||
char *label;
|
||||
|
||||
if (surface->committed) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
|
|
@ -2681,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,
|
||||
|
|
@ -2691,9 +2839,7 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
|
||||
surface->committed = background_committed;
|
||||
surface->committed_private = sh_output;
|
||||
|
||||
str_printf(&label, "background for output %s", surface->output->name);
|
||||
weston_surface_set_label(surface, label);
|
||||
weston_surface_set_label_func(surface, background_get_label);
|
||||
|
||||
weston_desktop_shell_send_configure(resource, 0,
|
||||
surface_resource,
|
||||
|
|
@ -2708,22 +2854,21 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
&sh_output->background_surface_listener);
|
||||
}
|
||||
|
||||
static int
|
||||
panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "panel for output %s",
|
||||
(surface->output ? surface->output->name : "NULL"));
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
|
|
@ -2750,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
|
||||
|
|
@ -2778,11 +2922,11 @@ 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;
|
||||
struct weston_head *head = weston_head_from_resource(output_resource);
|
||||
char *label;
|
||||
|
||||
if (surface->committed) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
|
|
@ -2795,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,
|
||||
|
|
@ -2806,9 +2950,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
|
||||
surface->committed = panel_committed;
|
||||
surface->committed_private = sh_output;
|
||||
|
||||
str_printf(&label, "panel for output %s", surface->output->name);
|
||||
weston_surface_set_label(surface, label);
|
||||
weston_surface_set_label_func(surface, panel_get_label);
|
||||
|
||||
weston_desktop_shell_send_configure(resource, 0,
|
||||
surface_resource,
|
||||
|
|
@ -2821,6 +2963,12 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
wl_signal_add(&surface->destroy_signal, &sh_output->panel_surface_listener);
|
||||
}
|
||||
|
||||
static int
|
||||
lock_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "lock window");
|
||||
}
|
||||
|
||||
static void
|
||||
lock_surface_committed(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -2877,7 +3025,7 @@ desktop_shell_set_lock_surface(struct wl_client *client,
|
|||
|
||||
surface->committed = lock_surface_committed;
|
||||
surface->committed_private = shell;
|
||||
weston_surface_set_label_static(surface, "lock window");
|
||||
weston_surface_set_label_func(surface, lock_surface_get_label);
|
||||
|
||||
shell->lock_surface = surface;
|
||||
shell->lock_surface_listener.notify = handle_lock_surface_destroy;
|
||||
|
|
@ -3283,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
|
||||
|
|
@ -3406,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;
|
||||
|
|
@ -3674,6 +3823,13 @@ shell_fade_done(struct weston_view_animation *animation, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fade_surface_get_label(struct weston_surface *surface,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "desktop shell fade surface");
|
||||
}
|
||||
|
||||
static struct weston_curtain *
|
||||
shell_fade_create_view(struct desktop_shell *shell)
|
||||
{
|
||||
|
|
@ -3682,9 +3838,9 @@ shell_fade_create_view(struct desktop_shell *shell)
|
|||
struct weston_curtain_params curtain_params = {
|
||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||
.surface_committed = black_surface_committed,
|
||||
.get_label = fade_surface_get_label,
|
||||
.surface_private = shell,
|
||||
.capture_input = true,
|
||||
.label = xstrdup("desktop shell fade surface"),
|
||||
};
|
||||
struct weston_curtain *curtain;
|
||||
bool first = true;
|
||||
|
|
@ -3711,7 +3867,6 @@ shell_fade_create_view(struct desktop_shell *shell)
|
|||
curtain_params.pos.c.y = y1;
|
||||
curtain_params.width = x2 - x1;
|
||||
curtain_params.height = y2 - y1;
|
||||
|
||||
curtain = weston_shell_utils_curtain_create(compositor, &curtain_params);
|
||||
assert(curtain);
|
||||
|
||||
|
|
@ -3820,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);
|
||||
|
|
@ -3850,12 +4008,6 @@ wake_handler(struct wl_listener *listener, void *data)
|
|||
unlock(shell);
|
||||
}
|
||||
|
||||
static void
|
||||
sleep_handler(struct wl_listener *listener, void *data)
|
||||
{
|
||||
weston_log("entering sleep mode: DPMS off\n");
|
||||
}
|
||||
|
||||
static void
|
||||
transform_handler(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -3895,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;
|
||||
|
|
@ -3933,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;
|
||||
|
|
@ -4317,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;
|
||||
|
||||
|
|
@ -4398,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);
|
||||
|
|
@ -4469,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);
|
||||
|
||||
|
|
@ -4487,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;
|
||||
|
|
@ -4496,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);
|
||||
}
|
||||
|
|
@ -4523,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);
|
||||
|
|
@ -4627,7 +4756,6 @@ shell_destroy(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&shell->destroy_listener.link);
|
||||
wl_list_remove(&shell->idle_listener.link);
|
||||
wl_list_remove(&shell->wake_listener.link);
|
||||
wl_list_remove(&shell->sleep_listener.link);
|
||||
wl_list_remove(&shell->transform_listener.link);
|
||||
|
||||
text_backend_destroy(shell->text_backend);
|
||||
|
|
@ -4809,8 +4937,6 @@ wet_shell_init(struct weston_compositor *ec,
|
|||
wl_signal_add(&ec->idle_signal, &shell->idle_listener);
|
||||
shell->wake_listener.notify = wake_handler;
|
||||
wl_signal_add(&ec->wake_signal, &shell->wake_listener);
|
||||
shell->sleep_listener.notify = sleep_handler;
|
||||
wl_signal_add(&ec->sleep_signal, &shell->sleep_listener);
|
||||
shell->transform_listener.notify = transform_handler;
|
||||
wl_signal_add(&ec->transform_signal, &shell->transform_listener);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,170 +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 surface’s layer is modified on configuring the surface, in
|
||||
* set_surface_type() (which is only called when the surface’s type change is
|
||||
* _committed_). If a surface’s 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 surface’s 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 wl_listener surface_label_update;
|
||||
|
||||
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,
|
||||
|
||||
|
|
@ -251,7 +84,6 @@ struct desktop_shell {
|
|||
|
||||
struct wl_listener idle_listener;
|
||||
struct wl_listener wake_listener;
|
||||
struct wl_listener sleep_listener;
|
||||
struct wl_listener transform_listener;
|
||||
struct wl_listener resized_listener;
|
||||
struct wl_listener destroy_listener;
|
||||
|
|
@ -308,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;
|
||||
|
|
@ -345,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,
|
||||
|
|
@ -368,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 */
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
buffers {
|
||||
size_kb: 16384
|
||||
fill_policy: RING_BUFFER
|
||||
}
|
||||
|
||||
data_sources {
|
||||
config {
|
||||
name: "track_event"
|
||||
track_event_config {
|
||||
enabled_categories: "mesa.default"
|
||||
enabled_categories: "mesa.slow"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
duration_ms: 5000
|
||||
write_into_file: true
|
||||
file_write_period_ms: 500
|
||||
flush_period_ms: 500
|
||||
|
|
@ -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 ----------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -14,16 +14,14 @@ Welcome to Weston documentation!
|
|||
Weston
|
||||
------
|
||||
|
||||
Weston is a Wayland compositor designed for correctness, reliability,
|
||||
predictability, and performance.
|
||||
Weston is the reference implementation of a Wayland compositor, as well as a
|
||||
useful environment in and of itself.
|
||||
|
||||
Out of the box, Weston provides a very basic desktop, or a full-featured
|
||||
environment for non-desktop uses such as automotive, embedded, in-flight,
|
||||
industrial, kiosks, set-top boxes and TVs.
|
||||
|
||||
It also provides a library called :ref:`libweston-label` which allows
|
||||
users to build their own custom full-featured environments on top of
|
||||
Weston's core.
|
||||
industrial, kiosks, set-top boxes and TVs. It also provides a library allowing
|
||||
other projects to build their own full-featured environments on top of Weston's
|
||||
core.
|
||||
|
||||
The core focus of Weston is correctness and reliability. Weston aims to be lean
|
||||
and fast, but more importantly, to be predictable. Whilst Weston does have
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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@
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--------------------------------
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
.. _libweston-label:
|
||||
|
||||
Libweston
|
||||
=========
|
||||
|
||||
|
|
@ -12,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,17 +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.
|
||||
|
||||
For capturing a trace you can use the supplied
|
||||
`out of process trace <https://gitlab.freedesktop.org/wayland/weston/-/tree/main/doc/perfetto/perfetto_out_of_process_trace.cfg>`_.
|
||||
config file.
|
||||
|
||||
Inserting timeline points
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -198,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
|
||||
------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
files = [
|
||||
'compositor.rst',
|
||||
'head.rst',
|
||||
'debug-flight-recorder.rst',
|
||||
'log.rst',
|
||||
'output.rst',
|
||||
'output-management.rst',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
----------------------
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
1255
frontend/main.c
1255
frontend/main.c
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,6 @@ deps_weston = [
|
|||
dep_libevdev,
|
||||
dep_libdl,
|
||||
dep_threads,
|
||||
dep_libdisplay_info,
|
||||
]
|
||||
|
||||
if get_option('xwayland')
|
||||
|
|
@ -68,6 +67,32 @@ install_data(
|
|||
install_dir: dir_data / 'wayland-sessions'
|
||||
)
|
||||
|
||||
if get_option('screenshare')
|
||||
srcs_screenshare = [
|
||||
'screen-share.c',
|
||||
fullscreen_shell_unstable_v1_client_protocol_h,
|
||||
fullscreen_shell_unstable_v1_protocol_c,
|
||||
]
|
||||
deps_screenshare = [
|
||||
dep_libexec_weston,
|
||||
dep_libshared,
|
||||
dep_libweston_public,
|
||||
dep_libweston_private_h, # XXX: https://gitlab.freedesktop.org/wayland/weston/issues/292
|
||||
dep_wayland_client,
|
||||
]
|
||||
plugin_screenshare = shared_library(
|
||||
'screen-share',
|
||||
srcs_screenshare,
|
||||
include_directories: common_inc,
|
||||
dependencies: deps_screenshare,
|
||||
name_prefix: '',
|
||||
install: true,
|
||||
install_dir: dir_module_weston,
|
||||
install_rpath: '$ORIGIN'
|
||||
)
|
||||
env_modmap += 'screen-share.so=@0@;'.format(plugin_screenshare.full_path())
|
||||
endif
|
||||
|
||||
if get_option('systemd')
|
||||
dep_libsystemd = dependency('libsystemd', required: false)
|
||||
if not dep_libsystemd.found()
|
||||
|
|
|
|||
1247
frontend/screen-share.c
Normal file
1247
frontend/screen-share.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -36,6 +36,11 @@ bool
|
|||
get_renderer_from_string(const char *name,
|
||||
enum weston_renderer_type *renderer);
|
||||
|
||||
int
|
||||
wet_output_set_color_characteristics(struct weston_output *output,
|
||||
struct weston_config *wc,
|
||||
struct weston_config_section *section);
|
||||
|
||||
int
|
||||
wet_output_set_eotf_mode(struct weston_output *output,
|
||||
struct weston_config_section *section,
|
||||
|
|
@ -48,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);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ struct screenshooter {
|
|||
struct wl_client *client;
|
||||
struct wl_listener client_destroy_listener;
|
||||
struct wl_listener compositor_destroy_listener;
|
||||
struct weston_recorder *recorder;
|
||||
struct wl_listener authorization;
|
||||
};
|
||||
|
||||
|
|
@ -79,6 +80,30 @@ screenshooter_binding(struct weston_keyboard *keyboard,
|
|||
&shooter->client_destroy_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
|
||||
uint32_t key, void *data)
|
||||
{
|
||||
struct weston_compositor *ec = keyboard->seat->compositor;
|
||||
struct weston_output *output;
|
||||
struct screenshooter *shooter = data;
|
||||
struct weston_recorder *recorder = shooter->recorder;;
|
||||
static const char filename[] = "capture.wcap";
|
||||
|
||||
if (recorder) {
|
||||
weston_recorder_stop(recorder);
|
||||
shooter->recorder = NULL;
|
||||
} else {
|
||||
if (keyboard->focus && keyboard->focus->output)
|
||||
output = keyboard->focus->output;
|
||||
else
|
||||
output = container_of(ec->output_list.next,
|
||||
struct weston_output, link);
|
||||
|
||||
shooter->recorder = weston_recorder_start(output, filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
authorize_screenshooter(struct wl_listener *l,
|
||||
struct weston_output_capture_attempt *att)
|
||||
|
|
@ -116,6 +141,8 @@ screenshooter_create(struct weston_compositor *ec)
|
|||
|
||||
weston_compositor_add_key_binding(ec, KEY_S, MODIFIER_SUPER,
|
||||
screenshooter_binding, shooter);
|
||||
weston_compositor_add_key_binding(ec, KEY_R, MODIFIER_SUPER,
|
||||
recorder_binding, shooter);
|
||||
|
||||
shooter->compositor_destroy_listener.notify = screenshooter_destroy;
|
||||
wl_signal_add(&ec->destroy_signal,
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
|||
struct weston_config *config = wet_get_config(wxw->compositor);
|
||||
struct weston_config_section *section;
|
||||
struct wl_client *client;
|
||||
struct weston_client *wcl;
|
||||
struct wl_event_loop *loop;
|
||||
struct custom_env child_env;
|
||||
int no_cloexec_fds[5];
|
||||
|
|
@ -186,10 +185,6 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
|||
goto err_proc;
|
||||
}
|
||||
|
||||
wcl = weston_compositor_get_client(wxw->compositor, client);
|
||||
weston_client_set_internal_name(wcl, "(Xw)%" PRIu64,
|
||||
weston_client_get_internal_id(wcl));
|
||||
|
||||
wxw->wm_fd = x11_wm_socket.fds[0];
|
||||
|
||||
/* Now we can no longer fail, close the child end of our sockets */
|
||||
|
|
@ -265,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;
|
||||
}
|
||||
|
|
|
|||
974
fullscreen-shell/fullscreen-shell.c
Normal file
974
fullscreen-shell/fullscreen-shell.c
Normal file
|
|
@ -0,0 +1,974 @@
|
|||
/*
|
||||
* Copyright © 2013 Jason Ekstrand
|
||||
*
|
||||
* 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 <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libweston/libweston.h>
|
||||
#include "frontend/weston.h"
|
||||
#include "fullscreen-shell-unstable-v1-server-protocol.h"
|
||||
#include "shared/helpers.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
|
||||
struct fullscreen_shell {
|
||||
struct wl_client *client;
|
||||
struct wl_listener client_destroyed;
|
||||
struct wl_listener destroy_listener;
|
||||
struct weston_compositor *compositor;
|
||||
|
||||
struct weston_layer layer;
|
||||
struct wl_list output_list;
|
||||
struct wl_listener output_created_listener;
|
||||
struct wl_listener output_resized_listener;
|
||||
struct wl_listener output_moved_listener;
|
||||
|
||||
struct wl_listener seat_created_listener;
|
||||
|
||||
/* List of one surface per client, presented for the NULL output
|
||||
*
|
||||
* This is implemented as a list in case someone fixes the shell
|
||||
* implementation to support more than one client.
|
||||
*/
|
||||
struct wl_list default_surface_list; /* struct fs_client_surface::link */
|
||||
};
|
||||
|
||||
struct fs_output {
|
||||
struct fullscreen_shell *shell;
|
||||
struct wl_list link;
|
||||
|
||||
struct weston_output *output;
|
||||
struct wl_listener output_destroyed;
|
||||
|
||||
struct {
|
||||
struct weston_surface *surface;
|
||||
struct wl_listener surface_destroyed;
|
||||
struct wl_resource *mode_feedback;
|
||||
|
||||
int presented_for_mode;
|
||||
enum zwp_fullscreen_shell_v1_present_method method;
|
||||
int32_t framerate;
|
||||
} pending;
|
||||
|
||||
struct weston_surface *surface;
|
||||
struct wl_listener surface_destroyed;
|
||||
struct weston_view *view;
|
||||
struct weston_curtain *curtain;
|
||||
struct weston_transform transform; /* matrix from x, y */
|
||||
|
||||
int presented_for_mode;
|
||||
enum zwp_fullscreen_shell_v1_present_method method;
|
||||
uint32_t framerate;
|
||||
};
|
||||
|
||||
struct pointer_focus_listener {
|
||||
struct fullscreen_shell *shell;
|
||||
struct wl_listener pointer_focus;
|
||||
struct wl_listener seat_caps;
|
||||
struct wl_listener seat_destroyed;
|
||||
};
|
||||
|
||||
struct fs_client_surface {
|
||||
struct weston_surface *surface;
|
||||
enum zwp_fullscreen_shell_v1_present_method method;
|
||||
struct wl_list link; /* struct fullscreen_shell::default_surface_list */
|
||||
struct wl_listener surface_destroyed;
|
||||
};
|
||||
|
||||
static void
|
||||
remove_default_surface(struct fs_client_surface *surf)
|
||||
{
|
||||
wl_list_remove(&surf->surface_destroyed.link);
|
||||
wl_list_remove(&surf->link);
|
||||
free(surf);
|
||||
}
|
||||
|
||||
static void
|
||||
default_surface_destroy_listener(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_client_surface *surf;
|
||||
|
||||
surf = container_of(listener, struct fs_client_surface, surface_destroyed);
|
||||
|
||||
remove_default_surface(surf);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_default_surface(struct fullscreen_shell *shell, struct weston_surface *surface,
|
||||
enum zwp_fullscreen_shell_v1_present_method method)
|
||||
{
|
||||
struct fs_client_surface *surf, *prev = NULL;
|
||||
|
||||
if (!wl_list_empty(&shell->default_surface_list))
|
||||
prev = container_of(shell->default_surface_list.prev,
|
||||
struct fs_client_surface, link);
|
||||
|
||||
if (prev)
|
||||
remove_default_surface(prev);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
surf = zalloc(sizeof *surf);
|
||||
if (!surf)
|
||||
return;
|
||||
|
||||
surf->surface = surface;
|
||||
surf->method = method;
|
||||
|
||||
wl_list_insert(shell->default_surface_list.prev, &surf->link);
|
||||
|
||||
surf->surface_destroyed.notify = default_surface_destroy_listener;
|
||||
wl_signal_add(&surface->destroy_signal, &surf->surface_destroyed);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_focus_changed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_pointer *pointer = data;
|
||||
|
||||
if (pointer->focus && pointer->focus->surface->resource)
|
||||
weston_seat_set_keyboard_focus(pointer->seat, pointer->focus->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
seat_caps_changed(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct weston_seat *seat = data;
|
||||
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
|
||||
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
||||
struct pointer_focus_listener *listener;
|
||||
struct fs_output *fsout;
|
||||
|
||||
listener = container_of(l, struct pointer_focus_listener, seat_caps);
|
||||
|
||||
/* no pointer */
|
||||
if (pointer) {
|
||||
if (!listener->pointer_focus.link.prev) {
|
||||
wl_signal_add(&pointer->focus_signal,
|
||||
&listener->pointer_focus);
|
||||
}
|
||||
} else {
|
||||
if (listener->pointer_focus.link.prev) {
|
||||
wl_list_remove(&listener->pointer_focus.link);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyboard && keyboard->focus != NULL) {
|
||||
wl_list_for_each(fsout, &listener->shell->output_list, link) {
|
||||
if (fsout->surface) {
|
||||
weston_seat_set_keyboard_focus(seat, fsout->surface);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
seat_destroyed(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct pointer_focus_listener *listener;
|
||||
|
||||
listener = container_of(l, struct pointer_focus_listener,
|
||||
seat_destroyed);
|
||||
|
||||
free(listener);
|
||||
}
|
||||
|
||||
static void
|
||||
seat_created(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct weston_seat *seat = data;
|
||||
struct pointer_focus_listener *listener;
|
||||
|
||||
listener = zalloc(sizeof *listener);
|
||||
if (!listener)
|
||||
return;
|
||||
|
||||
listener->shell = container_of(l, struct fullscreen_shell,
|
||||
seat_created_listener);
|
||||
listener->pointer_focus.notify = pointer_focus_changed;
|
||||
listener->seat_caps.notify = seat_caps_changed;
|
||||
listener->seat_destroyed.notify = seat_destroyed;
|
||||
|
||||
wl_signal_add(&seat->destroy_signal, &listener->seat_destroyed);
|
||||
wl_signal_add(&seat->updated_caps_signal, &listener->seat_caps);
|
||||
|
||||
seat_caps_changed(&listener->seat_caps, seat);
|
||||
}
|
||||
|
||||
static void
|
||||
black_surface_committed(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
}
|
||||
|
||||
static struct weston_curtain *
|
||||
create_curtain(struct weston_compositor *ec, struct fs_output *fsout,
|
||||
struct weston_coord_global pos, int w, int h)
|
||||
{
|
||||
struct weston_curtain_params curtain_params = {
|
||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||
.pos = pos, .width = w, .height = h,
|
||||
.surface_committed = black_surface_committed,
|
||||
.get_label = NULL,
|
||||
.surface_private = fsout,
|
||||
.capture_input = true,
|
||||
};
|
||||
struct weston_curtain *curtain;
|
||||
|
||||
curtain = weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||
if (!curtain) {
|
||||
weston_log("no memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return curtain;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_set_surface(struct fs_output *fsout, struct weston_surface *surface,
|
||||
enum zwp_fullscreen_shell_v1_present_method method,
|
||||
int32_t framerate, int presented_for_mode);
|
||||
static void
|
||||
fs_output_apply_pending(struct fs_output *fsout);
|
||||
static void
|
||||
fs_output_clear_pending(struct fs_output *fsout);
|
||||
|
||||
static void
|
||||
fs_output_destroy(struct fs_output *fsout)
|
||||
{
|
||||
fs_output_set_surface(fsout, NULL, 0, 0, 0);
|
||||
fs_output_clear_pending(fsout);
|
||||
|
||||
weston_shell_utils_curtain_destroy(fsout->curtain);
|
||||
wl_list_remove(&fsout->link);
|
||||
|
||||
if (fsout->output)
|
||||
wl_list_remove(&fsout->output_destroyed.link);
|
||||
free(fsout);
|
||||
}
|
||||
|
||||
static void
|
||||
output_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *output = container_of(listener,
|
||||
struct fs_output,
|
||||
output_destroyed);
|
||||
fs_output_destroy(output);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fsout = container_of(listener,
|
||||
struct fs_output,
|
||||
surface_destroyed);
|
||||
fsout->surface = NULL;
|
||||
fsout->view = NULL;
|
||||
wl_list_remove(&fsout->transform.link);
|
||||
wl_list_init(&fsout->transform.link);
|
||||
}
|
||||
|
||||
static void
|
||||
pending_surface_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fsout = container_of(listener,
|
||||
struct fs_output,
|
||||
pending.surface_destroyed);
|
||||
fsout->pending.surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
configure_presented_surface_internal(struct weston_surface *surface);
|
||||
|
||||
static struct fs_output *
|
||||
fs_output_create(struct fullscreen_shell *shell, struct weston_output *output)
|
||||
{
|
||||
struct weston_seat *seat;
|
||||
struct fs_output *fsout;
|
||||
struct fs_client_surface *surf;
|
||||
|
||||
fsout = zalloc(sizeof *fsout);
|
||||
if (!fsout)
|
||||
return NULL;
|
||||
|
||||
fsout->shell = shell;
|
||||
wl_list_insert(&shell->output_list, &fsout->link);
|
||||
wl_list_init(&fsout->transform.link);
|
||||
|
||||
fsout->output = output;
|
||||
fsout->output_destroyed.notify = output_destroyed;
|
||||
wl_signal_add(&output->destroy_signal, &fsout->output_destroyed);
|
||||
|
||||
fsout->surface_destroyed.notify = surface_destroyed;
|
||||
fsout->pending.surface_destroyed.notify = pending_surface_destroyed;
|
||||
fsout->curtain = create_curtain(shell->compositor, fsout,
|
||||
output->pos,
|
||||
output->width, output->height);
|
||||
weston_view_move_to_layer(fsout->curtain->view,
|
||||
&shell->layer.view_list);
|
||||
|
||||
if (!wl_list_empty(&shell->default_surface_list)) {
|
||||
surf = container_of(shell->default_surface_list.prev,
|
||||
struct fs_client_surface, link);
|
||||
|
||||
fs_output_set_surface(fsout, surf->surface, surf->method, 0, 0);
|
||||
configure_presented_surface_internal(surf->surface);
|
||||
|
||||
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
||||
struct weston_keyboard *keyboard =
|
||||
weston_seat_get_keyboard(seat);
|
||||
|
||||
if (keyboard && !keyboard->focus)
|
||||
weston_seat_set_keyboard_focus(seat, surf->surface);
|
||||
}
|
||||
}
|
||||
|
||||
return fsout;
|
||||
}
|
||||
|
||||
static struct fs_output *
|
||||
fs_output_for_output(struct weston_output *output)
|
||||
{
|
||||
struct wl_listener *listener;
|
||||
|
||||
if (!output)
|
||||
return NULL;
|
||||
|
||||
listener = wl_signal_get(&output->destroy_signal, output_destroyed);
|
||||
|
||||
return container_of(listener, struct fs_output, output_destroyed);
|
||||
}
|
||||
|
||||
static void
|
||||
restore_output_mode(struct weston_output *output)
|
||||
{
|
||||
if (output && output->original_mode)
|
||||
weston_output_mode_switch_to_native(output);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_scale_view(struct fs_output *fsout, float width, float height)
|
||||
{
|
||||
int32_t surf_x, surf_y, surf_width, surf_height;
|
||||
struct weston_matrix *matrix;
|
||||
struct weston_view *view = fsout->view;
|
||||
struct weston_output *output = fsout->output;
|
||||
struct weston_coord_global pos = fsout->output->pos;
|
||||
|
||||
weston_shell_utils_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y,
|
||||
&surf_width, &surf_height);
|
||||
|
||||
if (output->width == surf_width && output->height == surf_height) {
|
||||
pos.c.x -= surf_x;
|
||||
pos.c.y -= surf_y;
|
||||
weston_view_set_position(view, pos);
|
||||
weston_view_remove_transform(fsout->view, &fsout->transform);
|
||||
} else {
|
||||
matrix = &fsout->transform.matrix;
|
||||
weston_matrix_init(matrix);
|
||||
|
||||
weston_matrix_scale(matrix, width / surf_width,
|
||||
height / surf_height, 1);
|
||||
weston_view_add_transform(fsout->view,
|
||||
&fsout->view->geometry.transformation_list,
|
||||
&fsout->transform);
|
||||
|
||||
pos.c.x += (output->width - width) / 2 - surf_x;
|
||||
pos.c.y += (output->height - height) / 2 - surf_y;
|
||||
weston_view_set_position(view, pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_configure(struct fs_output *fsout, struct weston_surface *surface);
|
||||
|
||||
static void
|
||||
fs_output_configure_simple(struct fs_output *fsout,
|
||||
struct weston_surface *configured_surface)
|
||||
{
|
||||
struct weston_output *output = fsout->output;
|
||||
float output_aspect, surface_aspect;
|
||||
int32_t surf_x, surf_y, surf_width, surf_height;
|
||||
struct weston_coord_global pos;
|
||||
|
||||
if (fsout->pending.surface == configured_surface)
|
||||
fs_output_apply_pending(fsout);
|
||||
|
||||
assert(fsout->view);
|
||||
|
||||
restore_output_mode(fsout->output);
|
||||
|
||||
wl_list_remove(&fsout->transform.link);
|
||||
wl_list_init(&fsout->transform.link);
|
||||
|
||||
weston_shell_utils_subsurfaces_boundingbox(fsout->view->surface,
|
||||
&surf_x, &surf_y,
|
||||
&surf_width, &surf_height);
|
||||
|
||||
output_aspect = (float) output->width / (float) output->height;
|
||||
surface_aspect = (float) surf_width / (float) surf_height;
|
||||
|
||||
switch (fsout->method) {
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER:
|
||||
weston_shell_utils_center_on_output(fsout->view, fsout->output);
|
||||
break;
|
||||
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM:
|
||||
if (output_aspect < surface_aspect)
|
||||
fs_output_scale_view(fsout,
|
||||
output->width,
|
||||
output->width / surface_aspect);
|
||||
else
|
||||
fs_output_scale_view(fsout,
|
||||
output->height * surface_aspect,
|
||||
output->height);
|
||||
break;
|
||||
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM_CROP:
|
||||
if (output_aspect < surface_aspect)
|
||||
fs_output_scale_view(fsout,
|
||||
output->height * surface_aspect,
|
||||
output->height);
|
||||
else
|
||||
fs_output_scale_view(fsout,
|
||||
output->width,
|
||||
output->width / surface_aspect);
|
||||
break;
|
||||
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_STRETCH:
|
||||
fs_output_scale_view(fsout, output->width, output->height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pos = fsout->output->pos;
|
||||
pos.c.x -= surf_x;
|
||||
pos.c.y -= surf_y;
|
||||
weston_view_set_position(fsout->curtain->view, pos);
|
||||
weston_surface_set_size(fsout->curtain->view->surface,
|
||||
fsout->output->width,
|
||||
fsout->output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_configure_for_mode(struct fs_output *fsout,
|
||||
struct weston_surface *configured_surface)
|
||||
{
|
||||
int32_t surf_x, surf_y, surf_width, surf_height;
|
||||
struct weston_mode mode;
|
||||
struct weston_coord_global pos;
|
||||
int ret;
|
||||
|
||||
if (fsout->pending.surface != configured_surface) {
|
||||
/* Nothing to really reconfigure. We'll just recenter the
|
||||
* view in case they played with subsurfaces */
|
||||
weston_shell_utils_center_on_output(fsout->view, fsout->output);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have a pending surface */
|
||||
weston_shell_utils_subsurfaces_boundingbox(fsout->pending.surface,
|
||||
&surf_x, &surf_y,
|
||||
&surf_width, &surf_height);
|
||||
|
||||
/* The actual output mode is in physical units. We need to
|
||||
* transform the surface size to physical unit size by flipping and
|
||||
* possibly scaling it.
|
||||
*/
|
||||
switch (fsout->output->transform) {
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
mode.width = surf_height * fsout->output->native_scale;
|
||||
mode.height = surf_width * fsout->output->native_scale;
|
||||
break;
|
||||
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
default:
|
||||
mode.width = surf_width * fsout->output->native_scale;
|
||||
mode.height = surf_height * fsout->output->native_scale;
|
||||
}
|
||||
mode.flags = 0;
|
||||
mode.refresh = fsout->pending.framerate;
|
||||
|
||||
ret = weston_output_mode_switch_to_temporary(fsout->output, &mode,
|
||||
fsout->output->native_scale);
|
||||
|
||||
if (ret != 0) {
|
||||
/* The mode switch failed. Clear the pending and
|
||||
* reconfigure as per normal */
|
||||
if (fsout->pending.mode_feedback) {
|
||||
zwp_fullscreen_shell_mode_feedback_v1_send_mode_failed(
|
||||
fsout->pending.mode_feedback);
|
||||
wl_resource_destroy(fsout->pending.mode_feedback);
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
fs_output_clear_pending(fsout);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsout->pending.mode_feedback) {
|
||||
zwp_fullscreen_shell_mode_feedback_v1_send_mode_successful(
|
||||
fsout->pending.mode_feedback);
|
||||
wl_resource_destroy(fsout->pending.mode_feedback);
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
fs_output_apply_pending(fsout);
|
||||
|
||||
pos = fsout->output->pos;
|
||||
pos.c.x -= surf_x;
|
||||
pos.c.y -= surf_y;
|
||||
weston_view_set_position(fsout->view, pos);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_configure(struct fs_output *fsout,
|
||||
struct weston_surface *surface)
|
||||
{
|
||||
if (fsout->pending.surface == surface) {
|
||||
if (fsout->pending.presented_for_mode)
|
||||
fs_output_configure_for_mode(fsout, surface);
|
||||
else
|
||||
fs_output_configure_simple(fsout, surface);
|
||||
} else {
|
||||
if (fsout->presented_for_mode)
|
||||
fs_output_configure_for_mode(fsout, surface);
|
||||
else
|
||||
fs_output_configure_simple(fsout, surface);
|
||||
}
|
||||
|
||||
weston_output_schedule_repaint(fsout->output);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_presented_surface(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
configure_presented_surface_internal(surface);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_presented_surface_internal(struct weston_surface *surface)
|
||||
{
|
||||
struct fullscreen_shell *shell = surface->committed_private;
|
||||
struct fs_output *fsout;
|
||||
|
||||
if (surface->committed != configure_presented_surface)
|
||||
return;
|
||||
|
||||
if (!weston_surface_has_content(surface))
|
||||
return;
|
||||
|
||||
if (!weston_surface_is_mapped(surface))
|
||||
weston_surface_map(surface);
|
||||
|
||||
wl_list_for_each(fsout, &shell->output_list, link)
|
||||
if (fsout->surface == surface ||
|
||||
fsout->pending.surface == surface)
|
||||
fs_output_configure(fsout, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_apply_pending(struct fs_output *fsout)
|
||||
{
|
||||
assert(fsout->pending.surface);
|
||||
|
||||
if (!weston_surface_is_mapped(fsout->pending.surface) &&
|
||||
!weston_surface_has_content(fsout->pending.surface))
|
||||
return;
|
||||
|
||||
if (fsout->surface && fsout->surface != fsout->pending.surface) {
|
||||
wl_list_remove(&fsout->surface_destroyed.link);
|
||||
|
||||
weston_view_destroy(fsout->view);
|
||||
fsout->view = NULL;
|
||||
|
||||
if (wl_list_empty(&fsout->surface->views)) {
|
||||
fsout->surface->committed = NULL;
|
||||
fsout->surface->committed_private = NULL;
|
||||
}
|
||||
|
||||
fsout->surface = NULL;
|
||||
}
|
||||
|
||||
fsout->method = fsout->pending.method;
|
||||
fsout->framerate = fsout->pending.framerate;
|
||||
fsout->presented_for_mode = fsout->pending.presented_for_mode;
|
||||
|
||||
if (fsout->surface != fsout->pending.surface) {
|
||||
fsout->surface = fsout->pending.surface;
|
||||
if (!weston_surface_is_mapped(fsout->surface))
|
||||
weston_surface_map(fsout->surface);
|
||||
|
||||
fsout->view = weston_view_create(fsout->surface);
|
||||
if (!fsout->view) {
|
||||
weston_log("no memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_add(&fsout->surface->destroy_signal,
|
||||
&fsout->surface_destroyed);
|
||||
weston_view_move_to_layer(fsout->view,
|
||||
&fsout->shell->layer.view_list);
|
||||
}
|
||||
|
||||
fs_output_clear_pending(fsout);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_clear_pending(struct fs_output *fsout)
|
||||
{
|
||||
if (!fsout->pending.surface)
|
||||
return;
|
||||
|
||||
if (fsout->pending.mode_feedback) {
|
||||
zwp_fullscreen_shell_mode_feedback_v1_send_present_cancelled(
|
||||
fsout->pending.mode_feedback);
|
||||
wl_resource_destroy(fsout->pending.mode_feedback);
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&fsout->pending.surface_destroyed.link);
|
||||
fsout->pending.surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_set_surface(struct fs_output *fsout, struct weston_surface *surface,
|
||||
enum zwp_fullscreen_shell_v1_present_method method,
|
||||
int32_t framerate, int presented_for_mode)
|
||||
{
|
||||
fs_output_clear_pending(fsout);
|
||||
|
||||
if (surface) {
|
||||
if (!surface->committed) {
|
||||
surface->committed = configure_presented_surface;
|
||||
surface->committed_private = fsout->shell;
|
||||
}
|
||||
|
||||
fsout->pending.surface = surface;
|
||||
wl_signal_add(&fsout->pending.surface->destroy_signal,
|
||||
&fsout->pending.surface_destroyed);
|
||||
|
||||
fsout->pending.method = method;
|
||||
fsout->pending.framerate = framerate;
|
||||
fsout->pending.presented_for_mode = presented_for_mode;
|
||||
} else if (fsout->surface) {
|
||||
/* we clear immediately */
|
||||
wl_list_remove(&fsout->surface_destroyed.link);
|
||||
|
||||
weston_view_destroy(fsout->view);
|
||||
fsout->view = NULL;
|
||||
|
||||
if (wl_list_empty(&fsout->surface->views)) {
|
||||
fsout->surface->committed = NULL;
|
||||
fsout->surface->committed_private = NULL;
|
||||
}
|
||||
|
||||
fsout->surface = NULL;
|
||||
|
||||
weston_output_schedule_repaint(fsout->output);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_release(struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_present_surface(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *surface_res,
|
||||
uint32_t method,
|
||||
struct wl_resource *output_res)
|
||||
{
|
||||
struct fullscreen_shell *shell =
|
||||
wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface;
|
||||
struct weston_seat *seat;
|
||||
struct fs_output *fsout;
|
||||
|
||||
surface = surface_res ? wl_resource_get_user_data(surface_res) : NULL;
|
||||
|
||||
switch(method) {
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM_CROP:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_STRETCH:
|
||||
break;
|
||||
default:
|
||||
wl_resource_post_error(resource,
|
||||
ZWP_FULLSCREEN_SHELL_V1_ERROR_INVALID_METHOD,
|
||||
"Invalid presentation method");
|
||||
}
|
||||
|
||||
if (output_res) {
|
||||
struct weston_head *head =
|
||||
weston_head_from_resource(output_res);
|
||||
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
fsout = fs_output_for_output(head->output);
|
||||
fs_output_set_surface(fsout, surface, method, 0, 0);
|
||||
} else {
|
||||
replace_default_surface(shell, surface, method);
|
||||
|
||||
wl_list_for_each(fsout, &shell->output_list, link)
|
||||
fs_output_set_surface(fsout, surface, method, 0, 0);
|
||||
}
|
||||
|
||||
if (surface) {
|
||||
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
||||
struct weston_keyboard *keyboard =
|
||||
weston_seat_get_keyboard(seat);
|
||||
|
||||
if (keyboard && !keyboard->focus)
|
||||
weston_seat_set_keyboard_focus(seat, surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mode_feedback_destroyed(struct wl_resource *resource)
|
||||
{
|
||||
struct fs_output *fsout = wl_resource_get_user_data(resource);
|
||||
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_present_surface_for_mode(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *surface_res,
|
||||
struct wl_resource *output_res,
|
||||
int32_t framerate,
|
||||
uint32_t feedback_id)
|
||||
{
|
||||
struct fullscreen_shell *shell =
|
||||
wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface;
|
||||
struct weston_seat *seat;
|
||||
struct fs_output *fsout;
|
||||
struct weston_head *head = weston_head_from_resource(output_res);
|
||||
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
fsout = fs_output_for_output(head->output);
|
||||
|
||||
if (surface_res == NULL) {
|
||||
fs_output_set_surface(fsout, NULL, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
surface = wl_resource_get_user_data(surface_res);
|
||||
fs_output_set_surface(fsout, surface, 0, framerate, 1);
|
||||
|
||||
fsout->pending.mode_feedback =
|
||||
wl_resource_create(client,
|
||||
&zwp_fullscreen_shell_mode_feedback_v1_interface,
|
||||
1, feedback_id);
|
||||
wl_resource_set_implementation(fsout->pending.mode_feedback, NULL,
|
||||
fsout, mode_feedback_destroyed);
|
||||
|
||||
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
||||
struct weston_keyboard *keyboard =
|
||||
weston_seat_get_keyboard(seat);
|
||||
|
||||
if (keyboard && !keyboard->focus)
|
||||
weston_seat_set_keyboard_focus(seat, surface);
|
||||
}
|
||||
}
|
||||
|
||||
struct zwp_fullscreen_shell_v1_interface fullscreen_shell_implementation = {
|
||||
fullscreen_shell_release,
|
||||
fullscreen_shell_present_surface,
|
||||
fullscreen_shell_present_surface_for_mode,
|
||||
};
|
||||
|
||||
static void
|
||||
output_geometry_changed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fsout;
|
||||
|
||||
fsout = fs_output_for_output(data);
|
||||
if (fsout && fsout->surface)
|
||||
fs_output_configure(fsout, fsout->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
output_created(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fullscreen_shell *shell;
|
||||
|
||||
shell = container_of(listener, struct fullscreen_shell,
|
||||
output_created_listener);
|
||||
|
||||
fs_output_create(shell, data);
|
||||
}
|
||||
|
||||
static void
|
||||
client_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fullscreen_shell *shell = container_of(listener,
|
||||
struct fullscreen_shell,
|
||||
client_destroyed);
|
||||
shell->client = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bind_fullscreen_shell(struct wl_client *client, void *data, uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct fullscreen_shell *shell = data;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (shell->client != NULL && shell->client != client)
|
||||
return;
|
||||
else if (shell->client == NULL) {
|
||||
shell->client = client;
|
||||
wl_client_add_destroy_listener(client, &shell->client_destroyed);
|
||||
}
|
||||
|
||||
resource = wl_resource_create(client,
|
||||
&zwp_fullscreen_shell_v1_interface,
|
||||
1, id);
|
||||
wl_resource_set_implementation(resource,
|
||||
&fullscreen_shell_implementation,
|
||||
shell, NULL);
|
||||
|
||||
if (shell->compositor->capabilities & WESTON_CAP_CURSOR_PLANE)
|
||||
zwp_fullscreen_shell_v1_send_capability(resource,
|
||||
ZWP_FULLSCREEN_SHELL_V1_CAPABILITY_CURSOR_PLANE);
|
||||
|
||||
if (shell->compositor->capabilities & WESTON_CAP_ARBITRARY_MODES)
|
||||
zwp_fullscreen_shell_v1_send_capability(resource,
|
||||
ZWP_FULLSCREEN_SHELL_V1_CAPABILITY_ARBITRARY_MODES);
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fs_output, *fs_output_next;
|
||||
struct fs_client_surface *surf;
|
||||
struct fullscreen_shell *shell =
|
||||
container_of(listener, struct fullscreen_shell, destroy_listener);
|
||||
|
||||
/* remove the curtain(s) */
|
||||
wl_list_for_each_safe(fs_output, fs_output_next, &shell->output_list, link)
|
||||
fs_output_destroy(fs_output);
|
||||
|
||||
wl_list_remove(&shell->output_created_listener.link);
|
||||
wl_list_remove(&shell->output_moved_listener.link);
|
||||
wl_list_remove(&shell->output_resized_listener.link);
|
||||
|
||||
if (!wl_list_empty(&shell->default_surface_list)) {
|
||||
surf = container_of(shell->default_surface_list.prev,
|
||||
struct fs_client_surface, link);
|
||||
remove_default_surface(surf);
|
||||
}
|
||||
|
||||
weston_layer_fini(&shell->layer);
|
||||
free(shell);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
wet_shell_init(struct weston_compositor *compositor,
|
||||
int *argc, char *argv[])
|
||||
{
|
||||
struct fullscreen_shell *shell;
|
||||
struct weston_seat *seat;
|
||||
struct weston_output *output;
|
||||
|
||||
shell = zalloc(sizeof *shell);
|
||||
if (shell == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
shell->compositor = compositor;
|
||||
|
||||
if (!weston_compositor_add_destroy_listener_once(compositor,
|
||||
&shell->destroy_listener,
|
||||
fullscreen_shell_destroy)) {
|
||||
free(shell);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wl_list_init(&shell->default_surface_list);
|
||||
|
||||
shell->client_destroyed.notify = client_destroyed;
|
||||
|
||||
weston_layer_init(&shell->layer, compositor);
|
||||
weston_layer_set_position(&shell->layer,
|
||||
WESTON_LAYER_POSITION_FULLSCREEN);
|
||||
|
||||
wl_list_init(&shell->output_list);
|
||||
shell->output_created_listener.notify = output_created;
|
||||
wl_signal_add(&compositor->output_created_signal,
|
||||
&shell->output_created_listener);
|
||||
wl_list_for_each(output, &compositor->output_list, link)
|
||||
fs_output_create(shell, output);
|
||||
|
||||
shell->output_resized_listener.notify = output_geometry_changed;
|
||||
wl_signal_add(&compositor->output_resized_signal,
|
||||
&shell->output_resized_listener);
|
||||
|
||||
shell->output_moved_listener.notify = output_geometry_changed;
|
||||
wl_signal_add(&compositor->output_moved_signal,
|
||||
&shell->output_moved_listener);
|
||||
|
||||
shell->seat_created_listener.notify = seat_created;
|
||||
wl_signal_add(&compositor->seat_created_signal,
|
||||
&shell->seat_created_listener);
|
||||
wl_list_for_each(seat, &compositor->seat_list, link)
|
||||
seat_created(&shell->seat_created_listener, seat);
|
||||
|
||||
wl_global_create(compositor->wl_display,
|
||||
&zwp_fullscreen_shell_v1_interface, 1, shell,
|
||||
bind_fullscreen_shell);
|
||||
|
||||
screenshooter_create(compositor);
|
||||
return 0;
|
||||
}
|
||||
20
fullscreen-shell/meson.build
Normal file
20
fullscreen-shell/meson.build
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
if get_option('shell-fullscreen')
|
||||
srcs_shell_fullscreen = [
|
||||
'fullscreen-shell.c',
|
||||
fullscreen_shell_unstable_v1_server_protocol_h,
|
||||
fullscreen_shell_unstable_v1_protocol_c,
|
||||
]
|
||||
deps_shell_fullscreen = [
|
||||
dep_libweston_public,
|
||||
dep_libexec_weston,
|
||||
]
|
||||
shared_library(
|
||||
'fullscreen-shell',
|
||||
srcs_shell_fullscreen,
|
||||
include_directories: common_inc,
|
||||
dependencies: deps_shell_fullscreen,
|
||||
name_prefix: '',
|
||||
install: true,
|
||||
install_dir: dir_module_weston
|
||||
)
|
||||
endif
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ struct weston_rdp_backend_config {
|
|||
char *rdp_key;
|
||||
char *server_cert;
|
||||
char *server_key;
|
||||
int vmconnect;
|
||||
int env_socket;
|
||||
bool resizeable;
|
||||
int force_no_compression;
|
||||
|
|
@ -94,7 +93,6 @@ struct weston_rdp_backend_config {
|
|||
rdp_audio_in_teardown audio_in_teardown;
|
||||
rdp_audio_out_setup audio_out_setup;
|
||||
rdp_audio_out_teardown audio_out_teardown;
|
||||
char *nla_ntlm_db;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -1,314 +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;
|
||||
};
|
||||
|
||||
void
|
||||
weston_color_gamut_from_protocol(struct weston_color_gamut *dst,
|
||||
int32_t r_x, int32_t r_y,
|
||||
int32_t g_x, int32_t g_y,
|
||||
int32_t b_x, int32_t b_y,
|
||||
int32_t w_x, int32_t w_y);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -217,8 +217,6 @@ struct weston_size
|
|||
weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface);
|
||||
struct weston_size
|
||||
weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface);
|
||||
char *
|
||||
weston_desktop_surface_make_label(struct weston_desktop_surface *surface);
|
||||
struct weston_desktop_surface *
|
||||
weston_desktop_surface_get_parent(struct weston_desktop_surface *surface);
|
||||
void
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,259 +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);
|
||||
}
|
||||
|
||||
/** Element-wise vector subtraction a - b */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_sub_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return WESTON_VEC3F(a.x - b.x,
|
||||
a.y - b.y,
|
||||
a.z - b.z);
|
||||
}
|
||||
|
||||
/** Element-wise vector sum a + b */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_add_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return WESTON_VEC3F(a.x + b.x,
|
||||
a.y + b.y,
|
||||
a.z + b.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 addition A + B */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_add_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 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
|
||||
|
|
@ -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
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
|
||||
/* parameter for weston_curtain_create() */
|
||||
struct weston_curtain_params {
|
||||
char *label;
|
||||
int (*get_label)(struct weston_surface *es, char *buf, size_t len);
|
||||
void (*surface_committed)(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin);
|
||||
void *surface_private;
|
||||
|
|
@ -61,6 +61,10 @@ weston_shell_utils_subsurfaces_boundingbox(struct weston_surface *surface,
|
|||
int32_t *x, int32_t *y,
|
||||
int32_t *w, int32_t *h);
|
||||
|
||||
int
|
||||
weston_shell_utils_surface_get_label(struct weston_surface *surface,
|
||||
char *buf, size_t len);
|
||||
|
||||
/* helper to create a view w/ a color */
|
||||
struct weston_curtain *
|
||||
weston_shell_utils_curtain_create(struct weston_compositor *compositor,
|
||||
|
|
@ -71,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
|
||||
|
|
|
|||
|
|
@ -88,9 +88,6 @@ void
|
|||
weston_log_scope_write(struct weston_log_scope *scope,
|
||||
const char *data, size_t len);
|
||||
|
||||
FILE *
|
||||
weston_log_scope_stream(struct weston_log_scope *scope);
|
||||
|
||||
int
|
||||
weston_log_scope_vprintf(struct weston_log_scope *scope,
|
||||
const char *fmt, va_list ap);
|
||||
|
|
@ -99,14 +96,6 @@ int
|
|||
weston_log_scope_printf(struct weston_log_scope *scope,
|
||||
const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
void
|
||||
weston_log_scope_puts(struct weston_log_scope *scope, const char *str);
|
||||
|
||||
void
|
||||
weston_log_subscription_write(struct weston_log_subscription *sub,
|
||||
const char *data, size_t len);
|
||||
|
||||
void
|
||||
weston_log_subscription_printf(struct weston_log_subscription *sub,
|
||||
const char *fmt, ...)
|
||||
|
|
@ -157,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -49,10 +49,8 @@
|
|||
#include "ivi-layout-shell.h"
|
||||
#include "libweston/libweston.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/string-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
|
||||
|
|
@ -73,8 +71,6 @@ struct ivi_shell_surface
|
|||
struct wl_list children_link;
|
||||
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_listener surface_label_update;
|
||||
};
|
||||
|
||||
struct ivi_input_panel_surface
|
||||
|
|
@ -211,6 +207,16 @@ ivi_shell_surface_committed(struct weston_surface *surface,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ivi_shell_surface_get_label(struct weston_surface *surface,
|
||||
char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
|
||||
|
||||
return snprintf(buf, len, "ivi-surface %#x", shell_surf->id_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
layout_surface_cleanup(struct ivi_shell_surface *ivisurf)
|
||||
{
|
||||
|
|
@ -232,7 +238,7 @@ layout_surface_cleanup(struct ivi_shell_surface *ivisurf)
|
|||
|
||||
ivisurf->surface->committed = NULL;
|
||||
ivisurf->surface->committed_private = NULL;
|
||||
weston_surface_set_label(ivisurf->surface, NULL);
|
||||
weston_surface_set_label_func(ivisurf->surface, NULL);
|
||||
ivisurf->surface = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +323,6 @@ application_surface_create(struct wl_client *client,
|
|||
struct weston_surface *weston_surface =
|
||||
wl_resource_get_user_data(surface_resource);
|
||||
struct wl_resource *res;
|
||||
char *label;
|
||||
|
||||
if (weston_surface_set_role(weston_surface, "ivi_surface",
|
||||
resource, IVI_APPLICATION_ERROR_ROLE) < 0)
|
||||
|
|
@ -338,7 +343,7 @@ application_surface_create(struct wl_client *client,
|
|||
|
||||
ivisurf = xzalloc(sizeof *ivisurf);
|
||||
|
||||
wl_list_init(&ivisurf->surface_label_update.link);
|
||||
wl_list_init(&ivisurf->link);
|
||||
wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
|
||||
|
||||
ivisurf->shell = shell;
|
||||
|
|
@ -367,9 +372,8 @@ application_surface_create(struct wl_client *client,
|
|||
|
||||
weston_surface->committed = ivi_shell_surface_committed;
|
||||
weston_surface->committed_private = ivisurf;
|
||||
|
||||
str_printf(&label, "ivi-surface %u", ivisurf->id_surface);
|
||||
weston_surface_set_label(weston_surface, label);
|
||||
weston_surface_set_label_func(weston_surface,
|
||||
ivi_shell_surface_get_label);
|
||||
|
||||
res = wl_resource_create(client, &ivi_surface_interface, 1, id);
|
||||
if (res == NULL) {
|
||||
|
|
@ -618,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
|
||||
|
|
@ -628,18 +632,6 @@ desktop_surface_pong(struct weston_desktop_client *client,
|
|||
/* Not supported */
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_update_label(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface = data;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_added(struct weston_desktop_surface *surface,
|
||||
void *user_data)
|
||||
|
|
@ -672,10 +664,6 @@ desktop_surface_added(struct weston_desktop_surface *surface,
|
|||
wl_list_init(&ivisurf->children_link);
|
||||
|
||||
weston_desktop_surface_set_user_data(surface, ivisurf);
|
||||
|
||||
ivisurf->surface_label_update.notify = desktop_surface_update_label;
|
||||
weston_desktop_surface_add_metadata_listener(surface, &ivisurf->surface_label_update);
|
||||
desktop_surface_update_label(&ivisurf->surface_label_update, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -688,7 +676,6 @@ desktop_surface_removed(struct weston_desktop_surface *surface,
|
|||
|
||||
assert(ivisurf != NULL);
|
||||
|
||||
wl_list_remove(&ivisurf->surface_label_update.link);
|
||||
weston_desktop_surface_set_user_data(surface, NULL);
|
||||
|
||||
wl_list_for_each_safe(ivisurf_child, tmp, &ivisurf->children_list,
|
||||
|
|
@ -889,6 +876,12 @@ update_input_panels(struct wl_listener *listener, void *data)
|
|||
ivi_layout_update_text_input_cursor(data);
|
||||
}
|
||||
|
||||
static int
|
||||
input_panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "input panel");
|
||||
}
|
||||
|
||||
static void
|
||||
input_panel_committed(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -950,7 +943,7 @@ create_input_panel_surface(struct ivi_shell *shell,
|
|||
|
||||
surface->committed = input_panel_committed;
|
||||
surface->committed_private = ipsurf;
|
||||
weston_surface_set_label_static(surface, "input panel");
|
||||
weston_surface_set_label_func(surface, input_panel_get_label);
|
||||
|
||||
wl_list_init(&ipsurf->link);
|
||||
wl_list_insert(&shell->input_panel.surfaces, &ipsurf->link);
|
||||
|
|
@ -1023,7 +1016,7 @@ destroy_input_panel_surface_resource(struct wl_resource *resource)
|
|||
|
||||
ipsurf->surface->committed = NULL;
|
||||
ipsurf->surface->committed_private = NULL;
|
||||
weston_surface_set_label(ipsurf->surface, NULL);
|
||||
weston_surface_set_label_func(ipsurf->surface, NULL);
|
||||
ipsurf->surface = NULL;
|
||||
|
||||
wl_list_remove(&ipsurf->surface_destroy_listener.link);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -36,7 +34,6 @@
|
|||
#include "frontend/weston.h"
|
||||
#include "libweston/libweston.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
|
||||
#include <libweston/xwayland-api.h>
|
||||
|
|
@ -140,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);
|
||||
|
|
@ -150,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)
|
||||
|
|
@ -183,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;
|
||||
|
|
@ -208,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -219,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -237,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;
|
||||
|
|
@ -255,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);
|
||||
|
|
@ -271,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);
|
||||
|
|
@ -296,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
|
||||
|
|
@ -382,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);
|
||||
|
|
@ -434,37 +436,23 @@ 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);
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_update_label(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface = data;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_destroy(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
|
|
@ -489,8 +477,6 @@ kiosk_shell_surface_destroy(struct kiosk_shell_surface *shsurf)
|
|||
shsurf->parent = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&shsurf->surface_label_update.link);
|
||||
|
||||
free(shsurf);
|
||||
}
|
||||
|
||||
|
|
@ -528,10 +514,6 @@ kiosk_shell_surface_create(struct kiosk_shell *shell,
|
|||
wl_signal_init(&shsurf->destroy_signal);
|
||||
wl_signal_init(&shsurf->parent_destroy_signal);
|
||||
|
||||
shsurf->surface_label_update.notify = desktop_surface_update_label;
|
||||
weston_desktop_surface_add_metadata_listener(desktop_surface, &shsurf->surface_label_update);
|
||||
desktop_surface_update_label(&shsurf->surface_label_update, desktop_surface);
|
||||
|
||||
/* start life inserting itself as root of its own surface tree list */
|
||||
wl_list_init(&shsurf->surface_tree_list);
|
||||
wl_list_init(&shsurf->surface_tree_link);
|
||||
|
|
@ -548,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);
|
||||
|
|
@ -693,6 +676,13 @@ kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
kiosk_shell_background_surface_get_label(struct weston_surface *surface,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "kiosk shell background surface");
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_output_recreate_background(struct kiosk_shell_output *shoutput)
|
||||
{
|
||||
|
|
@ -726,7 +716,7 @@ kiosk_shell_output_recreate_background(struct kiosk_shell_output *shoutput)
|
|||
|
||||
curtain_params.capture_input = true;
|
||||
|
||||
curtain_params.label = xstrdup("kiosk shell background surface");
|
||||
curtain_params.get_label = kiosk_shell_background_surface_get_label;
|
||||
curtain_params.surface_committed = NULL;
|
||||
curtain_params.surface_private = NULL;
|
||||
|
||||
|
|
@ -834,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;
|
||||
}
|
||||
|
|
@ -853,11 +840,14 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
{
|
||||
struct kiosk_shell *shell = data;
|
||||
struct kiosk_shell_surface *shsurf;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
|
||||
shsurf = kiosk_shell_surface_create(shell, desktop_surface);
|
||||
if (!shsurf)
|
||||
return;
|
||||
|
||||
weston_surface_set_label_func(surface, weston_shell_utils_surface_get_label);
|
||||
kiosk_shell_surface_set_fullscreen(shsurf, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -880,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;
|
||||
|
||||
|
|
@ -898,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);
|
||||
|
|
@ -960,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;
|
||||
|
||||
|
|
@ -1004,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 */
|
||||
|
|
@ -1034,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 =
|
||||
|
|
@ -1053,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);
|
||||
|
|
@ -1145,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
|
||||
|
|
@ -1163,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);
|
||||
}
|
||||
|
|
@ -1247,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,
|
||||
|
|
@ -1335,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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -80,8 +80,6 @@ struct kiosk_shell_surface {
|
|||
} xwayland;
|
||||
|
||||
bool appid_output_assigned;
|
||||
|
||||
struct wl_listener surface_label_update;
|
||||
};
|
||||
|
||||
struct kiosk_shell_seat {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,204 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2025-2026 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
|
||||
|
||||
#include "drm-internal.h"
|
||||
#include "drm-kms-enums.h"
|
||||
|
||||
struct drm_colorop_clut_blob {
|
||||
/* drm_device::drm_colorop_clut_blob_list */
|
||||
struct wl_list link;
|
||||
struct drm_device *device;
|
||||
|
||||
/* Lifetime matches the xform. */
|
||||
struct weston_color_transform *xform;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
uint32_t shaper_len;
|
||||
uint32_t clut_len;
|
||||
|
||||
uint32_t shaper_blob_id;
|
||||
uint32_t clut_blob_id;
|
||||
};
|
||||
|
||||
struct drm_colorop_matrix_blob {
|
||||
/* drm_device::drm_colorop_matrix_blob_list */
|
||||
struct wl_list link;
|
||||
struct drm_device *device;
|
||||
|
||||
/* Lifetime matches the xform. */
|
||||
struct weston_color_transform *xform;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
uint32_t blob_id;
|
||||
};
|
||||
|
||||
struct drm_colorop {
|
||||
struct drm_color_pipeline *pipeline;
|
||||
struct wl_list link; /* drm_pipeline::colorop_list */
|
||||
|
||||
enum wdrm_colorop_type type;
|
||||
|
||||
uint32_t id;
|
||||
|
||||
/* Some colorop's can be bypassed. */
|
||||
bool can_bypass;
|
||||
|
||||
/* Only useful for 1D and 3D LUT colorop's. */
|
||||
uint32_t size;
|
||||
|
||||
/* Holds the properties for the colorop. */
|
||||
struct drm_property_info props[WDRM_COLOROP__COUNT];
|
||||
};
|
||||
|
||||
enum colorop_object_type {
|
||||
COLOROP_OBJECT_TYPE_CURVE = 0,
|
||||
COLOROP_OBJECT_TYPE_MATRIX,
|
||||
COLOROP_OBJECT_TYPE_3x1D_LUT,
|
||||
COLOROP_OBJECT_TYPE_3D_LUT,
|
||||
COLOROP_OBJECT_TYPE_MULTIPLIER,
|
||||
};
|
||||
|
||||
struct drm_colorop_state_object {
|
||||
/* Defines which of the below is valid. The others are zero. */
|
||||
enum colorop_object_type type;
|
||||
|
||||
uint64_t curve_type_prop_val;
|
||||
uint32_t matrix_blob_id;
|
||||
uint32_t lut_3x1d_blob_id;
|
||||
uint32_t lut_3d_blob_id;
|
||||
uint64_t multiplier;
|
||||
};
|
||||
|
||||
struct drm_colorop_state {
|
||||
struct drm_colorop *colorop;
|
||||
/* struct drm_color_pipeline_state::colorop_state_list */
|
||||
struct wl_list link;
|
||||
|
||||
/* Object that should be programmed through the colorop. */
|
||||
struct drm_colorop_state_object object;
|
||||
};
|
||||
|
||||
struct drm_color_pipeline {
|
||||
struct drm_plane *plane;
|
||||
struct wl_list colorop_list; /* drm_colorop::link */
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct drm_color_pipeline_state {
|
||||
struct drm_color_pipeline *pipeline;
|
||||
|
||||
/* struct drm_colorop_state::link */
|
||||
struct wl_list colorop_state_list;
|
||||
};
|
||||
|
||||
#if CAN_OFFLOAD_COLOR_PIPELINE
|
||||
|
||||
void
|
||||
drm_color_pipeline_state_destroy(struct drm_color_pipeline_state *state);
|
||||
|
||||
struct drm_color_pipeline_state *
|
||||
drm_color_pipeline_state_from_xform(struct drm_plane *plane,
|
||||
struct weston_color_transform *xform,
|
||||
const char *indent);
|
||||
|
||||
struct drm_colorop_3x1d_lut_blob *
|
||||
drm_colorop_3x1d_lut_blob_create(struct drm_device *device,
|
||||
struct weston_color_transform *xform,
|
||||
enum weston_color_curve_step curve_step,
|
||||
enum drm_colorop_3x1d_lut_blob_quantization quantization,
|
||||
struct weston_vec3f *cm_lut, uint32_t lut_len);
|
||||
|
||||
struct drm_colorop_3x1d_lut_blob *
|
||||
drm_colorop_3x1d_lut_blob_search(struct drm_device *device,
|
||||
struct weston_color_transform *xform,
|
||||
enum weston_color_curve_step curve_step,
|
||||
enum drm_colorop_3x1d_lut_blob_quantization quantization,
|
||||
uint32_t lut_len);
|
||||
|
||||
const char *
|
||||
drm_colorop_type_to_str(struct drm_colorop *colorop);
|
||||
|
||||
void
|
||||
drm_plane_populate_color_pipelines(struct drm_plane *plane,
|
||||
drmModeObjectPropertiesPtr plane_props);
|
||||
|
||||
void
|
||||
drm_plane_release_color_pipelines(struct drm_plane *plane);
|
||||
|
||||
#else /* CAN_OFFLOAD_COLOR_PIPELINE */
|
||||
|
||||
static inline void
|
||||
drm_color_pipeline_state_destroy(struct drm_color_pipeline_state *state)
|
||||
{
|
||||
}
|
||||
|
||||
static inline struct drm_color_pipeline_state *
|
||||
drm_color_pipeline_state_from_xform(struct drm_plane *plane,
|
||||
struct weston_color_transform *xform,
|
||||
const char *indent)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct drm_colorop_3x1d_lut_blob *
|
||||
drm_colorop_3x1d_lut_blob_create(struct drm_device *device,
|
||||
struct weston_color_transform *xform,
|
||||
enum weston_color_curve_step curve_step,
|
||||
enum drm_colorop_3x1d_lut_blob_quantization quantization,
|
||||
struct weston_vec3f *cm_lut, uint32_t lut_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct drm_colorop_3x1d_lut_blob *
|
||||
drm_colorop_3x1d_lut_blob_search(struct drm_device *device,
|
||||
struct weston_color_transform *xform,
|
||||
enum weston_color_curve_step curve_step,
|
||||
enum drm_colorop_3x1d_lut_blob_quantization quantization,
|
||||
uint32_t lut_len)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_colorop_type_to_str(struct drm_colorop *colorop)
|
||||
{
|
||||
return "undefined";
|
||||
}
|
||||
|
||||
static inline void
|
||||
drm_plane_populate_color_pipelines(struct drm_plane *plane,
|
||||
drmModeObjectPropertiesPtr plane_props)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
drm_plane_release_color_pipelines(struct drm_plane *plane)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CAN_OFFLOAD_COLOR_PIPELINE */
|
||||
|
|
@ -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->kms_device->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->kms_device->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)
|
||||
{
|
||||
|
|
@ -174,13 +137,13 @@ drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
|||
unsigned int i;
|
||||
|
||||
/* No point creating cursors if we don't have a plane for them. */
|
||||
if (!output->cursor_handle)
|
||||
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->kms_device->fd) {
|
||||
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,
|
||||
|
|
@ -216,60 +179,11 @@ 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_handle)
|
||||
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->kms_device->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)
|
||||
{
|
||||
struct weston_mode *mode = output->base.current_mode;
|
||||
struct drm_plane *plane = output->scanout_handle->plane;
|
||||
struct drm_plane *plane = output->scanout_plane;
|
||||
struct weston_drm_format *fmt;
|
||||
const uint64_t *modifiers;
|
||||
unsigned int num_modifiers;
|
||||
|
|
@ -298,7 +212,7 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
|||
* on a different GPU), we have to use linear buffers to make sure that
|
||||
* the allocated GBM surface is correctly displayed on the KMS device.
|
||||
*/
|
||||
if (gbm_device_get_fd(gbm) != output->device->kms_device->fd)
|
||||
if (gbm_device_get_fd(gbm) != output->device->drm.fd)
|
||||
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
|
||||
|
||||
/* We may allocate with no modifiers in the following situations:
|
||||
|
|
@ -315,215 +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++) {
|
||||
struct drm_plane *scanout_plane = output->scanout_handle->plane;
|
||||
|
||||
if (!weston_drm_format_array_find_format(&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 (output->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);
|
||||
output->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 (output->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);
|
||||
output->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 (!output->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);
|
||||
|
|
@ -532,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) {
|
||||
|
|
@ -546,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_handle->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->kms_device->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(drm_gbm_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 (output->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);
|
||||
output->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)
|
||||
{
|
||||
|
|
@ -755,8 +280,12 @@ drm_output_fini_egl(struct drm_output *output)
|
|||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
|
||||
/* Destroying the GBM surface will destroy all our GBM buffers,
|
||||
* regardless of refcount. */
|
||||
weston_assert_ptr_null(b->compositor, output->scanout_handle);
|
||||
* regardless of refcount. Ensure we destroy them here. */
|
||||
if (!b->compositor->shutting_down &&
|
||||
output->scanout_plane->state_cur->fb &&
|
||||
output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
|
||||
drm_plane_reset_state(output->scanout_plane);
|
||||
}
|
||||
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
gbm_surface_destroy(output->gbm_surface);
|
||||
|
|
@ -764,22 +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;
|
||||
|
||||
weston_assert_ptr_null(b->compositor, output->scanout_handle);
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -811,45 +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_plane_state *pstate =
|
||||
drm_output_state_get_plane(state, output->scanout_handle->plane);
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
struct drm_device *device = output->device;
|
||||
struct linux_dmabuf_memory *dmabuf;
|
||||
struct drm_fb *ret;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pstate->in_fence_fd = renderer->vulkan->create_fence_fd(&output->base);
|
||||
if (pstate->in_fence_fd < 1) {
|
||||
weston_log("failed to get fence fd from rendering\n");
|
||||
drm_fb_unref(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output->current_image = (output->current_image + 1) % ARRAY_LENGTH(output->renderbuffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
|
@ -80,12 +78,6 @@
|
|||
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
|
||||
#endif
|
||||
|
||||
#ifndef MAX_DMABUF_PLANES
|
||||
#define MAX_DMABUF_PLANES 4
|
||||
#endif
|
||||
|
||||
#define DRM_MAX_REUSE_FAILURES 10
|
||||
|
||||
/**
|
||||
* A small wrapper to print information into the 'drm-backend' debug scope.
|
||||
*
|
||||
|
|
@ -119,15 +111,8 @@
|
|||
* system. To avoid confusing side effects, we explicitly cast to the widest
|
||||
* possible type and use a matching format specifier.
|
||||
*/
|
||||
#define DO_DRM_DEBUG_COMPLEX(scope, ...) \
|
||||
weston_log_scope_printf(scope, __VA_ARGS__)
|
||||
|
||||
#define DO_DRM_DEBUG(scope, string) \
|
||||
weston_log_scope_puts(scope, string)
|
||||
|
||||
#define drm_debug(b, format, ...) \
|
||||
DO_DRM_DEBUG ## __VA_OPT__(_COMPLEX) \
|
||||
((b)->debug, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#define drm_debug(b, ...) \
|
||||
weston_log_scope_printf((b)->debug, __VA_ARGS__)
|
||||
|
||||
#define MAX_CLONED_CONNECTORS 4
|
||||
|
||||
|
|
@ -164,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.
|
||||
|
|
@ -174,35 +180,15 @@ 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,
|
||||
};
|
||||
|
||||
enum drm_recovery_status {
|
||||
DRM_RECOVERY_UNNECESSARY = 0,
|
||||
DRM_RECOVERY_WAIT_FOR_IDLE = 1,
|
||||
DRM_RECOVERY_SCHEDULED = 2,
|
||||
DRM_RECOVERY_APPLIED = 3,
|
||||
};
|
||||
|
||||
struct drm_kms_device {
|
||||
int id;
|
||||
char *filename;
|
||||
dev_t devnum;
|
||||
struct udev_device *udev_device;
|
||||
|
||||
int fd;
|
||||
struct weston_launcher *fd_owner;
|
||||
};
|
||||
|
||||
struct drm_device {
|
||||
struct drm_backend *backend;
|
||||
|
||||
/* owned */
|
||||
struct drm_kms_device *kms_device;
|
||||
struct wl_event_source *drm_event_source;
|
||||
struct {
|
||||
int id;
|
||||
int fd;
|
||||
char *filename;
|
||||
dev_t devnum;
|
||||
} drm;
|
||||
|
||||
/* Track the GEM handles if the device does not have a gbm device, which
|
||||
* tracks the handles for us.
|
||||
|
|
@ -219,9 +205,7 @@ struct drm_device {
|
|||
|
||||
bool will_repaint;
|
||||
|
||||
enum drm_recovery_status recovery_status;
|
||||
|
||||
int32_t atomic_completes_pending;
|
||||
bool state_invalid;
|
||||
|
||||
bool atomic_modeset;
|
||||
|
||||
|
|
@ -229,13 +213,11 @@ struct drm_device {
|
|||
|
||||
bool aspect_ratio_supported;
|
||||
|
||||
bool color_pipeline_supported;
|
||||
|
||||
int32_t cursor_width;
|
||||
int32_t cursor_height;
|
||||
|
||||
bool cursors_are_broken;
|
||||
bool disable_client_buffer_scanout;
|
||||
bool sprites_are_broken;
|
||||
|
||||
void *repaint_data;
|
||||
|
||||
|
|
@ -250,15 +232,6 @@ struct drm_device {
|
|||
|
||||
/* drm_backend::kms_list */
|
||||
struct wl_list link;
|
||||
|
||||
/* struct drm_colorop_3x1d_lut_blob::link */
|
||||
struct wl_list drm_colorop_3x1d_lut_blob_list;
|
||||
/* struct drm_colorop_clut_blob::link */
|
||||
struct wl_list drm_colorop_clut_blob_list;
|
||||
/* struct drm_colorop_matrix_blob::link */
|
||||
struct wl_list drm_colorop_matrix_blob_list;
|
||||
|
||||
int reused_state_failures;
|
||||
};
|
||||
|
||||
struct drm_backend {
|
||||
|
|
@ -266,6 +239,7 @@ struct drm_backend {
|
|||
struct weston_compositor *compositor;
|
||||
|
||||
struct udev *udev;
|
||||
struct wl_event_source *drm_source;
|
||||
|
||||
struct udev_monitor *udev_monitor;
|
||||
struct wl_event_source *udev_drm_source;
|
||||
|
|
@ -279,22 +253,14 @@ struct drm_backend {
|
|||
|
||||
bool use_pixman_shadow;
|
||||
|
||||
bool offload_blend_to_output;
|
||||
|
||||
struct udev_input input;
|
||||
|
||||
uint32_t pageflip_timeout;
|
||||
|
||||
/* True, if underlay planes exist. */
|
||||
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 {
|
||||
|
|
@ -307,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 */
|
||||
|
|
@ -322,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;
|
||||
|
|
@ -337,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;
|
||||
};
|
||||
|
|
@ -370,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
|
||||
|
|
@ -392,37 +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;
|
||||
};
|
||||
|
||||
enum drm_colorop_3x1d_lut_blob_quantization {
|
||||
DRM_COLOROP_3X1D_LUT_BLOB_QUANTIZATION_U16 = 0,
|
||||
DRM_COLOROP_3X1D_LUT_BLOB_QUANTIZATION_U32,
|
||||
};
|
||||
|
||||
struct drm_colorop_3x1d_lut_blob {
|
||||
/* drm_device::drm_colorop_3x1d_lut_blob_list */
|
||||
struct wl_list link;
|
||||
struct drm_device *device;
|
||||
|
||||
/* Lifetime matches the xform. */
|
||||
struct weston_color_transform *xform;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
/* Which curve of the xform the 3x1D LUT was generated from. */
|
||||
enum weston_color_curve_step curve_step;
|
||||
|
||||
enum drm_colorop_3x1d_lut_blob_quantization quantization;
|
||||
|
||||
uint32_t lut_len;
|
||||
|
||||
uint32_t blob_id;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -434,7 +358,7 @@ struct drm_colorop_3x1d_lut_blob {
|
|||
*/
|
||||
struct drm_plane_state {
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_handle *handle;
|
||||
struct drm_output *output;
|
||||
struct drm_output_state *output_state;
|
||||
|
||||
struct drm_fb *fb;
|
||||
|
|
@ -443,10 +367,7 @@ struct drm_plane_state {
|
|||
struct weston_buffer_release_reference release;
|
||||
} fb_ref;
|
||||
|
||||
struct weston_paint_node *paint_node; /**< maintained for drm_assign_planes only */
|
||||
|
||||
/* only when a color transformation is being offloaded */
|
||||
struct drm_color_pipeline_state *pipeline_state;
|
||||
struct weston_view *ev; /**< maintained for drm_assign_planes only */
|
||||
|
||||
int32_t src_x, src_y;
|
||||
uint32_t src_w, src_h;
|
||||
|
|
@ -458,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 */
|
||||
|
|
@ -499,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;
|
||||
|
|
@ -512,20 +432,6 @@ struct drm_plane {
|
|||
struct wl_list link;
|
||||
|
||||
struct weston_drm_format_array formats;
|
||||
|
||||
uint32_t pipeline_props_id;
|
||||
uint32_t num_color_pipelines;
|
||||
struct drm_color_pipeline *pipelines;
|
||||
};
|
||||
|
||||
struct drm_plane_handle {
|
||||
struct drm_output *output;
|
||||
struct drm_plane *plane;
|
||||
|
||||
/* Whether this plane supports overlay, underlay, or both */
|
||||
enum drm_plane_subtype subtype;
|
||||
|
||||
struct wl_list link; /* drm_output::plane_handle_list */
|
||||
};
|
||||
|
||||
struct drm_connector {
|
||||
|
|
@ -565,7 +471,6 @@ struct drm_writeback_state {
|
|||
|
||||
enum writeback_screenshot_state state;
|
||||
struct weston_capture_task *ct;
|
||||
struct wl_listener ct_destroy_listener;
|
||||
|
||||
struct drm_fb *fb;
|
||||
int32_t out_fence_fd;
|
||||
|
|
@ -617,15 +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;
|
||||
|
||||
/* CRTC prop WDRM_CRTC_BACKGROUND_COLOR */
|
||||
uint64_t background_color;
|
||||
|
||||
/* Union of formats of all compatible writeback connectors */
|
||||
struct weston_drm_format_array writeback_formats;
|
||||
};
|
||||
|
||||
struct drm_output {
|
||||
|
|
@ -644,20 +540,14 @@ struct drm_output {
|
|||
bool dpms_off_pending;
|
||||
bool mode_switch_pending;
|
||||
|
||||
/* List of hardware planes this output can use, excluding the special
|
||||
* cursor and scanout planes. */
|
||||
struct wl_list plane_handle_list;
|
||||
|
||||
/* True, if underlay planes exist. */
|
||||
bool has_underlay;
|
||||
|
||||
uint32_t gbm_cursor_handle[2];
|
||||
struct drm_fb *gbm_cursor_fb[2];
|
||||
struct drm_plane_handle *cursor_handle;
|
||||
struct drm_plane *cursor_plane;
|
||||
struct weston_view *cursor_view;
|
||||
struct wl_listener cursor_view_destroy_listener;
|
||||
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;
|
||||
|
||||
|
|
@ -667,12 +557,11 @@ 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_blob *blend_to_output_xform;
|
||||
|
||||
/* Plane being displayed directly on the CRTC */
|
||||
struct drm_plane_handle *scanout_handle;
|
||||
struct drm_plane *scanout_plane;
|
||||
|
||||
/* The last state submitted to the kernel for this CRTC. */
|
||||
struct drm_output_state *state_cur;
|
||||
|
|
@ -684,26 +573,20 @@ 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;
|
||||
struct wl_listener recorder_frame_listener;
|
||||
|
||||
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);
|
||||
|
||||
submit_frame_cb virtual_submit_frame;
|
||||
|
||||
enum wdrm_content_type content_type;
|
||||
|
||||
bool reused_state;
|
||||
bool force_rebuild_state;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -717,20 +600,11 @@ to_drm_head(struct weston_head *base)
|
|||
return container_of(base, struct drm_head, base);
|
||||
}
|
||||
|
||||
void
|
||||
drm_device_recovery_schedule(struct drm_device *device);
|
||||
|
||||
void
|
||||
drm_device_recovery_required(struct drm_device *device);
|
||||
|
||||
void
|
||||
drm_device_recovery_complete(struct drm_device *device);
|
||||
|
||||
void
|
||||
drm_writeback_reference_planes(struct drm_writeback_state *state,
|
||||
struct wl_list *plane_state_list);
|
||||
bool
|
||||
drm_writeback_try_complete(struct drm_writeback_state *state);
|
||||
drm_writeback_should_wait_completion(struct drm_writeback_state *state);
|
||||
void
|
||||
drm_writeback_fail_screenshot(struct drm_writeback_state *state,
|
||||
const char *err_msg);
|
||||
|
|
@ -774,55 +648,24 @@ to_drm_mode(struct weston_mode *base)
|
|||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_plane_type_name_internal(struct drm_plane *p, struct drm_plane_handle *h)
|
||||
drm_output_get_plane_type_name(struct drm_plane *p)
|
||||
{
|
||||
assert(!p || !h);
|
||||
|
||||
if (h)
|
||||
p = h->plane;
|
||||
|
||||
switch (p->type) {
|
||||
case WDRM_PLANE_TYPE_PRIMARY:
|
||||
return "primary";
|
||||
case WDRM_PLANE_TYPE_CURSOR:
|
||||
return "cursor";
|
||||
case WDRM_PLANE_TYPE_OVERLAY:
|
||||
if (!h)
|
||||
return "overlay(no subtype)";
|
||||
|
||||
switch (h->subtype) {
|
||||
case PLANE_SUBTYPE_OVERLAY_ONLY:
|
||||
return "overlay";
|
||||
case PLANE_SUBTYPE_UNDERLAY_ONLY:
|
||||
return "underlay";
|
||||
case PLANE_SUBTYPE_BOTH:
|
||||
return "over/underlay";
|
||||
}
|
||||
// fall through
|
||||
return p->is_underlay ? "underlay" : "overlay";
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_plane_type_name(struct drm_plane *p)
|
||||
{
|
||||
return drm_output_get_plane_type_name_internal(p, NULL);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_handle_type_name(struct drm_plane_handle *h)
|
||||
{
|
||||
return drm_output_get_plane_type_name_internal(NULL, h);
|
||||
}
|
||||
|
||||
struct drm_crtc *
|
||||
drm_crtc_find(struct drm_device *device, uint32_t crtc_id);
|
||||
|
||||
bool
|
||||
drm_crtc_supports_background_color(struct drm_crtc *crtc);
|
||||
|
||||
struct drm_head *
|
||||
drm_head_find_by_connector(struct drm_backend *backend, struct drm_device *device, uint32_t connector_id);
|
||||
|
||||
|
|
@ -838,7 +681,7 @@ drm_paint_node_transform_supported(struct weston_paint_node *node, struct drm_pl
|
|||
{
|
||||
/* if false, the transform doesn't map to any of the standard
|
||||
* (ie: 90 degree) output transformations. */
|
||||
if (!node->simple_transform)
|
||||
if (!node->valid_transform)
|
||||
return false;
|
||||
|
||||
if (drm_rotation_from_output_transform(plane, node->transform) == 0)
|
||||
|
|
@ -894,7 +737,6 @@ extern struct drm_property_enum_info content_protection_enums[];
|
|||
extern struct drm_property_enum_info hdcp_content_type_enums[];
|
||||
extern const struct drm_property_info connector_props[];
|
||||
extern const struct drm_property_info crtc_props[];
|
||||
extern const struct drm_property_info colorop_props[];
|
||||
|
||||
int
|
||||
init_kms_caps(struct drm_device *device);
|
||||
|
|
@ -906,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
|
||||
|
|
@ -922,15 +768,13 @@ 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);
|
||||
|
||||
void
|
||||
drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev);
|
||||
|
||||
int
|
||||
drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output);
|
||||
|
||||
|
|
@ -940,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;
|
||||
}
|
||||
|
|
@ -986,8 +822,8 @@ enum drm_output_state_duplicate_mode {
|
|||
};
|
||||
|
||||
struct drm_output_state *
|
||||
drm_output_state_alloc(struct drm_output *output);
|
||||
|
||||
drm_output_state_alloc(struct drm_output *output,
|
||||
struct drm_pending_state *pending_state);
|
||||
struct drm_output_state *
|
||||
drm_output_state_duplicate(struct drm_output_state *src,
|
||||
struct drm_pending_state *pending_state,
|
||||
|
|
@ -1013,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);
|
||||
|
|
@ -1026,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);
|
||||
|
||||
|
|
@ -1041,12 +869,6 @@ int
|
|||
parse_gbm_format(const char *s, const struct pixel_format_info *default_format,
|
||||
const struct pixel_format_info **format);
|
||||
|
||||
struct drm_plane_handle *
|
||||
drm_plane_create_handle(struct drm_plane *plane, struct drm_output *output);
|
||||
|
||||
void
|
||||
drm_plane_destroy_handle(struct drm_plane_handle *plane);
|
||||
|
||||
#ifdef BUILD_DRM_VIRTUAL
|
||||
extern int
|
||||
drm_backend_init_virtual_output_api(struct weston_compositor *compositor);
|
||||
|
|
@ -1071,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)
|
||||
|
|
@ -1107,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
|
||||
|
|
|
|||
|
|
@ -56,9 +56,6 @@ enum wdrm_plane_property {
|
|||
WDRM_PLANE_ZPOS,
|
||||
WDRM_PLANE_ROTATION,
|
||||
WDRM_PLANE_ALPHA,
|
||||
WDRM_PLANE_COLOR_ENCODING,
|
||||
WDRM_PLANE_COLOR_PIPELINE,
|
||||
WDRM_PLANE_COLOR_RANGE,
|
||||
WDRM_PLANE__COUNT
|
||||
};
|
||||
|
||||
|
|
@ -85,100 +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_PIPELINE property.
|
||||
*
|
||||
* This property is special: the enum values are not deterministic. Each enum
|
||||
* value corresponds to the id of a colorop created at runtime by the KMS
|
||||
* driver. drm_property_info_populate() expects well-known values for enum
|
||||
* properties, so a dummy value is defined to allow it to populate plane->props
|
||||
* correctly.
|
||||
*/
|
||||
enum wdrm_plane_color_pipeline {
|
||||
WDRM_PLANE_COLOR_PIPELINE_DUMMY = 0,
|
||||
WDRM_PLANE_COLOR_PIPELINE__COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 colorop.
|
||||
*/
|
||||
enum wdrm_colorop_property {
|
||||
WDRM_COLOROP_TYPE = 0,
|
||||
WDRM_COLOROP_NEXT,
|
||||
WDRM_COLOROP_BYPASS,
|
||||
WDRM_COLOROP_SIZE,
|
||||
WDRM_COLOROP_DATA,
|
||||
WDRM_COLOROP_MULTIPLIER,
|
||||
WDRM_COLOROP_LUT1D_INTERPOLATION,
|
||||
WDRM_COLOROP_LUT3D_INTERPOLATION,
|
||||
WDRM_COLOROP_CURVE_1D,
|
||||
WDRM_COLOROP__COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible values for the WDRM_COLOROP_TYPE property.
|
||||
*/
|
||||
enum wdrm_colorop_type {
|
||||
WDRM_COLOROP_TYPE_1D_CURVE = 0,
|
||||
WDRM_COLOROP_TYPE_1D_LUT,
|
||||
WDRM_COLOROP_TYPE_CTM_3X4,
|
||||
WDRM_COLOROP_TYPE_MULTIPLIER,
|
||||
WDRM_COLOROP_TYPE_3D_LUT,
|
||||
WDRM_COLOROP_TYPE__COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible values for the WDRM_COLOROP_CURVE_1D property.
|
||||
*/
|
||||
enum wdrm_colorop_curve_1d {
|
||||
WDRM_COLOROP_CURVE_1D_SRGB_EOTF = 0,
|
||||
WDRM_COLOROP_CURVE_1D_SRGB_INV_EOTF,
|
||||
WDRM_COLOROP_CURVE_1D_PQ_125_EOTF,
|
||||
WDRM_COLOROP_CURVE_1D_PQ_125_INV_EOTF,
|
||||
WDRM_COLOROP_CURVE_1D_BT2020_INV_OETF,
|
||||
WDRM_COLOROP_CURVE_1D_BT2020_OETF,
|
||||
WDRM_COLOROP_CURVE_1D_GAMMA_22,
|
||||
WDRM_COLOROP_CURVE_1D_GAMMA_22_INV,
|
||||
WDRM_COLOROP_CURVE_1D__COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible values for the WDRM_COLOROP_LUT1D_INTERPOLATION property.
|
||||
*/
|
||||
enum wdrm_colorop_lut1d_interpolation {
|
||||
WDRM_COLOROP_LUT1D_INTERPOLATION_LINEAR = 0,
|
||||
WDRM_COLOROP_LUT1D_INTERPOLATION__COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible values for the WDRM_COLOROP_LUT3D_INTERPOLATION property.
|
||||
*/
|
||||
enum wdrm_colorop_lut3d_interpolation {
|
||||
WDRM_COLOROP_LUT3D_INTERPOLATION_TETRAHEDRAL = 0,
|
||||
WDRM_COLOROP_LUT3D_INTERPOLATION__COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* List of properties attached to a DRM connector
|
||||
*/
|
||||
|
|
@ -197,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
|
||||
};
|
||||
|
||||
|
|
@ -271,6 +173,5 @@ enum wdrm_crtc_property {
|
|||
WDRM_CRTC_GAMMA_LUT,
|
||||
WDRM_CRTC_GAMMA_LUT_SIZE,
|
||||
WDRM_CRTC_VRR_ENABLED,
|
||||
WDRM_CRTC_BACKGROUND_COLOR,
|
||||
WDRM_CRTC__COUNT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
@ -105,7 +104,7 @@ get_drm_plane_index_maximum(struct drm_device *device)
|
|||
* @param device DRM device
|
||||
* @param output Output to create internal plane for
|
||||
*/
|
||||
static struct drm_plane_handle *
|
||||
static struct drm_plane *
|
||||
drm_virtual_plane_create(struct drm_device *device, struct drm_output *output)
|
||||
{
|
||||
struct drm_backend *b = device->backend;
|
||||
|
|
@ -146,7 +145,7 @@ drm_virtual_plane_create(struct drm_device *device, struct drm_output *output)
|
|||
plane->plane_idx = get_drm_plane_index_maximum(device) + 1;
|
||||
wl_list_insert(&device->plane_list, &plane->link);
|
||||
|
||||
return drm_plane_create_handle(plane, output);
|
||||
return plane;
|
||||
|
||||
err:
|
||||
drm_plane_state_free(plane->state_cur, true);
|
||||
|
|
@ -158,15 +157,11 @@ err:
|
|||
/**
|
||||
* Destroy one DRM plane
|
||||
*
|
||||
* @param handle Plane handle to deallocate (will be freed along with the plane)
|
||||
* @param plane Plane to deallocate (will be freed)
|
||||
*/
|
||||
static void
|
||||
drm_virtual_plane_destroy(struct drm_plane_handle *handle)
|
||||
drm_virtual_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_plane *plane = handle->plane;
|
||||
|
||||
drm_plane_destroy_handle(handle);
|
||||
|
||||
drm_plane_state_free(plane->state_cur, true);
|
||||
weston_plane_release(&plane->base);
|
||||
wl_list_remove(&plane->link);
|
||||
|
|
@ -210,9 +205,8 @@ 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_handle->plane;
|
||||
struct drm_plane *scanout_plane = output->scanout_plane;
|
||||
struct drm_plane_state *scanout_state;
|
||||
struct drm_pending_state *pending_state;
|
||||
struct drm_device *device;
|
||||
|
|
@ -233,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);
|
||||
|
|
@ -260,7 +258,7 @@ drm_virtual_output_deinit(struct weston_output *base)
|
|||
|
||||
drm_output_fini_egl(output);
|
||||
|
||||
drm_virtual_plane_destroy(output->scanout_handle);
|
||||
drm_virtual_plane_destroy(output->scanout_plane);
|
||||
drm_virtual_crtc_destroy(output->crtc);
|
||||
}
|
||||
|
||||
|
|
@ -303,8 +301,8 @@ drm_virtual_output_enable(struct weston_output *output_base)
|
|||
goto err;
|
||||
}
|
||||
|
||||
output->scanout_handle = drm_virtual_plane_create(device, output);
|
||||
if (!output->scanout_handle) {
|
||||
output->scanout_plane = drm_virtual_plane_create(device, output);
|
||||
if (!output->scanout_plane) {
|
||||
weston_log("Failed to find primary plane for output %s\n",
|
||||
output->base.name);
|
||||
return -1;
|
||||
|
|
@ -320,6 +318,12 @@ 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,
|
||||
&output->base.primary_plane);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
|
@ -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,12 +372,10 @@ 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);
|
||||
output->state_cur = drm_output_state_alloc(output, NULL);
|
||||
|
||||
weston_compositor_add_pending_output(&output->base, c);
|
||||
|
||||
|
|
@ -440,6 +435,11 @@ drm_virtual_output_finish_frame(struct weston_output *output_base,
|
|||
output->state_last = NULL;
|
||||
|
||||
weston_output_finish_frame(&output->base, stamp, presented_flags);
|
||||
|
||||
/* We can't call this from frame_notify, because the output's
|
||||
* repaint needed flag is cleared just after that */
|
||||
if (output->recorder)
|
||||
weston_output_schedule_repaint(&output->base);
|
||||
}
|
||||
|
||||
static const struct weston_drm_virtual_output_api virt_api = {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -41,7 +41,6 @@
|
|||
#include "shared/hash.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/weston-assert.h"
|
||||
#include "drm-internal.h"
|
||||
#include "linux-dmabuf.h"
|
||||
|
||||
|
|
@ -100,7 +99,7 @@ static void gem_handle_put(struct drm_device *device, int handle)
|
|||
ref_count = hash_table_lookup(device->gem_handle_refcnt, handle);
|
||||
if (!ref_count) {
|
||||
weston_log("failed to find GEM handle %d for device %s\n",
|
||||
handle, device->kms_device->filename);
|
||||
handle, device->drm.filename);
|
||||
return;
|
||||
}
|
||||
(*ref_count)--;
|
||||
|
|
@ -108,28 +107,20 @@ static void gem_handle_put(struct drm_device *device, int handle)
|
|||
if (*ref_count == 0) {
|
||||
hash_table_remove(device->gem_handle_refcnt, handle);
|
||||
free(ref_count);
|
||||
drmCloseBufferHandle(device->kms_device->fd, handle);
|
||||
drmCloseBufferHandle(device->drm.fd, 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
|
||||
|
|
@ -156,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
|
||||
|
|
@ -183,35 +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) {
|
||||
weston_assert_false(device->backend->compositor, fb->direct_display);
|
||||
/* 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->kms_device->fd) {
|
||||
weston_log("fb was not allocated for scanout device %s\n",
|
||||
device->kms_device->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_planes = gbm_bo_get_plane_count(fb->bo);
|
||||
} else {
|
||||
weston_assert_true(device->backend->compositor, fb->direct_display);
|
||||
|
||||
num_planes = fb->num_planes;
|
||||
if (fb->fd != device->drm.fd) {
|
||||
weston_log("fb was not allocated for scanout device %s\n",
|
||||
device->drm.filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -313,7 +289,7 @@ drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
|||
create_arg.width = width;
|
||||
create_arg.height = height;
|
||||
|
||||
ret = drmIoctl(device->kms_device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
|
||||
ret = drmIoctl(device->drm.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
|
||||
if (ret)
|
||||
goto err_fb;
|
||||
|
||||
|
|
@ -325,7 +301,7 @@ drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
|||
fb->size = create_arg.size;
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
fb->fd = device->kms_device->fd;
|
||||
fb->fd = device->drm.fd;
|
||||
|
||||
if (drm_fb_addfb(device, fb) != 0) {
|
||||
weston_log("failed to create kms fb: %s\n", strerror(errno));
|
||||
|
|
@ -339,18 +315,18 @@ drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
|||
goto err_add_fb;
|
||||
|
||||
fb->map = mmap(NULL, fb->size, PROT_WRITE,
|
||||
MAP_SHARED, device->kms_device->fd, map_arg.offset);
|
||||
MAP_SHARED, device->drm.fd, map_arg.offset);
|
||||
if (fb->map == MAP_FAILED)
|
||||
goto err_add_fb;
|
||||
|
||||
return fb;
|
||||
|
||||
err_add_fb:
|
||||
drmModeRmFB(device->kms_device->fd, fb->fb_id);
|
||||
drmModeRmFB(device->drm.fd, fb->fb_id);
|
||||
err_bo:
|
||||
memset(&destroy_arg, 0, sizeof(destroy_arg));
|
||||
destroy_arg.handle = create_arg.handle;
|
||||
drmIoctl(device->kms_device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
|
||||
drmIoctl(device->drm.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
|
||||
err_fb:
|
||||
free(fb);
|
||||
return NULL;
|
||||
|
|
@ -388,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
|
||||
|
|
@ -426,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;
|
||||
|
|
@ -442,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);
|
||||
|
|
@ -450,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);
|
||||
|
|
@ -484,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->kms_device->fd;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -512,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);
|
||||
|
|
@ -539,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)
|
||||
|
|
@ -571,7 +508,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
|||
fb->refcnt = 1;
|
||||
fb->backend = device->backend;
|
||||
fb->bo = bo;
|
||||
fb->fd = device->kms_device->fd;
|
||||
fb->fd = device->drm.fd;
|
||||
|
||||
fb->width = gbm_bo_get_width(bo);
|
||||
fb->height = gbm_bo_get_height(bo);
|
||||
|
|
@ -645,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
|
||||
|
|
@ -678,7 +614,7 @@ drm_can_scanout_dmabuf(struct weston_backend *backend,
|
|||
|
||||
static bool
|
||||
drm_fb_compatible_with_plane(struct drm_fb *fb, struct drm_plane *plane,
|
||||
struct weston_paint_node *pnode)
|
||||
struct weston_view *view)
|
||||
{
|
||||
struct drm_device *device = plane->device;
|
||||
struct drm_backend *b = device->backend;
|
||||
|
|
@ -702,11 +638,10 @@ drm_fb_compatible_with_plane(struct drm_fb *fb, struct drm_plane *plane,
|
|||
return true;
|
||||
}
|
||||
|
||||
drm_debug(b, "\t\t\t\t[%s] not assigning paint node %s on %s, "
|
||||
drm_debug(b, "\t\t\t\t[%s] not assigning view %p on %s, "
|
||||
"plane %d (format %s (0x%lx) with modifier 0x%llx) not supported\n",
|
||||
drm_output_get_plane_type_name(plane),
|
||||
pnode->internal_name,
|
||||
drm_output_get_plane_type_name(plane),
|
||||
view, drm_output_get_plane_type_name(plane),
|
||||
plane->plane_id, fb->format->drm_format_name,
|
||||
(unsigned long) fb->format->format,
|
||||
(unsigned long long) fb->modifier);
|
||||
|
|
@ -739,29 +674,28 @@ 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;
|
||||
struct drm_device *device = output->device;
|
||||
struct weston_surface *surface = pnode->surface;
|
||||
struct weston_buffer *buffer = surface->buffer_ref.buffer;
|
||||
struct weston_view *ev = pnode->view;
|
||||
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
||||
struct drm_fb_private *private;
|
||||
struct drm_buffer_fb *buf_fb;
|
||||
bool is_opaque = pnode->is_fully_opaque;
|
||||
bool is_opaque = weston_view_is_opaque(ev, &ev->transform.boundingbox);
|
||||
struct drm_fb *fb;
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
||||
surface->desired_protection > output->base.current_protection) {
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
||||
ev->surface->desired_protection > output->base.current_protection) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -777,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -788,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;
|
||||
}
|
||||
|
||||
|
|
@ -807,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;
|
||||
}
|
||||
|
||||
|
|
@ -824,7 +758,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
if (plane->type == WDRM_PLANE_TYPE_CURSOR)
|
||||
continue;
|
||||
|
||||
if (drm_fb_compatible_with_plane(fb, plane, pnode))
|
||||
if (drm_fb_compatible_with_plane(fb, plane, pnode->view))
|
||||
fb->plane_mask |= 1 << (plane->plane_idx);
|
||||
}
|
||||
if (fb->plane_mask == 0) {
|
||||
|
|
@ -837,12 +771,12 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
* drm_fb we take an additional ref for the weston_buffer's cache. */
|
||||
buf_fb->fb = drm_fb_ref(fb);
|
||||
|
||||
drm_debug(b, "\t\t\t[paint node] paint node %s format: %s\n",
|
||||
pnode->internal_name, fb->format->drm_format_name);
|
||||
drm_debug(b, "\t\t\t[view] view %p format: %s\n",
|
||||
ev, fb->format->drm_format_name);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = drmModeCreatePropertyBlob(device->kms_device->fd,
|
||||
ret = drmModeCreatePropertyBlob(device->drm.fd,
|
||||
&meta, sizeof meta, &blob_id);
|
||||
if (ret != 0) {
|
||||
weston_log("Error: failed to create KMS blob for HDR metadata on output '%s': %s\n",
|
||||
|
|
@ -168,7 +168,7 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output)
|
|||
return -1;
|
||||
}
|
||||
|
||||
drmModeDestroyPropertyBlob(device->kms_device->fd,
|
||||
drmModeDestroyPropertyBlob(device->drm.fd,
|
||||
output->hdr_output_metadata_blob_id);
|
||||
|
||||
output->hdr_output_metadata_blob_id = blob_id;
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -64,7 +64,7 @@ static long backlight_get(struct backlight *backlight, char *node)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = read(fd, buffer, sizeof(buffer));
|
||||
ret = read(fd, &buffer, sizeof(buffer));
|
||||
if (ret < 1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
|
|
@ -119,6 +119,12 @@ long backlight_set_brightness(struct backlight *backlight, long brightness)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = read(fd, &buffer, sizeof(buffer));
|
||||
if (ret < 1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
str_printf(&buffer, "%ld", brightness);
|
||||
if (!buffer) {
|
||||
ret = -1;
|
||||
|
|
@ -234,7 +240,7 @@ struct backlight *backlight_init(struct udev_device *drm_device,
|
|||
if (fd < 0)
|
||||
goto out;
|
||||
|
||||
ret = read (fd, buffer, sizeof(buffer));
|
||||
ret = read (fd, &buffer, sizeof(buffer));
|
||||
close (fd);
|
||||
|
||||
if (ret < 1)
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
@ -32,13 +46,8 @@ srcs_drm = [
|
|||
presentation_time_server_protocol_h,
|
||||
]
|
||||
|
||||
if (libdrm_supports_color_pipeline)
|
||||
srcs_drm += 'colorops.c'
|
||||
endif
|
||||
|
||||
deps_drm = [
|
||||
dep_egl, # optional
|
||||
dep_vulkan, # optional
|
||||
dep_libm,
|
||||
dep_libdl,
|
||||
dep_libshared,
|
||||
|
|
@ -60,16 +69,21 @@ 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')
|
||||
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()
|
||||
error('VA-API recorder requires @0@ >= 0.34.0 which was not found. Or, you can use \'-Dbackend-drm-screencast-vaapi=false\'.'.format(name))
|
||||
endif
|
||||
deps_drm += d
|
||||
endforeach
|
||||
|
||||
srcs_drm += 'vaapi-recorder.c'
|
||||
deps_drm += dependency('threads')
|
||||
config_h.set('BUILD_VAAPI_RECORDER', '1')
|
||||
endif
|
||||
|
||||
if get_option('deprecated-remoting') or get_option('deprecated-pipewire')
|
||||
if get_option('remoting') or get_option('pipewire')
|
||||
if not get_option('renderer-gl')
|
||||
error('DRM virtual requires renderer-gl.')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -139,7 +133,7 @@ drm_mode_ensure_blob(struct drm_device *device, struct drm_mode *mode)
|
|||
if (mode->blob_id)
|
||||
return 0;
|
||||
|
||||
ret = drmModeCreatePropertyBlob(device->kms_device->fd,
|
||||
ret = drmModeCreatePropertyBlob(device->drm.fd,
|
||||
&mode->mode_info,
|
||||
sizeof(mode->mode_info),
|
||||
&mode->blob_id);
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -428,7 +369,7 @@ drm_head_maybe_update_display_data(struct drm_head *head,
|
|||
&head->connector.props[WDRM_CONNECTOR_EDID],
|
||||
props, 0);
|
||||
if (blob_id)
|
||||
edid_blob = drmModeGetPropertyBlob(device->kms_device->fd, blob_id);
|
||||
edid_blob = drmModeGetPropertyBlob(device->drm.fd, blob_id);
|
||||
|
||||
if (edid_blob && edid_blob->length > 0) {
|
||||
if (!head->display_data ||
|
||||
|
|
@ -553,7 +494,7 @@ static void
|
|||
drm_output_destroy_mode(struct drm_device *device, struct drm_mode *mode)
|
||||
{
|
||||
if (mode->blob_id)
|
||||
drmModeDestroyPropertyBlob(device->kms_device->fd, mode->blob_id);
|
||||
drmModeDestroyPropertyBlob(device->drm.fd, mode->blob_id);
|
||||
wl_list_remove(&mode->base.link);
|
||||
free(mode);
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -32,11 +32,8 @@
|
|||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#include "colorops.h"
|
||||
#include "drm-internal.h"
|
||||
#include "shared/weston-assert.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/xalloc.h"
|
||||
|
||||
/**
|
||||
* Allocate a new, empty, plane state.
|
||||
|
|
@ -50,7 +47,6 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
|
|||
assert(state);
|
||||
state->output_state = state_output;
|
||||
state->plane = plane;
|
||||
state->handle = NULL;
|
||||
state->in_fence_fd = -1;
|
||||
state->rotation = drm_rotation_from_output_transform(plane,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
|
@ -59,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
|
||||
|
|
@ -96,8 +89,6 @@ drm_plane_state_free(struct drm_plane_state *state, bool force)
|
|||
state->in_fence_fd = -1;
|
||||
state->zpos = DRM_PLANE_ZPOS_INVALID_PLANE;
|
||||
state->alpha = DRM_PLANE_ALPHA_OPAQUE;
|
||||
drm_color_pipeline_state_destroy(state->pipeline_state);
|
||||
state->pipeline_state = NULL;
|
||||
|
||||
/* Once the damage blob has been submitted, it is refcounted internally
|
||||
* by the kernel, which means we can safely discard it.
|
||||
|
|
@ -105,7 +96,7 @@ drm_plane_state_free(struct drm_plane_state *state, bool force)
|
|||
if (state->damage_blob_id != 0) {
|
||||
device = state->plane->device;
|
||||
|
||||
drmModeDestroyPropertyBlob(device->kms_device->fd,
|
||||
drmModeDestroyPropertyBlob(device->drm.fd,
|
||||
state->damage_blob_id);
|
||||
state->damage_blob_id = 0;
|
||||
}
|
||||
|
|
@ -219,46 +210,110 @@ drm_plane_state_put_back(struct drm_plane_state *state)
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a weston_paint_node, fill the drm_plane_state's co-ordinates to
|
||||
* display on a given plane.
|
||||
* 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 *pnode,
|
||||
struct weston_paint_node *node,
|
||||
uint64_t zpos)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct weston_view *ev = node->view;
|
||||
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
||||
pixman_region32_t dest_rect;
|
||||
pixman_box32_t *box;
|
||||
struct weston_coord corners[2];
|
||||
float sxf1, syf1, sxf2, syf2;
|
||||
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.
|
||||
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);
|
||||
|
||||
/* Update the base weston_plane co-ordinates. */
|
||||
box = pixman_region32_extents(&ev->transform.boundingbox);
|
||||
state->plane->base.x = box->x1;
|
||||
state->plane->base.y = box->y1;
|
||||
|
||||
/* First calculate the destination co-ordinates by taking the
|
||||
* area of the view which is visible on this output, performing any
|
||||
* transforms to account for output rotation and scale as necessary. */
|
||||
pixman_region32_init(&dest_rect);
|
||||
pixman_region32_intersect(&dest_rect, &ev->transform.boundingbox,
|
||||
&output->base.region);
|
||||
weston_region_global_to_output(&dest_rect, &output->base, &dest_rect);
|
||||
|
||||
box = pixman_region32_extents(&dest_rect);
|
||||
|
||||
state->dest_x = box->x1;
|
||||
state->dest_y = box->y1;
|
||||
state->dest_w = box->x2 - box->x1;
|
||||
state->dest_h = box->y2 - box->y1;
|
||||
|
||||
/* Now calculate the source rectangle, by transforming the destination
|
||||
* rectangle by the output to buffer matrix. */
|
||||
corners[0] = weston_matrix_transform_coord(
|
||||
&node->output_to_buffer_matrix,
|
||||
weston_coord(box->x1, box->y1));
|
||||
corners[1] = weston_matrix_transform_coord(
|
||||
&node->output_to_buffer_matrix,
|
||||
weston_coord(box->x2, box->y2));
|
||||
sxf1 = corners[0].x;
|
||||
syf1 = corners[0].y;
|
||||
sxf2 = corners[1].x;
|
||||
syf2 = corners[1].y;
|
||||
pixman_region32_fini(&dest_rect);
|
||||
|
||||
/* Make sure that our post-transform coordinates are in the
|
||||
* right order.
|
||||
*/
|
||||
assert(drm_paint_node_transform_supported(pnode, state->plane));
|
||||
if (sxf1 > sxf2) {
|
||||
float temp = sxf1;
|
||||
|
||||
assert(pnode->simple_transform);
|
||||
state->rotation = drm_rotation_from_output_transform(state->plane, pnode->transform);
|
||||
sxf1 = sxf2;
|
||||
sxf2 = temp;
|
||||
}
|
||||
if (syf1 > syf2) {
|
||||
float temp = syf1;
|
||||
|
||||
state->dest_x = pnode->output_dest.x;
|
||||
state->dest_y = pnode->output_dest.y;
|
||||
state->dest_w = pnode->output_dest.width;
|
||||
state->dest_h = pnode->output_dest.height;
|
||||
syf1 = syf2;
|
||||
syf2 = temp;
|
||||
}
|
||||
|
||||
/* Convert to U16.16 KMS fixed-point encoding. */
|
||||
state->src_x = wl_fixed_from_double(pnode->buffer_source_x) << 8;
|
||||
state->src_y = wl_fixed_from_double(pnode->buffer_source_y) << 8;
|
||||
state->src_w = wl_fixed_from_double(pnode->buffer_source_width) << 8;
|
||||
state->src_h = wl_fixed_from_double(pnode->buffer_source_height) << 8;
|
||||
/* Shift from S23.8 wl_fixed to U16.16 KMS fixed-point encoding. */
|
||||
state->src_x = wl_fixed_from_double(sxf1) << 8;
|
||||
state->src_y = wl_fixed_from_double(syf1) << 8;
|
||||
state->src_w = wl_fixed_from_double(sxf2 - sxf1) << 8;
|
||||
state->src_h = wl_fixed_from_double(syf2 - syf1) << 8;
|
||||
|
||||
/* Clamp our source co-ordinates to surface bounds; it's possible
|
||||
* for intermediate translations to give us slightly incorrect
|
||||
* co-ordinates if we have, for example, multiple zooming
|
||||
* transformations. View bounding boxes are also explicitly rounded
|
||||
* greedily. */
|
||||
if (state->src_x < 0)
|
||||
state->src_x = 0;
|
||||
if (state->src_y < 0)
|
||||
state->src_y = 0;
|
||||
if (state->src_w > (uint32_t) ((buffer->width << 16) - state->src_x))
|
||||
state->src_w = (buffer->width << 16) - state->src_x;
|
||||
if (state->src_h > (uint32_t) ((buffer->height << 16) - state->src_y))
|
||||
state->src_h = (buffer->height << 16) - state->src_y;
|
||||
|
||||
/* apply zpos if available */
|
||||
state->zpos = zpos;
|
||||
|
||||
/* The alpha of the view is normalized to alpha value range
|
||||
* [min_alpha, max_alpha] that got from drm. The alpha value would
|
||||
* never exceed max_alpha if pnode->view_alpha <= 1.0.
|
||||
* never exceed max_alpha if ev->alpha <= 1.0.
|
||||
*/
|
||||
state->alpha = min_alpha +
|
||||
(uint16_t)round((max_alpha - min_alpha) * pnode->view_alpha);
|
||||
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -315,7 +370,8 @@ drm_output_state_get_plane(struct drm_output_state *state_output,
|
|||
* in the repaint cycle; see drm_output_state_duplicate.
|
||||
*/
|
||||
struct drm_output_state *
|
||||
drm_output_state_alloc(struct drm_output *output)
|
||||
drm_output_state_alloc(struct drm_output *output,
|
||||
struct drm_pending_state *pending_state)
|
||||
{
|
||||
struct drm_output_state *state = zalloc(sizeof(*state));
|
||||
|
||||
|
|
@ -323,7 +379,11 @@ drm_output_state_alloc(struct drm_output *output)
|
|||
state->output = output;
|
||||
state->dpms = WESTON_DPMS_OFF;
|
||||
state->protection = WESTON_HDCP_DISABLE;
|
||||
wl_list_init(&state->link);
|
||||
state->pending_state = pending_state;
|
||||
if (pending_state)
|
||||
wl_list_insert(&pending_state->output_list, &state->link);
|
||||
else
|
||||
wl_list_init(&state->link);
|
||||
|
||||
wl_list_init(&state->plane_list);
|
||||
|
||||
|
|
@ -343,12 +403,10 @@ drm_output_state_duplicate(struct drm_output_state *src,
|
|||
struct drm_pending_state *pending_state,
|
||||
enum drm_output_state_duplicate_mode plane_mode)
|
||||
{
|
||||
struct weston_compositor *compositor = src->output->base.compositor;
|
||||
struct drm_output_state *dst = xmalloc(sizeof(*dst));
|
||||
struct drm_output_state *dst = malloc(sizeof(*dst));
|
||||
struct drm_plane_state *ps;
|
||||
|
||||
/* The reuse bit isn't stored in the state */
|
||||
weston_assert_false(compositor, src->mode & DRM_OUTPUT_PROPOSE_STATE_REUSE);
|
||||
assert(dst);
|
||||
|
||||
/* Copy the whole structure, then individually modify the
|
||||
* pending_state, as well as the list link into our pending
|
||||
|
|
@ -366,7 +424,7 @@ drm_output_state_duplicate(struct drm_output_state *src,
|
|||
wl_list_for_each(ps, &src->plane_list, link) {
|
||||
/* Don't carry planes which are now disabled; these should be
|
||||
* free for other outputs to reuse. */
|
||||
if (!ps->handle)
|
||||
if (!ps->output)
|
||||
continue;
|
||||
|
||||
if (plane_mode == DRM_OUTPUT_STATE_CLEAR_PLANES)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue