mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-25 08:20:11 +01:00
Compare commits
No commits in common. "main" and "13.0.95" have entirely different histories.
340 changed files with 16532 additions and 52320 deletions
206
.gitlab-ci.yml
206
.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: '2025-12-19-mesa-25.3.2'
|
||||
FDO_DISTRIBUTION_TAG: '2024-08-14-00-freerdp3.x'
|
||||
|
||||
|
||||
include:
|
||||
|
|
@ -66,11 +66,6 @@ include:
|
|||
# we need a default case though, so all the rest still run
|
||||
- when: on_success
|
||||
|
||||
default:
|
||||
retry:
|
||||
max: 2
|
||||
when: runner_system_failure
|
||||
|
||||
.merge-rules:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
|
|
@ -84,7 +79,7 @@ stages:
|
|||
- "Pre Base container"
|
||||
- "Base container"
|
||||
- "Full build and test"
|
||||
- "No-GL/Vulkan build and test"
|
||||
- "No-GL build and test"
|
||||
- "Other builds"
|
||||
- pages
|
||||
|
||||
|
|
@ -93,23 +88,20 @@ stages:
|
|||
.os-debian-lts:
|
||||
variables:
|
||||
BUILD_OS: debian
|
||||
LLVM_VERSION: 15
|
||||
USE_DEBIAN_BACKPORTS: y
|
||||
PACKAGES_SPECIFIC: vulkan-validationlayers-dev
|
||||
LLVM_VERSION: 11
|
||||
FREERDP_VERSION: 2
|
||||
FDO_DISTRIBUTION_VERSION: bookworm
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
||||
FDO_DISTRIBUTION_VERSION: bullseye
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
|
||||
|
||||
.os-debian:
|
||||
variables:
|
||||
BUILD_OS: debian
|
||||
LLVM_VERSION: 19
|
||||
LLVM_VERSION: 15
|
||||
FREERDP_VERSION: 3
|
||||
USE_DEBIAN_BACKPORTS: y
|
||||
PACKAGES_SPECIFIC: vulkan-utility-libraries-dev libpolly-19-dev libclang-rt-19-dev python3-standard-imghdr
|
||||
# If you upgrade from trixie, see the use_tls=0 notes in tests/meson.build.
|
||||
FDO_DISTRIBUTION_VERSION: trixie
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
||||
USE_BOOKWORM_BACKPORTS: y
|
||||
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
|
||||
FDO_DISTRIBUTION_VERSION: bookworm
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
|
||||
|
||||
# Does not inherit .default-rules as we only want it to run in MR context.
|
||||
check-commit:
|
||||
|
|
@ -119,6 +111,7 @@ check-commit:
|
|||
stage: "Merge request checks"
|
||||
script:
|
||||
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
|
||||
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
|
||||
variables:
|
||||
GIT_DEPTH: 100
|
||||
artifacts:
|
||||
|
|
@ -146,14 +139,12 @@ check-commit:
|
|||
- .os-debian-lts
|
||||
variables:
|
||||
BUILD_ARCH: "armv7"
|
||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||
|
||||
.debian-armv7:
|
||||
extends:
|
||||
- .os-debian
|
||||
variables:
|
||||
BUILD_ARCH: "armv7"
|
||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
|
||||
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
|
||||
# Inhibit installation of freerdp-dev
|
||||
|
|
@ -220,6 +211,8 @@ armv7-debian-lts-container_prep:
|
|||
- .fdo.container-build@debian
|
||||
tags:
|
||||
- aarch64
|
||||
variables:
|
||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
||||
needs:
|
||||
- job: base-container-pre
|
||||
timeout: 30m
|
||||
|
|
@ -232,6 +225,8 @@ armv7-debian-container_prep:
|
|||
- .fdo.container-build@debian
|
||||
tags:
|
||||
- aarch64
|
||||
variables:
|
||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
||||
needs:
|
||||
- job: base-container-pre
|
||||
timeout: 30m
|
||||
|
|
@ -267,23 +262,17 @@ aarch64-debian-container_prep:
|
|||
timeout: 15m
|
||||
variables:
|
||||
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
|
||||
BUILDDIR_WESTINY: $CI_PROJECT_DIR/build-westiny-$CI_JOB_NAME
|
||||
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
||||
PREFIX_WESTINY: $CI_PROJECT_DIR/prefix-westiny-$CI_JOB_NAME
|
||||
before_script:
|
||||
- export PATH=~/.local/bin:$PATH
|
||||
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
||||
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
|
||||
- export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
|
||||
- mkdir "$BUILDDIR" "$PREFIX"
|
||||
- mkdir "$BUILDDIR_WESTINY" "$PREFIX_WESTINY"
|
||||
|
||||
.build-with-clang:
|
||||
variables:
|
||||
CC: clang-$LLVM_VERSION
|
||||
CC_LD: lld-$LLVM_VERSION
|
||||
CXX: clang++-$LLVM_VERSION
|
||||
CXX_LD: lld-$LLVM_VERSION
|
||||
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
|
||||
|
||||
# Extends the core build templates to also provide for running our testing. We
|
||||
|
|
@ -293,8 +282,17 @@ aarch64-debian-container_prep:
|
|||
extends:
|
||||
- .default-rules
|
||||
script:
|
||||
"${CI_PROJECT_DIR}/.gitlab-ci/build-and-test.sh"
|
||||
|
||||
- cd "$BUILDDIR"
|
||||
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
- ninja install
|
||||
- test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
||||
- virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
||||
- TEST_RES=$(cat $TESTS_RES_PATH)
|
||||
- rm $TESTS_RES_PATH
|
||||
- cp -R /weston-virtme ./
|
||||
- rm weston-virtme/${KERNEL_IMAGE}
|
||||
- exit $TEST_RES
|
||||
artifacts:
|
||||
name: weston-$CI_COMMIT_SHA
|
||||
when: always
|
||||
|
|
@ -305,7 +303,7 @@ aarch64-debian-container_prep:
|
|||
- $BUILDDIR/weston-virtme
|
||||
- $PREFIX
|
||||
reports:
|
||||
junit: $BUILDDIR/meson-logs/testlog.junit.xml
|
||||
junit: $BUILDDIR/meson-logs/testlog-junit.xml
|
||||
|
||||
# Same as above, but without running any tests.
|
||||
.build-no-test:
|
||||
|
|
@ -427,79 +425,67 @@ aarch64-debian-container_prep:
|
|||
- job: aarch64-debian-container_prep
|
||||
artifacts: false
|
||||
|
||||
# Full build (gcov + perfetto) used for testing under KVM.
|
||||
# Full build, used for testing under KVM.
|
||||
.build-options-full:
|
||||
stage: "Full build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Doptimization=0
|
||||
-Db_coverage=true
|
||||
--force-fallback-for=perfetto
|
||||
-Dperfetto=true
|
||||
-Dperfetto:werror=false
|
||||
-Dwerror=true
|
||||
-Dtest-skip-is-failure=true
|
||||
after_script:
|
||||
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
|
||||
- ninja -C "$BUILDDIR" coverage-xml
|
||||
|
||||
# Full build, (without gcov and perfetto)
|
||||
.build-options-full-v2:
|
||||
stage: "Full build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Doptimization=0
|
||||
-Dwerror=true
|
||||
-Dtest-skip-is-failure=true
|
||||
|
||||
x86_64-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-x86_64
|
||||
- .build-options-full
|
||||
|
||||
x86_64-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-full
|
||||
artifacts:
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: $BUILDDIR/meson-logs/coverage.xml
|
||||
|
||||
x86_64-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-full-v2
|
||||
|
||||
aarch64-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
aarch64-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
x86_64-clang-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-x86_64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
x86_64-clang-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
aarch64-clang-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
aarch64-clang-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
# Docs should be invariant on all architectures, so we only do it on Debian
|
||||
# x86-64.
|
||||
|
|
@ -513,20 +499,9 @@ docs-build:
|
|||
- .build-env-debian-x86_64
|
||||
- .build-no-test
|
||||
|
||||
# Building without gl-renderer and/or vulkan-renderer, to make sure this keeps working.
|
||||
.build-options-no-gl-no-vulkan:
|
||||
stage: "No-GL/Vulkan build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||
-Drenderer-gl=false
|
||||
-Drenderer-vulkan=false
|
||||
-Dremoting=false
|
||||
-Dpipewire=false
|
||||
-Dwerror=true
|
||||
|
||||
# Building without gl-renderer, to make sure this keeps working.
|
||||
.build-options-no-gl:
|
||||
stage: "No-GL/Vulkan build and test"
|
||||
stage: "No-GL build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||
|
|
@ -535,72 +510,51 @@ docs-build:
|
|||
-Dpipewire=false
|
||||
-Dwerror=true
|
||||
|
||||
.build-options-no-vulkan:
|
||||
stage: "No-GL/Vulkan build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||
-Drenderer-vulkan=false
|
||||
-Dremoting=false
|
||||
-Dpipewire=false
|
||||
-Dwerror=true
|
||||
|
||||
x86_64-debian-lts-no-gl-no-vulkan-build:
|
||||
x86_64-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-x86_64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
x86_64-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-debian-lts-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-clang-debian-lts-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-clang-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
aarch64-debian-lts-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
aarch64-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
- .build-options-no-gl
|
||||
|
||||
x86_64-debian-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-no-gl
|
||||
|
||||
x86_64-debian-no-vulkan-build:
|
||||
armv7-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-no-vulkan
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
armv7-debian-no-gl-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
armv7-clang-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
armv7-clang-debian-no-gl-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
aarch64-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-options-no-gl
|
||||
|
||||
aarch64-debian-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-options-no-gl
|
||||
|
||||
# Expose docs and coverage reports, so we can show users any changes to these
|
||||
# inside their merge requests, letting us check them before merge.
|
||||
|
|
@ -612,18 +566,18 @@ x86_64-debian-no-vulkan-build:
|
|||
docs-and-coverage:
|
||||
extends:
|
||||
- .default-rules
|
||||
- .debian-lts-x86_64
|
||||
- .debian-x86_64
|
||||
- .fdo.suffixed-image@debian
|
||||
stage: pages
|
||||
needs:
|
||||
- job: docs-build
|
||||
artifacts: true
|
||||
- job: x86_64-debian-lts-full-build
|
||||
- job: x86_64-debian-full-build
|
||||
artifacts: true
|
||||
timeout: 5m
|
||||
script:
|
||||
- mv prefix-weston-docs-build/share/doc/weston Documentation
|
||||
- mv build-weston-x86_64-debian-lts-full-build/meson-logs/coveragereport Test_Coverage
|
||||
- mv build-weston-x86_64-debian-full-build/meson-logs/coveragereport Test_Coverage
|
||||
- rm Test_Coverage/gcov.css
|
||||
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
|
||||
- cp doc/style/*.png Test_Coverage/
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
fdo_log_section_start_collapsed build_weston "build_weston"
|
||||
cd "$BUILDDIR"
|
||||
meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
ninja install
|
||||
|
||||
if [ "$CI_JOB_NAME" == "x86_64-debian-full-build" ]; then
|
||||
cd "$BUILDDIR_WESTINY"
|
||||
export NPREFIX=$CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
||||
export PKG_CONFIG_PATH=$NPREFIX/lib/pkgconfig/:$NPREFIX/share/pkgconfig/:$NPREFIX/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
|
||||
meson setup --prefix="$PREFIX_WESTINY" --wrap-mode=nofallback ../westinyplus/
|
||||
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
ninja install
|
||||
ninja clean
|
||||
cd -
|
||||
fi
|
||||
fdo_log_section_end build_weston
|
||||
|
||||
test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
||||
virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
||||
TEST_RES=$(cat $TESTS_RES_PATH)
|
||||
rm $TESTS_RES_PATH
|
||||
cp -R /weston-virtme ./
|
||||
rm weston-virtme/${KERNEL_IMAGE}
|
||||
exit $TEST_RES
|
||||
|
|
@ -4,8 +4,6 @@
|
|||
# .gitlab-ci.yml for more information. This script is called from an
|
||||
# OS-specific build scripts like debian-install.sh.
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
set -o xtrace -o errexit
|
||||
|
||||
# Set concurrency to an appropriate level for our shared runners, falling back
|
||||
|
|
@ -27,8 +25,7 @@ esac
|
|||
|
||||
# Build and install Meson. Generally we want to keep this in sync with what
|
||||
# we require inside meson.build.
|
||||
fdo_log_section_start_collapsed install_meson "install_meson"
|
||||
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.4.2
|
||||
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.0.0
|
||||
export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
|
||||
|
|
@ -44,22 +41,31 @@ pip3 install $PIP_ARGS sphinxcontrib-qthelp==1.0.3
|
|||
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
|
||||
pip3 install $PIP_ARGS breathe==4.31.0
|
||||
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
|
||||
fdo_log_section_end install_meson
|
||||
|
||||
|
||||
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
|
||||
# predictably test the DRM backend in the absence of real hardware. We lock the
|
||||
# version here so we see predictable results.
|
||||
#
|
||||
# To run this we use virtme-ng, a QEMU wrapper. It is a fork from virtme, whose
|
||||
# development stalled.
|
||||
# To run this we use virtme, a QEMU wrapper: https://github.com/amluto/virtme
|
||||
#
|
||||
# virtme-ng makes our lives easier by abstracting handling of the console,
|
||||
# virtme makes our lives easier by abstracting handling of the console,
|
||||
# filesystem, etc, so we can pretend that the VM we execute in is actually
|
||||
# just a regular container.
|
||||
fdo_log_section_start_collapsed install_kernel "install_kernel"
|
||||
#
|
||||
# The reason why we are using a fork here is that it adds a patch to have the
|
||||
# --script-dir command line option. With that we can run scripts that are in a
|
||||
# certain folder when virtme starts, which is necessary in our use case.
|
||||
#
|
||||
# The upstream also has some commands that could help us to reach the same
|
||||
# results: --script-sh and --script-exec. Unfornutately they are not completely
|
||||
# implemented yet, so we had some trouble to use them and it was becoming
|
||||
# hackery.
|
||||
#
|
||||
# The fork pulls in this support from the original GitHub PR, rebased on top of
|
||||
# a newer upstream version which fixes AArch64 support.
|
||||
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
||||
git clone --depth=1 --branch=v6.18 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
|
||||
# 6.3 is (still) used as >= 6.5 drm-writeback test will timeout
|
||||
git clone --depth=1 --branch=v6.3 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
|
||||
cd linux
|
||||
|
||||
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
|
||||
|
|
@ -85,8 +91,9 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
|||
./scripts/config \
|
||||
--enable CONFIG_DRM \
|
||||
--enable CONFIG_DRM_KMS_HELPER \
|
||||
--enable CONFIG_DRM_KMS_FB_HELPER \
|
||||
--enable CONFIG_DRM_VKMS \
|
||||
--enable CONFIG_UDMABUF
|
||||
--enable CONFIG_DRM_VGEM
|
||||
make ARCH=${LINUX_ARCH} oldconfig
|
||||
make ARCH=${LINUX_ARCH}
|
||||
|
||||
|
|
@ -101,15 +108,14 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
|||
./setup.py install
|
||||
cd ..
|
||||
fi
|
||||
fdo_log_section_end install_kernel
|
||||
|
||||
# Build and install Wayland; keep this version in sync with our dependency
|
||||
# in meson.build.
|
||||
fdo_log_section_start_collapsed install_wayland "install_wayland"
|
||||
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
|
||||
cd wayland
|
||||
git show -s HEAD
|
||||
meson setup build --wrap-mode=nofallback -Ddocumentation=false
|
||||
mkdir build
|
||||
meson build --wrap-mode=nofallback -Ddocumentation=false
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf wayland
|
||||
|
|
@ -117,39 +123,24 @@ rm -rf wayland
|
|||
# Keep this version in sync with our dependency in meson.build. If you wish to
|
||||
# raise a MR against custom protocol, please change this reference to clone
|
||||
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
|
||||
git clone --branch 1.46 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||
git clone --branch 1.33 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||
cd wayland-protocols
|
||||
git show -s HEAD
|
||||
meson setup build --wrap-mode=nofallback -Dtests=false
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf wayland-protocols
|
||||
fdo_log_section_end install_wayland
|
||||
|
||||
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
|
||||
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa
|
||||
# depends on 2.4.109 as well.
|
||||
# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30}
|
||||
fdo_log_section_start_collapsed install_libdrm "install_libdrm"
|
||||
git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
||||
git clone --branch libdrm-2.4.109 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
||||
cd drm
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dvc4=false -Dfreedreno=false -Detnaviv=false
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf drm
|
||||
fdo_log_section_end install_libdrm
|
||||
|
||||
# Build and install Vulkan-Headers with a defined version, mostly because
|
||||
# the version in Debian 11 (bullseye) is too old to build vulkan-renderer.
|
||||
fdo_log_section_start_collapsed install_vulkan_headers "install_vulkan_headers"
|
||||
git clone --branch sdk-1.3.239.0 --depth=1 https://github.com/KhronosGroup/Vulkan-Headers
|
||||
cd Vulkan-Headers
|
||||
cmake -G Ninja -B build
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf Vulkan-Headers
|
||||
fdo_log_section_end install_vulkan_headers
|
||||
|
||||
# Build and install our own version of Mesa. Debian provides a perfectly usable
|
||||
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
|
||||
|
|
@ -158,89 +149,64 @@ fdo_log_section_end install_vulkan_headers
|
|||
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
|
||||
# please be prepared for some of the tests to change output, which will need to
|
||||
# be manually inspected for correctness.
|
||||
fdo_log_section_start_collapsed install_mesa "install_mesa"
|
||||
|
||||
# Needed for Mesa >= 25.3
|
||||
git clone --branch 12.2.0 --depth=1 https://github.com/KhronosGroup/glslang
|
||||
cd glslang
|
||||
cmake -G Ninja -B build
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf glslang
|
||||
|
||||
# The 25.3 was the first stable release where the Vulkan backend works with
|
||||
# vkms+lavapipe.
|
||||
git clone --branch mesa-25.3.2 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
||||
git clone --branch 23.0 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
||||
cd mesa
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dgallium-drivers=llvmpipe -Dvulkan-drivers=swrast -Dvideo-codecs= \
|
||||
-Degl=enabled -Dgbm=enabled -Dgles2=enabled -Dllvm=enabled \
|
||||
-Dshared-glapi=enabled -Dglx=disabled
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dgallium-drivers=swrast -Dvulkan-drivers= -Ddri-drivers=
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf mesa
|
||||
fdo_log_section_end install_mesa
|
||||
|
||||
# PipeWire is used for remoting support. Unlike our other dependencies its
|
||||
# behaviour will be stable, however as a pre-1.0 project its API is not yet
|
||||
# stable, so again we lock it to a fixed version.
|
||||
#
|
||||
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
|
||||
fdo_log_section_start_collapsed install_pipewire "install_pipewire"
|
||||
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
|
||||
cd pipewire-src
|
||||
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf pipewire-src
|
||||
fdo_log_section_end install_pipewire
|
||||
|
||||
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
|
||||
# We use this for our tests using the DRM backend.
|
||||
fdo_log_section_start_collapsed install_seatd "install_seatd"
|
||||
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
|
||||
cd seatd
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf seatd
|
||||
fdo_log_section_end install_seatd
|
||||
|
||||
# Build and install aml and neatvnc, which are required for the VNC backend
|
||||
fdo_log_section_start_collapsed install_aml_neatvnc "install_aml_neatvnc"
|
||||
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
|
||||
cd aml
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf aml
|
||||
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
|
||||
cd neatvnc
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf neatvnc
|
||||
fdo_log_section_end install_aml_neatvnc
|
||||
|
||||
# Build and install libdisplay-info, used by drm-backend
|
||||
fdo_log_section_start_collapsed install_libdisplay-info "install_libdisplay-info"
|
||||
git clone --branch 0.2.0 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
||||
git clone --branch 0.1.1 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
||||
cd libdisplay-info
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf libdisplay-info
|
||||
fdo_log_section_end install_libdisplay-info
|
||||
|
||||
# Build and install lcms2, which we use to support color-management.
|
||||
fdo_log_section_start_collapsed install_lcms2 "install_lcms2"
|
||||
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
|
||||
cd lcms2
|
||||
git checkout -b snapshot lcms2.16
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf lcms2
|
||||
fdo_log_section_end install_lcms2
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
584
clients/color.c
584
clients/color.c
|
|
@ -1,584 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2024 SUSE Software Solutions Germany GmbH
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "color-management-v1-client-protocol.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "single-pixel-buffer-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "window.h"
|
||||
|
||||
enum image_description_status {
|
||||
IMAGE_DESCRIPTION_NOT_CREATED = 0,
|
||||
IMAGE_DESCRIPTION_READY,
|
||||
IMAGE_DESCRIPTION_FAILED,
|
||||
};
|
||||
|
||||
struct pixel_color {
|
||||
uint32_t r;
|
||||
uint32_t g;
|
||||
uint32_t b;
|
||||
uint32_t a;
|
||||
};
|
||||
|
||||
struct color {
|
||||
struct display *display;
|
||||
struct window *window;
|
||||
struct widget *parent_widget;
|
||||
struct widget *widget;
|
||||
|
||||
struct wp_color_manager_v1 *color_manager;
|
||||
struct wp_color_management_surface_v1 *color_surface;
|
||||
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
struct wp_viewport *viewport;
|
||||
|
||||
struct pixel_color pixel_color;
|
||||
|
||||
enum wp_color_manager_v1_primaries primaries;
|
||||
enum wp_color_manager_v1_transfer_function transfer_function;
|
||||
float min_lum;
|
||||
float max_lum;
|
||||
float ref_lum;
|
||||
|
||||
uint32_t supported_color_features;
|
||||
uint32_t supported_rendering_intents;
|
||||
uint32_t supported_primaries_named;
|
||||
uint32_t supported_tf_named;
|
||||
};
|
||||
|
||||
struct valid_enum {
|
||||
const char *name;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
static bool opt_help = false;
|
||||
static uint32_t opt_width = 250;
|
||||
static uint32_t opt_height = 250;
|
||||
static const char *opt_r = NULL;
|
||||
static const char *opt_g = NULL;
|
||||
static const char *opt_b = NULL;
|
||||
static const char *opt_a = NULL;
|
||||
static const char *opt_primaries = NULL;
|
||||
static const char *opt_transfer_function = NULL;
|
||||
static const char *opt_min_lum = NULL;
|
||||
static const char *opt_max_lum = NULL;
|
||||
static const char *opt_ref_lum = NULL;
|
||||
static const struct weston_option cli_options[] = {
|
||||
{ WESTON_OPTION_BOOLEAN, "help", 0, &opt_help },
|
||||
{ WESTON_OPTION_UNSIGNED_INTEGER, "width", 'w', &opt_width },
|
||||
{ WESTON_OPTION_UNSIGNED_INTEGER, "height", 'h', &opt_height },
|
||||
{ WESTON_OPTION_STRING, 0, 'R', &opt_r },
|
||||
{ WESTON_OPTION_STRING, 0, 'G', &opt_g },
|
||||
{ WESTON_OPTION_STRING, 0, 'B', &opt_b },
|
||||
{ WESTON_OPTION_STRING, 0, 'A', &opt_a },
|
||||
{ WESTON_OPTION_STRING, "primaries", 'p', &opt_primaries },
|
||||
{ WESTON_OPTION_STRING, "transfer-function", 't', &opt_transfer_function },
|
||||
{ WESTON_OPTION_STRING, "min-lum", 'm', &opt_min_lum },
|
||||
{ WESTON_OPTION_STRING, "max-lum", 'M', &opt_max_lum },
|
||||
{ WESTON_OPTION_STRING, "ref-lum", 'r', &opt_ref_lum },
|
||||
};
|
||||
|
||||
static const struct valid_enum valid_primaries[] = {
|
||||
{ "srgb", WP_COLOR_MANAGER_V1_PRIMARIES_SRGB },
|
||||
{ "bt2020", WP_COLOR_MANAGER_V1_PRIMARIES_BT2020 },
|
||||
};
|
||||
|
||||
static const struct valid_enum valid_transfer_functions[] = {
|
||||
{ "srgb", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB },
|
||||
{ "pq", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ },
|
||||
{ "linear", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR },
|
||||
};
|
||||
|
||||
static bool
|
||||
validate_color(const char *c, uint32_t *dest, uint32_t fallback)
|
||||
{
|
||||
char *end;
|
||||
double value;
|
||||
|
||||
if (!c) {
|
||||
*dest = fallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = strtod(c, &end);
|
||||
if (value < 0.0 || value > 1.0 || *end != '\0') {
|
||||
fprintf(stderr, "Validating color failed, it should be between 0.0 and 1.0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = value * UINT32_MAX;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_option(const char *option, uint32_t *dest,
|
||||
const struct valid_enum *valid_options,
|
||||
int count, uint32_t fallback)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!option) {
|
||||
*dest = fallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (strcmp(valid_options[i].name, option) == 0) {
|
||||
*dest = valid_options[i].value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Validating option '%s' failed, valid options:\n", option);
|
||||
for (i = 0; i < count; i++)
|
||||
fprintf(stderr, "'%s' ", valid_options[i].name);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_luminance(const char *c, float *dest, float fallback)
|
||||
{
|
||||
char *end;
|
||||
float value;
|
||||
|
||||
if (!c) {
|
||||
*dest = fallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = strtof(c, &end);
|
||||
if (value < 0.f || value > 10000.f || *end != '\0') {
|
||||
fprintf(stderr, "Validating luminance failed, it should be between 0 and 10,000\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_options(struct color *color)
|
||||
{
|
||||
return validate_color(opt_r, &color->pixel_color.r, 0) &&
|
||||
validate_color(opt_g, &color->pixel_color.g, 0) &&
|
||||
validate_color(opt_b, &color->pixel_color.b, 0) &&
|
||||
validate_color(opt_a, &color->pixel_color.a, UINT32_MAX) &&
|
||||
validate_option(opt_primaries, &color->primaries,
|
||||
valid_primaries,
|
||||
ARRAY_LENGTH(valid_primaries),
|
||||
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
|
||||
validate_option(opt_transfer_function, &color->transfer_function,
|
||||
valid_transfer_functions,
|
||||
ARRAY_LENGTH(valid_transfer_functions),
|
||||
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
|
||||
validate_luminance(opt_min_lum, &color->min_lum, -1.f) &&
|
||||
validate_luminance(opt_max_lum, &color->max_lum, -1.f) &&
|
||||
validate_luminance(opt_ref_lum, &color->ref_lum, -1.f);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *program_name, int exit_code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
fprintf(stderr, "Usage: %s [OPTIONS]\n", program_name);
|
||||
fprintf(stderr, " --help\n");
|
||||
fprintf(stderr, " --width or -w\n");
|
||||
fprintf(stderr, " --height or -h\n");
|
||||
fprintf(stderr, " -R (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " -G (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " -B (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " -A (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " --primaries or -p:");
|
||||
fprintf(stderr, "\n ");
|
||||
for (i = 0; i < ARRAY_LENGTH(valid_primaries); i++)
|
||||
fprintf(stderr, " '%s'", valid_primaries[i].name);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " --transfer-function or -t:");
|
||||
fprintf(stderr, "\n ");
|
||||
for (i = 0; i < ARRAY_LENGTH(valid_transfer_functions); i++)
|
||||
fprintf(stderr, " '%s'", valid_transfer_functions[i].name);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " --min-lum or -m (0.0 to 10000.0)\n");
|
||||
fprintf(stderr, " --max-lum or -M (0.0 to 10000.0)\n");
|
||||
fprintf(stderr, " --ref-lum or -r (0.0 to 10000.0)\n");
|
||||
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static void
|
||||
supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t render_intent)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_rendering_intents |= 1 << render_intent;
|
||||
}
|
||||
|
||||
static void
|
||||
supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t feature)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_color_features |= 1 << feature;
|
||||
}
|
||||
|
||||
static void
|
||||
supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t tf)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_tf_named |= 1 << tf;
|
||||
}
|
||||
|
||||
static void
|
||||
supported_primaries_named(void *data,
|
||||
struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t primaries)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_primaries_named |= 1 << primaries;
|
||||
}
|
||||
|
||||
static void
|
||||
done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wp_color_manager_v1_listener color_manager_listener = {
|
||||
supported_intent,
|
||||
supported_feature,
|
||||
supported_tf_named,
|
||||
supported_primaries_named,
|
||||
done,
|
||||
};
|
||||
|
||||
static void
|
||||
global_handler(struct display *display, uint32_t name,
|
||||
const char *interface, uint32_t version, void *data)
|
||||
{
|
||||
struct color *color = data;
|
||||
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
||||
|
||||
if (strcmp(interface, wp_color_manager_v1_interface.name) == 0) {
|
||||
color->color_manager = display_bind(display, name,
|
||||
&wp_color_manager_v1_interface, 1);
|
||||
color->color_surface = wp_color_manager_v1_get_surface(color->color_manager,
|
||||
surface);
|
||||
wp_color_manager_v1_add_listener(color->color_manager,
|
||||
&color_manager_listener, color);
|
||||
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
||||
color->single_pixel_manager =
|
||||
display_bind(display, name,
|
||||
&wp_single_pixel_buffer_manager_v1_interface, 1);
|
||||
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
||||
color->viewporter = display_bind(display, name,
|
||||
&wp_viewporter_interface, 1);
|
||||
color->viewport = wp_viewporter_get_viewport(color->viewporter, surface);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
check_color_requirements(struct color *color)
|
||||
{
|
||||
|
||||
if (!color->color_manager) {
|
||||
fprintf(stderr, "The compositor doesn't expose %s\n",
|
||||
wp_color_manager_v1_interface.name);
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC))) {
|
||||
fprintf(stderr, "The color manager doesn't support the parametric creator\n");
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_primaries_named & (1 << color->primaries))) {
|
||||
fprintf(stderr, "The color manager doesn't support the primaries name\n");
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_tf_named & (1 << color->transfer_function))) {
|
||||
fprintf(stderr, "The color manager doesn't support the transfer function\n");
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_rendering_intents & (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL))) {
|
||||
fprintf(stderr, "The color manager doesn't support perceptual render intent\n");
|
||||
return false;
|
||||
}
|
||||
if (color->min_lum != -1.f || color->max_lum != -1.f || color->ref_lum != -1.f) {
|
||||
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES))) {
|
||||
fprintf(stderr, "The color manager doesn't support setting luminances\n");
|
||||
return false;
|
||||
}
|
||||
if (color->min_lum == -1.f || color->max_lum == -1.f || color->ref_lum == -1.f) {
|
||||
fprintf(stderr, "To set the luminances it is required min-lum, max-lum and ref-lum\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
color_destroy(struct color *color)
|
||||
{
|
||||
if (color->color_surface)
|
||||
wp_color_management_surface_v1_destroy(color->color_surface);
|
||||
|
||||
if (color->color_manager)
|
||||
wp_color_manager_v1_destroy(color->color_manager);
|
||||
|
||||
if (color->single_pixel_manager)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(color->single_pixel_manager);
|
||||
|
||||
if (color->viewport)
|
||||
wp_viewport_destroy(color->viewport);
|
||||
|
||||
if (color->viewporter)
|
||||
wp_viewporter_destroy(color->viewporter);
|
||||
|
||||
if (color->widget)
|
||||
widget_destroy(color->widget);
|
||||
|
||||
if (color->parent_widget)
|
||||
widget_destroy(color->parent_widget);
|
||||
|
||||
if (color->window)
|
||||
window_destroy(color->window);
|
||||
|
||||
if (color->display)
|
||||
display_destroy(color->display);
|
||||
|
||||
free(color);
|
||||
}
|
||||
|
||||
static void
|
||||
resize_handler(struct widget *parent_widget, int32_t width, int32_t height, void *data)
|
||||
{
|
||||
struct color *color = data;
|
||||
struct rectangle allocation;
|
||||
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
||||
struct wl_subsurface *subsurface = widget_get_wl_subsurface(color->widget);
|
||||
|
||||
widget_get_allocation(parent_widget, &allocation);
|
||||
wl_subsurface_set_position(subsurface, allocation.x, allocation.y);
|
||||
|
||||
wp_viewport_set_destination(color->viewport, width, height);
|
||||
|
||||
wl_surface_commit(surface);
|
||||
}
|
||||
|
||||
static void
|
||||
set_empty_input_region(struct color *color, struct widget *widget)
|
||||
{
|
||||
struct wl_region *region;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_surface *surface = widget_get_wl_surface(widget);
|
||||
|
||||
compositor = display_get_compositor(color->display);
|
||||
region = wl_compositor_create_region(compositor);
|
||||
wl_surface_set_input_region(surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
wl_buffer_destroy(buffer);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
||||
static void
|
||||
set_single_pixel(struct color *color, struct widget *widget)
|
||||
{
|
||||
struct wl_surface *surface = widget_get_wl_surface(widget);
|
||||
struct wl_buffer *buffer =
|
||||
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(color->single_pixel_manager,
|
||||
color->pixel_color.r,
|
||||
color->pixel_color.g,
|
||||
color->pixel_color.b,
|
||||
color->pixel_color.a);
|
||||
wl_buffer_add_listener(buffer, &buffer_listener, NULL);
|
||||
wl_surface_attach(surface, buffer, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
image_description_failed(void *data,
|
||||
struct wp_image_description_v1 *wp_image_description_v1,
|
||||
uint32_t cause, const char *msg)
|
||||
{
|
||||
enum image_description_status *image_desc_status = data;
|
||||
|
||||
fprintf(stderr, "Failed to create image description: %u - %s\n",
|
||||
cause, msg);
|
||||
|
||||
*image_desc_status = IMAGE_DESCRIPTION_FAILED;
|
||||
}
|
||||
|
||||
static void
|
||||
image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
|
||||
uint32_t identity)
|
||||
{
|
||||
enum image_description_status *image_desc_status = data;
|
||||
|
||||
*image_desc_status = IMAGE_DESCRIPTION_READY;
|
||||
}
|
||||
|
||||
static const struct wp_image_description_v1_listener image_description_listener = {
|
||||
image_description_failed,
|
||||
image_description_ready,
|
||||
};
|
||||
|
||||
static struct wp_image_description_v1 *
|
||||
create_image_description(struct color *color, uint32_t primaries_named, uint32_t tf_named)
|
||||
{
|
||||
struct wp_image_description_creator_params_v1 *params_creator;
|
||||
struct wp_image_description_v1 *image_description;
|
||||
enum image_description_status image_desc_status = IMAGE_DESCRIPTION_NOT_CREATED;
|
||||
int ret = 0;
|
||||
|
||||
params_creator = wp_color_manager_v1_create_parametric_creator(color->color_manager);
|
||||
wp_image_description_creator_params_v1_set_primaries_named(params_creator, primaries_named);
|
||||
wp_image_description_creator_params_v1_set_tf_named(params_creator, tf_named);
|
||||
if (color->min_lum != -1 && color->max_lum != -1 && color->ref_lum != -1)
|
||||
wp_image_description_creator_params_v1_set_luminances(params_creator,
|
||||
color->min_lum * 10000,
|
||||
color->max_lum,
|
||||
color->ref_lum);
|
||||
|
||||
image_description = wp_image_description_creator_params_v1_create(params_creator);
|
||||
wp_image_description_v1_add_listener(image_description,
|
||||
&image_description_listener,
|
||||
&image_desc_status);
|
||||
|
||||
while (ret != -1 && image_desc_status == IMAGE_DESCRIPTION_NOT_CREATED)
|
||||
ret = wl_display_dispatch(display_get_display(color->display));
|
||||
if (ret == -1) {
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
fprintf(stderr, "Error when creating the image description: %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (image_desc_status == IMAGE_DESCRIPTION_FAILED) {
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(image_desc_status == IMAGE_DESCRIPTION_READY);
|
||||
|
||||
return image_description;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_image_description(struct color *color, struct widget *widget)
|
||||
{
|
||||
struct wp_image_description_v1 *image_description;
|
||||
|
||||
image_description =
|
||||
create_image_description(color,
|
||||
color->primaries,
|
||||
color->transfer_function);
|
||||
if (!image_description)
|
||||
return false;
|
||||
|
||||
wp_color_management_surface_v1_set_image_description(
|
||||
color->color_surface,
|
||||
image_description,
|
||||
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
||||
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct color *color;
|
||||
|
||||
if (parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv) > 1)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
|
||||
if (opt_help)
|
||||
usage(argv[0], EXIT_SUCCESS);
|
||||
|
||||
color = xzalloc(sizeof *color);
|
||||
if (!validate_options(color)) {
|
||||
color_destroy(color);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
color->display = display_create(&argc, argv);
|
||||
if (!color->display) {
|
||||
color_destroy(color);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
color->window = window_create(color->display);
|
||||
color->parent_widget = window_frame_create(color->window, color);
|
||||
color->widget = window_add_subsurface(color->window, color, SUBSURFACE_SYNCHRONIZED);
|
||||
|
||||
display_set_user_data(color->display, color);
|
||||
display_set_global_handler(color->display, global_handler);
|
||||
wl_display_roundtrip(display_get_display(color->display));
|
||||
|
||||
if (!check_color_requirements(color)) {
|
||||
color_destroy(color);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
window_unset_shadow(color->window);
|
||||
window_set_title(color->window, "Color");
|
||||
window_set_appid(color->window, "org.freedesktop.weston.color");
|
||||
/* The first resize call sets the min size,
|
||||
* setting 0, 0 sets a default size */
|
||||
window_schedule_resize(color->window, 0, 0);
|
||||
window_schedule_resize(color->window, opt_width, opt_height);
|
||||
|
||||
widget_set_resize_handler(color->parent_widget, resize_handler);
|
||||
widget_set_use_cairo(color->widget, 0);
|
||||
|
||||
set_empty_input_region(color, color->widget);
|
||||
set_single_pixel(color, color->widget);
|
||||
|
||||
if (set_image_description(color, color->widget))
|
||||
display_run(color->display);
|
||||
|
||||
color_destroy(color);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
@ -163,21 +161,6 @@ simple_clients = [
|
|||
],
|
||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
||||
},
|
||||
{
|
||||
'name': 'timing',
|
||||
'sources': [
|
||||
'simple-timing.c',
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
commit_timing_v1_client_protocol_h,
|
||||
commit_timing_v1_protocol_c,
|
||||
fifo_v1_client_protocol_h,
|
||||
fifo_v1_protocol_c,
|
||||
presentation_time_client_protocol_h,
|
||||
presentation_time_protocol_c,
|
||||
],
|
||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
||||
},
|
||||
{
|
||||
'name': 'touch',
|
||||
'sources': [
|
||||
|
|
@ -189,89 +172,6 @@ simple_clients = [
|
|||
},
|
||||
]
|
||||
|
||||
if dep_vulkan.found() and prog_glslang.found()
|
||||
srcs_simple_vulkan_shaders = [
|
||||
'simple_vulkan_vertex_shader.vert',
|
||||
'simple_vulkan_fragment_shader.frag',
|
||||
]
|
||||
|
||||
simple_vulkan_shaders = []
|
||||
foreach s : srcs_simple_vulkan_shaders
|
||||
simple_vulkan_shaders += custom_target(s + '.spv.h',
|
||||
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
||||
input: s,
|
||||
output: '@BASENAME@.spv.h',
|
||||
)
|
||||
endforeach
|
||||
|
||||
simple_clients += {
|
||||
'name': 'vulkan',
|
||||
'sources': [
|
||||
'simple-vulkan.c',
|
||||
simple_vulkan_shaders,
|
||||
fractional_scale_v1_client_protocol_h,
|
||||
fractional_scale_v1_protocol_c,
|
||||
tearing_control_v1_client_protocol_h,
|
||||
tearing_control_v1_protocol_c,
|
||||
viewporter_client_protocol_h,
|
||||
viewporter_protocol_c,
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
],
|
||||
'dep_objs': [
|
||||
dep_vulkan,
|
||||
dep_libm,
|
||||
dep_libshared,
|
||||
dep_matrix_c,
|
||||
dep_wayland_client,
|
||||
],
|
||||
'deps': [ 'vulkan', 'wayland-cursor' ],
|
||||
'options': [ 'renderer-gl' ]
|
||||
}
|
||||
|
||||
srcs_simple_dmabuf_vulkan_shaders = [
|
||||
'simple_dmabuf_vulkan_vertex_shader.vert',
|
||||
'simple_dmabuf_vulkan_fragment_shader.frag',
|
||||
]
|
||||
|
||||
simple_dmabuf_vulkan_shaders = []
|
||||
foreach s : srcs_simple_dmabuf_vulkan_shaders
|
||||
simple_dmabuf_vulkan_shaders += custom_target(s + '.spv.h',
|
||||
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
||||
input: s,
|
||||
output: '@BASENAME@.spv.h',
|
||||
)
|
||||
endforeach
|
||||
|
||||
simple_clients += {
|
||||
'name': 'dmabuf-vulkan',
|
||||
'sources': [
|
||||
'simple-dmabuf-vulkan.c',
|
||||
simple_dmabuf_vulkan_shaders,
|
||||
linux_dmabuf_unstable_v1_client_protocol_h,
|
||||
linux_dmabuf_unstable_v1_protocol_c,
|
||||
linux_explicit_synchronization_unstable_v1_client_protocol_h,
|
||||
linux_explicit_synchronization_unstable_v1_protocol_c,
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
weston_direct_display_client_protocol_h,
|
||||
weston_direct_display_protocol_c,
|
||||
],
|
||||
'dep_objs': [
|
||||
dep_vulkan,
|
||||
dep_libdrm_headers,
|
||||
dep_libm,
|
||||
dep_libdrm,
|
||||
dep_libshared,
|
||||
dep_matrix_c,
|
||||
dep_wayland_client,
|
||||
dep_libweston_private, # for pixel-formats.h
|
||||
],
|
||||
'deps': [ 'vulkan', 'wayland-cursor', 'gbm' ],
|
||||
'options': [ 'renderer-gl' ]
|
||||
}
|
||||
endif
|
||||
|
||||
foreach t : simple_clients
|
||||
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
|
||||
t_name = 'weston-simple-' + t.get('name')
|
||||
|
|
@ -369,15 +269,6 @@ demo_clients = [
|
|||
'basename': 'cliptest',
|
||||
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
|
||||
},
|
||||
{
|
||||
'basename': 'color',
|
||||
'add_sources': [
|
||||
color_management_v1_client_protocol_h,
|
||||
color_management_v1_protocol_c,
|
||||
single_pixel_buffer_v1_client_protocol_h,
|
||||
single_pixel_buffer_v1_protocol_c,
|
||||
],
|
||||
},
|
||||
{
|
||||
'basename': 'constraints',
|
||||
'add_sources': [
|
||||
|
|
@ -500,7 +391,7 @@ if get_option('shell-desktop')
|
|||
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
|
||||
endif
|
||||
|
||||
if get_option('shell-desktop') or get_option('deprecated-shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
|
||||
if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
|
||||
exe_shooter = executable(
|
||||
'weston-screenshooter',
|
||||
'screenshot.c',
|
||||
|
|
@ -508,7 +399,6 @@ if get_option('shell-desktop') or get_option('deprecated-shell-fullscreen') or g
|
|||
weston_output_capture_protocol_c,
|
||||
include_directories: common_inc,
|
||||
dependencies: [
|
||||
dep_client_buffer,
|
||||
dep_toytoolkit,
|
||||
dep_libweston_private, # for pixel-formats.h
|
||||
dep_pixman,
|
||||
|
|
|
|||
|
|
@ -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,182 +382,41 @@ screenshot_set_buffer_size(struct buffer_size *buff_size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
received_formats_for_all_outputs(struct screenshooter_app *app)
|
||||
{
|
||||
struct screenshooter_output *output;
|
||||
|
||||
wl_list_for_each(output, &app->output_list, link) {
|
||||
if (!output->formats_done)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
all_output_formats_are_yuv(struct wl_list *output_list)
|
||||
{
|
||||
struct screenshooter_output *output;
|
||||
int color_model = -1;
|
||||
|
||||
wl_list_for_each(output, output_list, link) {
|
||||
if (color_model == -1) {
|
||||
color_model = output->buffer->buf->fmt->color_model;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)output->buffer->buf->fmt->color_model != color_model) {
|
||||
fprintf(stderr, "Mixing of RGB and YUV output formats not supported\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
assert(color_model == (int)COLOR_MODEL_RGB ||
|
||||
color_model == (int)COLOR_MODEL_YUV);
|
||||
return color_model == COLOR_MODEL_YUV;
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage_and_exit(void)
|
||||
{
|
||||
printf("usage flags:\n"
|
||||
"\t'-h,--help'"
|
||||
"\n\t\tprint this help output\n"
|
||||
"\t'-v,--verbose'"
|
||||
"\n\t\tprint additional output\n"
|
||||
"\t'-f,--format=<>'"
|
||||
"\n\t\tthe DRM format name to use without the DRM_FORMAT_ prefix, e.g. RGBA8888 or NV12\n"
|
||||
"\n\t\tIn case of YCbCr formats like NV12, instead of a single .png, the output will consist of raw .yuv files for each output."
|
||||
"\n\t\tThese files do not contain any metadata, however that can be added by converting to .y4m with a command like:"
|
||||
"\n\t\tffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m\n"
|
||||
"\n\t\tNote that this may not work for all YCbCr pixel formats.\n"
|
||||
"\t'-s,--source-type=<>'"
|
||||
"\n\t\tframebuffer to use framebuffer source (default), "
|
||||
"\n\t\twriteback to use writeback source\n"
|
||||
"\t'-b,--buffer-type=<>'"
|
||||
"\n\t\tshm to use a SHM buffer (default), "
|
||||
"\n\t\tdmabuf to use a DMA buffer\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static const struct weston_enum_map source_types [] = {
|
||||
{ "framebuffer", WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER },
|
||||
{ "writeback", WESTON_CAPTURE_V1_SOURCE_WRITEBACK },
|
||||
};
|
||||
|
||||
static const struct weston_enum_map buffer_types [] = {
|
||||
{ "shm", CLIENT_BUFFER_TYPE_SHM },
|
||||
{ "dmabuf", CLIENT_BUFFER_TYPE_DMABUF },
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct screenshooter_output *output;
|
||||
struct screenshooter_output *tmp_output;
|
||||
struct buffer_size buff_size = {};
|
||||
struct screenshooter_app app = {};
|
||||
int c, option_index;
|
||||
|
||||
app.src_type = WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER;
|
||||
app.buffer_type = CLIENT_BUFFER_TYPE_SHM;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{"format", required_argument, NULL, 'f'},
|
||||
{"source-type", required_argument, NULL, 's'},
|
||||
{"buffer-type", required_argument, NULL, 'b'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hvf:s:b:",
|
||||
long_options, &option_index)) != -1) {
|
||||
const struct weston_enum_map *entry;
|
||||
|
||||
switch(c) {
|
||||
case 'v':
|
||||
app.verbose = true;
|
||||
break;
|
||||
case 'f':
|
||||
app.requested_format = pixel_format_get_info_by_drm_name(optarg);
|
||||
if (!app.requested_format) {
|
||||
fprintf(stderr, "Unknown format %s\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
entry = weston_enum_map_find_name(source_types,
|
||||
optarg);
|
||||
if (!entry)
|
||||
print_usage_and_exit();
|
||||
|
||||
app.src_type = entry->value;
|
||||
break;
|
||||
case 'b':
|
||||
entry = weston_enum_map_find_name(buffer_types,
|
||||
optarg);
|
||||
if (!entry)
|
||||
print_usage_and_exit();
|
||||
|
||||
app.buffer_type = entry->value;
|
||||
break;
|
||||
default:
|
||||
print_usage_and_exit();
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_init(&app.output_list);
|
||||
|
||||
app.display = wl_display_connect(NULL);
|
||||
if (app.display == NULL) {
|
||||
display = wl_display_connect(NULL);
|
||||
if (display == NULL) {
|
||||
fprintf(stderr, "failed to create display: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
app.registry = wl_display_get_registry(app.display);
|
||||
app.registry = wl_display_get_registry(display);
|
||||
wl_registry_add_listener(app.registry, ®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.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER &&
|
||||
app.buffer_type != CLIENT_BUFFER_TYPE_SHM) {
|
||||
fprintf(stderr, "Error: Only support shm buffer with framebuffer source\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(app.buffer_type == CLIENT_BUFFER_TYPE_SHM && !app.shm) {
|
||||
fprintf(stderr, "Error: display does not support wl_shm\n");
|
||||
return -1;
|
||||
}
|
||||
if (app.buffer_type == CLIENT_BUFFER_TYPE_DMABUF && !app.dmabuf) {
|
||||
fprintf(stderr, "Error: Compositor does not support zwp_linux_dmabuf_v1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (app.verbose) {
|
||||
printf("Taking screenshot with %s source %s buffer\n",
|
||||
(app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER) ? "framebuffer" : "writeback",
|
||||
(app.buffer_type == CLIENT_BUFFER_TYPE_SHM) ? "shm" : "dma");
|
||||
}
|
||||
|
||||
/* Process initial events for wl_output and weston_capture_source_v1 */
|
||||
wl_display_roundtrip(app.display);
|
||||
|
||||
while (!received_formats_for_all_outputs(&app)) {
|
||||
if (app.verbose)
|
||||
printf("Waiting for compositor to send capture source data\n");
|
||||
|
||||
if (wl_display_dispatch(app.display) < 0) {
|
||||
fprintf(stderr, "Error: connection terminated\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wl_display_roundtrip(display);
|
||||
|
||||
do {
|
||||
app.retry = false;
|
||||
|
|
@ -712,7 +425,7 @@ main(int argc, char *argv[])
|
|||
screenshooter_output_capture(output);
|
||||
|
||||
while (app.waitcount > 0 && !app.failed) {
|
||||
if (wl_display_dispatch(app.display) < 0)
|
||||
if (wl_display_dispatch(display) < 0)
|
||||
app.failed = true;
|
||||
assert(app.waitcount >= 0);
|
||||
}
|
||||
|
|
@ -721,11 +434,7 @@ main(int argc, char *argv[])
|
|||
if (!app.failed) {
|
||||
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
|
||||
return -1;
|
||||
|
||||
if (all_output_formats_are_yuv(&app.output_list))
|
||||
screenshot_write_yuv(&buff_size, &app.output_list);
|
||||
else
|
||||
screenshot_write_png(&buff_size, &app.output_list);
|
||||
screenshot_write_png(&buff_size, &app.output_list);
|
||||
} else {
|
||||
fprintf(stderr, "Error: screenshot or protocol failure\n");
|
||||
}
|
||||
|
|
@ -735,10 +444,8 @@ main(int argc, char *argv[])
|
|||
|
||||
weston_capture_v1_destroy(app.capture_factory);
|
||||
wl_shm_destroy(app.shm);
|
||||
if (app.dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(app.dmabuf);
|
||||
wl_registry_destroy(app.registry);
|
||||
wl_display_disconnect(app.display);
|
||||
wl_display_disconnect(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ render(struct window *window, struct buffer *buffer)
|
|||
|
||||
glUniform1f(window->gl.offset_uniform, offset);
|
||||
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
||||
(GLfloat *) reflection.M.colmaj);
|
||||
(GLfloat *) reflection.d);
|
||||
|
||||
glClearColor(0.0,0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
@ -864,7 +864,7 @@ render_mandelbrot(struct window *window, struct buffer *buffer)
|
|||
|
||||
glUniform1f(window->gl.offset_uniform, offset);
|
||||
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
||||
(GLfloat *) reflection.M.colmaj);
|
||||
(GLfloat *) reflection.d);
|
||||
|
||||
glClearColor(0.6, 0.6, 0.6, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
@ -1110,12 +1110,6 @@ destroy_display(struct display *display)
|
|||
|
||||
free(display->modifiers);
|
||||
|
||||
if (display->direct_display)
|
||||
weston_direct_display_v1_destroy(display->direct_display);
|
||||
|
||||
if (display->explicit_sync)
|
||||
zwp_linux_explicit_synchronization_v1_destroy(display->explicit_sync);
|
||||
|
||||
if (display->dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(display->dmabuf);
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,885 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2011 Benjamin Franzke
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "shared/os-compatibility.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/zalloc.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#include "commit-timing-v1-client-protocol.h"
|
||||
#include "fifo-v1-client-protocol.h"
|
||||
#include "presentation-time-client-protocol.h"
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define MAX_BUFFER_ALLOC 1000
|
||||
|
||||
struct display {
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct xdg_wm_base *wm_base;
|
||||
struct wl_seat *seat;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct wl_shm *shm;
|
||||
struct wp_commit_timing_manager_v1 *commit_timing_manager;
|
||||
struct wp_fifo_manager_v1 *fifo_manager;
|
||||
struct wp_presentation *presentation;
|
||||
bool have_clock_id;
|
||||
clockid_t presentation_clock_id;
|
||||
int64_t first_frame_time;
|
||||
int64_t refresh_nsec;
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
struct window *window;
|
||||
struct wl_buffer *buffer;
|
||||
void *shm_data;
|
||||
int busy;
|
||||
int width, height;
|
||||
size_t size; /* width * 4 * height */
|
||||
struct wl_list buffer_link; /** window::buffer_list */
|
||||
};
|
||||
|
||||
struct window {
|
||||
struct display *display;
|
||||
int width, height;
|
||||
int init_width, init_height;
|
||||
struct wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct wl_list buffer_list;
|
||||
struct wl_callback *callback;
|
||||
struct wp_fifo_v1 *fifo;
|
||||
struct wp_commit_timer_v1 *commit_timer;
|
||||
bool wait_for_configure;
|
||||
bool maximized;
|
||||
bool fullscreen;
|
||||
bool needs_update_buffer;
|
||||
};
|
||||
|
||||
struct feedback {
|
||||
struct wp_presentation_feedback *fb;
|
||||
struct window *window;
|
||||
int64_t target_time;
|
||||
bool final;
|
||||
};
|
||||
|
||||
static int running = 1;
|
||||
|
||||
static void
|
||||
draw_for_time(void *data, int64_t time, bool wait_fifo);
|
||||
|
||||
static void
|
||||
finish_run(struct window *window);
|
||||
|
||||
static struct buffer *
|
||||
alloc_buffer(struct window *window, int width, int height)
|
||||
{
|
||||
struct buffer *buffer = calloc(1, sizeof(*buffer));
|
||||
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_buffer(struct buffer *buffer)
|
||||
{
|
||||
if (buffer->buffer)
|
||||
wl_buffer_destroy(buffer->buffer);
|
||||
|
||||
munmap(buffer->shm_data, buffer->size);
|
||||
wl_list_remove(&buffer->buffer_link);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static struct buffer *
|
||||
pick_free_buffer(struct window *window)
|
||||
{
|
||||
struct buffer *b;
|
||||
struct buffer *buffer = NULL;
|
||||
|
||||
wl_list_for_each(b, &window->buffer_list, buffer_link) {
|
||||
if (!b->busy) {
|
||||
buffer = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
prune_old_released_buffers(struct window *window)
|
||||
{
|
||||
struct buffer *b, *b_next;
|
||||
|
||||
wl_list_for_each_safe(b, b_next,
|
||||
&window->buffer_list, buffer_link) {
|
||||
if (!b->busy && (b->width != window->width ||
|
||||
b->height != window->height))
|
||||
destroy_buffer(b);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
struct buffer *mybuf = data;
|
||||
|
||||
mybuf->busy = 0;
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
||||
static int
|
||||
create_shm_buffer(struct window *window, struct buffer *buffer)
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
int fd, size, stride;
|
||||
void *data;
|
||||
int width, height;
|
||||
struct display *display;
|
||||
|
||||
width = window->width;
|
||||
height = window->height;
|
||||
stride = width * 4;
|
||||
size = stride * height;
|
||||
display = window->display;
|
||||
|
||||
fd = os_create_anonymous_file(size);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
||||
size, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pool = wl_shm_create_pool(display->shm, fd, size);
|
||||
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
||||
width, height,
|
||||
stride,
|
||||
WL_SHM_FORMAT_XRGB8888);
|
||||
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
||||
wl_shm_pool_destroy(pool);
|
||||
close(fd);
|
||||
|
||||
buffer->size = size;
|
||||
buffer->shm_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t format, int fd, uint32_t size)
|
||||
{
|
||||
/* Just so we 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->callback = NULL;
|
||||
window->display = display;
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
window->init_width = width;
|
||||
window->init_height = height;
|
||||
window->surface = wl_compositor_create_surface(display->compositor);
|
||||
window->fifo = wp_fifo_manager_v1_get_fifo(display->fifo_manager,
|
||||
window->surface);
|
||||
window->commit_timer = wp_commit_timing_manager_v1_get_timer(display->commit_timing_manager,
|
||||
window->surface);
|
||||
window->needs_update_buffer = false;
|
||||
wl_list_init(&window->buffer_list);
|
||||
|
||||
assert(display->wm_base);
|
||||
|
||||
window->xdg_surface =
|
||||
xdg_wm_base_get_xdg_surface(display->wm_base,
|
||||
window->surface);
|
||||
assert(window->xdg_surface);
|
||||
xdg_surface_add_listener(window->xdg_surface,
|
||||
&xdg_surface_listener, window);
|
||||
|
||||
window->xdg_toplevel =
|
||||
xdg_surface_get_toplevel(window->xdg_surface);
|
||||
assert(window->xdg_toplevel);
|
||||
xdg_toplevel_add_listener(window->xdg_toplevel,
|
||||
&xdg_toplevel_listener, window);
|
||||
|
||||
xdg_toplevel_set_title(window->xdg_toplevel, "simple-shm");
|
||||
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
||||
"org.freedesktop.weston.simple-shm");
|
||||
|
||||
wl_surface_commit(window->surface);
|
||||
window->wait_for_configure = true;
|
||||
|
||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
||||
alloc_buffer(window, window->width, window->height);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_window(struct window *window)
|
||||
{
|
||||
struct buffer *buffer, *buffer_next;
|
||||
|
||||
if (window->callback)
|
||||
wl_callback_destroy(window->callback);
|
||||
|
||||
wl_list_for_each_safe(buffer, buffer_next,
|
||||
&window->buffer_list, buffer_link)
|
||||
destroy_buffer(buffer);
|
||||
|
||||
if (window->xdg_toplevel)
|
||||
xdg_toplevel_destroy(window->xdg_toplevel);
|
||||
if (window->xdg_surface)
|
||||
xdg_surface_destroy(window->xdg_surface);
|
||||
wl_surface_destroy(window->surface);
|
||||
|
||||
if (window->fifo)
|
||||
wp_fifo_v1_destroy(window->fifo);
|
||||
|
||||
if (window->commit_timer)
|
||||
wp_commit_timer_v1_destroy(window->commit_timer);
|
||||
|
||||
free(window);
|
||||
}
|
||||
|
||||
static struct buffer *
|
||||
window_next_buffer(struct window *window)
|
||||
{
|
||||
struct buffer *buffer = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (window->needs_update_buffer) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
||||
alloc_buffer(window, window->width, window->height);
|
||||
|
||||
window->needs_update_buffer = false;
|
||||
}
|
||||
|
||||
buffer = pick_free_buffer(window);
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
if (!buffer->buffer) {
|
||||
ret = create_shm_buffer(window, buffer);
|
||||
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
/* paint the padding */
|
||||
memset(buffer->shm_data, 0xff,
|
||||
window->width * window->height * 4);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
paint_pixels(void *image, int width, int height, uint32_t time)
|
||||
{
|
||||
const int halfh = height / 2;
|
||||
const int halfw = width / 2;
|
||||
int ir, or;
|
||||
uint32_t *pixel = image;
|
||||
int y;
|
||||
|
||||
/* squared radii thresholds */
|
||||
or = (halfw < halfh ? halfw : halfh) - 8;
|
||||
ir = or - 32;
|
||||
or *= or;
|
||||
ir *= ir;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
int x;
|
||||
int y2 = (y - halfh) * (y - halfh);
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
uint32_t v;
|
||||
|
||||
/* squared distance from center */
|
||||
int r2 = (x - halfw) * (x - halfw) + y2;
|
||||
|
||||
if (r2 < ir)
|
||||
v = (r2 / 32 + time / 64) * 0x0080401;
|
||||
else if (r2 < or)
|
||||
v = (y + time / 32) * 0x0080401;
|
||||
else
|
||||
v = (x + time / 16) * 0x0080401;
|
||||
v &= 0x00ffffff;
|
||||
|
||||
/* cross if compositor uses X from XRGB as alpha */
|
||||
if (abs(x - y) > 6 && abs(x + y - height) > 6)
|
||||
v |= 0xff000000;
|
||||
|
||||
*pixel++ = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
queue_some_frames(struct window *window)
|
||||
{
|
||||
struct display *display = window->display;
|
||||
int64_t target_nsec;
|
||||
int i;
|
||||
|
||||
assert(display->first_frame_time);
|
||||
|
||||
/* Round off error will cause us problems if we don't
|
||||
* reduce this a bit, because we could end up rounding
|
||||
* to either side of a refresh.
|
||||
*/
|
||||
target_nsec = display->first_frame_time - 100000;
|
||||
|
||||
for (i = 0; i < 60; i++) {
|
||||
target_nsec += display->refresh_nsec * 2;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
target_nsec += display->refresh_nsec * 4;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
target_nsec += display->refresh_nsec * 10;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
target_nsec += display->refresh_nsec * 100;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
finish_run(window);
|
||||
}
|
||||
|
||||
static void
|
||||
feedback_sync_output(void *data,
|
||||
struct wp_presentation_feedback *presentation_feedback,
|
||||
struct wl_output *output)
|
||||
{
|
||||
/* Just don't care */
|
||||
}
|
||||
|
||||
static void
|
||||
feedback_presented(void *data,
|
||||
struct wp_presentation_feedback *presentation_feedback,
|
||||
uint32_t tv_sec_hi,
|
||||
uint32_t tv_sec_lo,
|
||||
uint32_t tv_nsec,
|
||||
uint32_t refresh_nsec,
|
||||
uint32_t seq_hi,
|
||||
uint32_t seq_lo,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct feedback *feedback = data;
|
||||
struct window *window = feedback->window;
|
||||
struct display *display = window->display;
|
||||
struct timespec pres_ts = {
|
||||
.tv_sec = ((int64_t)tv_sec_hi << 32) + tv_sec_lo,
|
||||
.tv_nsec = tv_nsec,
|
||||
};
|
||||
int64_t ntime = timespec_to_nsec(&pres_ts);
|
||||
double delay;
|
||||
|
||||
if (feedback->final) {
|
||||
running = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!feedback->target_time) {
|
||||
display->first_frame_time = ntime;
|
||||
display->refresh_nsec = refresh_nsec;
|
||||
queue_some_frames(window);
|
||||
goto out;
|
||||
}
|
||||
|
||||
delay = (ntime - feedback->target_time) / 1000000.0;
|
||||
|
||||
printf("%fms away from intended time\n", delay);
|
||||
if (fabs(delay) > display->refresh_nsec / 1000000)
|
||||
printf("Warning: we missed the intended target display cycle.\n");
|
||||
|
||||
out:
|
||||
wp_presentation_feedback_destroy(feedback->fb);
|
||||
free(feedback);
|
||||
}
|
||||
|
||||
static void
|
||||
feedback_discarded(void *data,
|
||||
struct wp_presentation_feedback *presentation_feedback)
|
||||
{
|
||||
struct feedback *feedback = data;
|
||||
|
||||
printf("Warning: a frame was discarded\n");
|
||||
|
||||
if (feedback->final)
|
||||
running = 0;
|
||||
|
||||
wp_presentation_feedback_destroy(feedback->fb);
|
||||
free(feedback);
|
||||
}
|
||||
|
||||
static const struct wp_presentation_feedback_listener feedback_listener = {
|
||||
feedback_sync_output,
|
||||
feedback_presented,
|
||||
feedback_discarded,
|
||||
};
|
||||
|
||||
static void
|
||||
finish_run(struct window *window)
|
||||
{
|
||||
struct display *display = window->display;
|
||||
struct feedback *feedback;
|
||||
struct buffer *buffer;
|
||||
|
||||
feedback = xzalloc(sizeof *feedback);
|
||||
feedback->window = window;
|
||||
feedback->final = true;
|
||||
feedback->target_time = 0;
|
||||
|
||||
buffer = window_next_buffer(window);
|
||||
assert(buffer);
|
||||
|
||||
paint_pixels(buffer->shm_data, window->width,
|
||||
window->height, 1);
|
||||
|
||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||
|
||||
feedback->fb = wp_presentation_feedback(display->presentation,
|
||||
window->surface);
|
||||
wp_presentation_feedback_add_listener(feedback->fb,
|
||||
&feedback_listener, feedback);
|
||||
|
||||
wp_fifo_v1_wait_barrier(window->fifo);
|
||||
wl_surface_commit(window->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_for_time(void *data, int64_t time, bool wait_fifo)
|
||||
{
|
||||
struct window *window = data;
|
||||
struct display *display = window->display;
|
||||
struct buffer *buffer;
|
||||
struct feedback *feedback;
|
||||
|
||||
assert(display->have_clock_id);
|
||||
|
||||
prune_old_released_buffers(window);
|
||||
|
||||
buffer = window_next_buffer(window);
|
||||
assert(buffer);
|
||||
|
||||
paint_pixels(buffer->shm_data, window->width,
|
||||
window->height, time / 1000000);
|
||||
|
||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||
|
||||
feedback = xzalloc(sizeof *feedback);
|
||||
feedback->window = window;
|
||||
|
||||
feedback->fb = wp_presentation_feedback(display->presentation,
|
||||
window->surface);
|
||||
wp_presentation_feedback_add_listener(feedback->fb,
|
||||
&feedback_listener, feedback);
|
||||
|
||||
feedback->target_time = time;
|
||||
if (time) {
|
||||
struct timespec target;
|
||||
|
||||
timespec_from_nsec(&target, time);
|
||||
wp_commit_timer_v1_set_timestamp(window->commit_timer,
|
||||
(int64_t)target.tv_sec >> 32,
|
||||
target.tv_sec,
|
||||
target.tv_nsec);
|
||||
}
|
||||
wp_fifo_v1_set_barrier(window->fifo);
|
||||
wl_surface_commit(window->surface);
|
||||
buffer->busy = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
||||
{
|
||||
xdg_wm_base_pong(shell, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||
xdg_wm_base_ping,
|
||||
};
|
||||
|
||||
static void
|
||||
presentation_handle_clock_id(void *data,
|
||||
struct wp_presentation *wp_presentation,
|
||||
uint32_t clock_id)
|
||||
{
|
||||
struct display *display = data;
|
||||
|
||||
display->presentation_clock_id = clock_id;
|
||||
display->have_clock_id = true;
|
||||
}
|
||||
|
||||
static const struct wp_presentation_listener presentation_listener = {
|
||||
presentation_handle_clock_id,
|
||||
};
|
||||
|
||||
static void
|
||||
registry_handle_global(void *data, struct wl_registry *registry,
|
||||
uint32_t id, const char *interface, uint32_t version)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
d->compositor =
|
||||
wl_registry_bind(registry,
|
||||
id, &wl_compositor_interface, 1);
|
||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
||||
d->wm_base = wl_registry_bind(registry,
|
||||
id, &xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
|
||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||
d->seat = wl_registry_bind(registry, id,
|
||||
&wl_seat_interface, 1);
|
||||
wl_seat_add_listener(d->seat, &seat_listener, d);
|
||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||
d->shm = wl_registry_bind(registry,
|
||||
id, &wl_shm_interface, 1);
|
||||
} else if (strcmp(interface, wp_commit_timing_manager_v1_interface.name) == 0) {
|
||||
d->commit_timing_manager = wl_registry_bind(registry, id,
|
||||
&wp_commit_timing_manager_v1_interface,
|
||||
1);
|
||||
} else if (strcmp(interface, wp_fifo_manager_v1_interface.name) == 0) {
|
||||
d->fifo_manager = wl_registry_bind(registry, id,
|
||||
&wp_fifo_manager_v1_interface,
|
||||
1);
|
||||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
||||
d->presentation = wl_registry_bind(registry, id,
|
||||
&wp_presentation_interface,
|
||||
2);
|
||||
wp_presentation_add_listener(d->presentation,
|
||||
&presentation_listener, d);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
registry_handle_global_remove(void *data, struct wl_registry *registry,
|
||||
uint32_t name)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_handle_global,
|
||||
registry_handle_global_remove
|
||||
};
|
||||
|
||||
static struct display *
|
||||
create_display(void)
|
||||
{
|
||||
struct display *display;
|
||||
|
||||
display = xzalloc(sizeof *display);
|
||||
|
||||
display->display = wl_display_connect(NULL);
|
||||
assert(display->display);
|
||||
|
||||
display->registry = wl_display_get_registry(display->display);
|
||||
wl_registry_add_listener(display->registry,
|
||||
®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;
|
||||
}
|
||||
|
|
|
|||
178
clients/window.c
178
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
|
||||
|
|
@ -4392,8 +4372,8 @@ undo_resize(struct window *window)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
window_configure_resize(struct window *window, int width, int height)
|
||||
void
|
||||
window_schedule_resize(struct window *window, int width, int height)
|
||||
{
|
||||
/* We should probably get these numbers from the theme. */
|
||||
const int min_width = 200, min_height = 200;
|
||||
|
|
@ -4420,12 +4400,6 @@ window_configure_resize(struct window *window, int width, int height)
|
|||
window->pending_allocation.height = window->min_allocation.height;
|
||||
|
||||
window->resize_needed = 1;
|
||||
}
|
||||
|
||||
void
|
||||
window_schedule_resize(struct window *window, int width, int height)
|
||||
{
|
||||
window_configure_resize(window, width, height);
|
||||
window_schedule_redraw(window);
|
||||
}
|
||||
|
||||
|
|
@ -4514,14 +4488,6 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|||
}
|
||||
}
|
||||
|
||||
/* If the window is being mapped fullscreen,
|
||||
* save the last pending allocation */
|
||||
if (window->fullscreen &&
|
||||
(window->saved_allocation.width == 0 ||
|
||||
window->saved_allocation.height == 0)) {
|
||||
window->saved_allocation = window->pending_allocation;
|
||||
}
|
||||
|
||||
if (window->frame) {
|
||||
if (window->maximized) {
|
||||
frame_set_flag(window->frame->frame, FRAME_FLAG_MAXIMIZED);
|
||||
|
|
@ -4542,14 +4508,14 @@ xdg_toplevel_handle_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
|||
* on the shadow margin to get the difference. */
|
||||
int margin = window_get_shadow_margin(window);
|
||||
|
||||
window_configure_resize(window,
|
||||
width + margin * 2,
|
||||
height + margin * 2);
|
||||
window_schedule_resize(window,
|
||||
width + margin * 2,
|
||||
height + margin * 2);
|
||||
} else if (window->saved_allocation.width > 0 &&
|
||||
window->saved_allocation.height > 0) {
|
||||
window_configure_resize(window,
|
||||
window->saved_allocation.width,
|
||||
window->saved_allocation.height);
|
||||
window_schedule_resize(window,
|
||||
window->saved_allocation.width,
|
||||
window->saved_allocation.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4971,20 +4937,6 @@ window_set_locked_pointer_motion_handler(struct window *window,
|
|||
window->locked_pointer_motion_handler = handler;
|
||||
}
|
||||
|
||||
void
|
||||
window_set_shadow(struct window *window)
|
||||
{
|
||||
if (window->frame)
|
||||
frame_unset_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
|
||||
}
|
||||
|
||||
void
|
||||
window_unset_shadow(struct window *window)
|
||||
{
|
||||
if (window->frame)
|
||||
frame_set_flag(window->frame->frame, FRAME_FLAG_NO_SHADOW);
|
||||
}
|
||||
|
||||
void
|
||||
window_set_title(struct window *window, const char *title)
|
||||
{
|
||||
|
|
@ -6719,7 +6671,7 @@ display_bind_tablets(struct display *d, uint32_t id)
|
|||
}
|
||||
|
||||
static void
|
||||
cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t render_intent)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
|
@ -6728,7 +6680,7 @@ cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
|||
}
|
||||
|
||||
static void
|
||||
cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t feature)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
|
@ -6737,31 +6689,24 @@ cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1
|
|||
}
|
||||
|
||||
static void
|
||||
cm_supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t tf_code)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static void
|
||||
cm_supported_primaries_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t primaries_code)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static void
|
||||
cm_done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static const struct wp_color_manager_v1_listener cm_listener = {
|
||||
static const struct xx_color_manager_v4_listener cm_listener = {
|
||||
.supported_intent = cm_supported_intent,
|
||||
.supported_feature = cm_supported_feature,
|
||||
.supported_tf_named = cm_supported_tf_named,
|
||||
.supported_primaries_named = cm_supported_primaries_named,
|
||||
.done = cm_done,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -6832,17 +6777,12 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
|||
&wp_viewporter_interface, 1);
|
||||
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
||||
display_bind_tablets(d, id);
|
||||
} else if (strcmp(interface, "wp_color_manager_v1") == 0) {
|
||||
} else if (strcmp(interface, "xx_color_manager_v4") == 0) {
|
||||
d->color_manager =
|
||||
wl_registry_bind(registry, id,
|
||||
&wp_color_manager_v1_interface, 1);
|
||||
wp_color_manager_v1_add_listener(d->color_manager,
|
||||
&xx_color_manager_v4_interface, 1);
|
||||
xx_color_manager_v4_add_listener(d->color_manager,
|
||||
&cm_listener, d);
|
||||
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
||||
d->single_pixel_buffer_manager =
|
||||
wl_registry_bind(registry, id,
|
||||
&wp_single_pixel_buffer_manager_v1_interface,
|
||||
1);
|
||||
}
|
||||
|
||||
if (d->global_handler)
|
||||
|
|
@ -7065,7 +7005,7 @@ display_destroy(struct display *display)
|
|||
xdg_wm_base_destroy(display->xdg_shell);
|
||||
|
||||
if (display->color_manager)
|
||||
wp_color_manager_v1_destroy(display->color_manager);
|
||||
xx_color_manager_v4_destroy(display->color_manager);
|
||||
|
||||
if (display->shm)
|
||||
wl_shm_destroy(display->shm);
|
||||
|
|
@ -7131,12 +7071,6 @@ display_get_compositor(struct display *display)
|
|||
return display->compositor;
|
||||
}
|
||||
|
||||
struct wp_single_pixel_buffer_manager_v1 *
|
||||
display_get_single_pixel_buffer_manager(struct display *display)
|
||||
{
|
||||
return display->single_pixel_buffer_manager;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
display_get_serial(struct display *display)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -48,6 +48,168 @@
|
|||
#define DEFAULT_NUM_WORKSPACES 1
|
||||
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
|
||||
|
||||
struct focus_state {
|
||||
struct desktop_shell *shell;
|
||||
struct weston_seat *seat;
|
||||
struct workspace *ws;
|
||||
struct weston_surface *keyboard_focus;
|
||||
struct wl_list link;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
};
|
||||
|
||||
/*
|
||||
* Surface stacking and ordering.
|
||||
*
|
||||
* This is handled using several linked lists of surfaces, organised into
|
||||
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
||||
* above all of the surfaces in the layer below. The set of layers is static and
|
||||
* in the following order (top-most first):
|
||||
* • Lock layer (only ever displayed on its own)
|
||||
* • Cursor layer
|
||||
* • Input panel layer
|
||||
* • Fullscreen layer
|
||||
* • Panel layer
|
||||
* • Workspace layers
|
||||
* • Background layer
|
||||
*
|
||||
* The list of layers may be manipulated to remove whole layers of surfaces from
|
||||
* display. For example, when locking the screen, all layers except the lock
|
||||
* layer are removed.
|
||||
*
|
||||
* A 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);
|
||||
|
|
@ -73,6 +235,20 @@ shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
|
|||
static void
|
||||
get_maximized_size(struct shell_surface *shsurf, int32_t *width, int32_t *height);
|
||||
|
||||
static struct shell_output *
|
||||
find_shell_output_from_weston_output(struct desktop_shell *shell,
|
||||
struct weston_output *output)
|
||||
{
|
||||
struct shell_output *shell_output;
|
||||
|
||||
wl_list_for_each(shell_output, &shell->output_list, link) {
|
||||
if (shell_output->output == output)
|
||||
return shell_output;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
shsurf_is_max_or_fullscreen(struct shell_surface *shsurf)
|
||||
{
|
||||
|
|
@ -93,8 +269,8 @@ set_shsurf_size_maximized_or_fullscreen(struct shell_surface *shsurf,
|
|||
|
||||
if (fullscreen_requested) {
|
||||
if (shsurf->output) {
|
||||
width = shsurf->output->output->width;
|
||||
height = shsurf->output->output->height;
|
||||
width = shsurf->output->width;
|
||||
height = shsurf->output->height;
|
||||
}
|
||||
} else if (max_requested) {
|
||||
/* take the panels into considerations */
|
||||
|
|
@ -193,18 +369,21 @@ shell_grab_start(struct shell_grab *grab,
|
|||
|
||||
void
|
||||
get_output_work_area(struct desktop_shell *shell,
|
||||
struct shell_output *sh_output,
|
||||
struct weston_output *output,
|
||||
pixman_rectangle32_t *area)
|
||||
{
|
||||
struct weston_output *output;
|
||||
struct shell_output *sh_output;
|
||||
|
||||
area->x = 0;
|
||||
area->y = 0;
|
||||
area->width = 0;
|
||||
area->height = 0;
|
||||
|
||||
if (!sh_output)
|
||||
if (!output)
|
||||
return;
|
||||
output = sh_output->output;
|
||||
|
||||
sh_output = find_shell_output_from_weston_output(shell, output);
|
||||
assert(sh_output);
|
||||
|
||||
area->x = output->pos.c.x;
|
||||
area->y = output->pos.c.y;
|
||||
|
|
@ -344,7 +523,6 @@ shell_configuration(struct desktop_shell *shell)
|
|||
struct weston_config *config;
|
||||
char *s, *client;
|
||||
bool allow_zap;
|
||||
bool disallow_output_changed_move;
|
||||
|
||||
config = wet_get_config(shell->compositor);
|
||||
section = weston_config_get_section(config, "shell", NULL, NULL);
|
||||
|
|
@ -357,11 +535,6 @@ shell_configuration(struct desktop_shell *shell)
|
|||
"allow-zap", &allow_zap, true);
|
||||
shell->allow_zap = allow_zap;
|
||||
|
||||
weston_config_section_get_bool(section,
|
||||
"disallow-output-changed-move",
|
||||
&disallow_output_changed_move, false);
|
||||
shell->disallow_output_changed_move = disallow_output_changed_move;
|
||||
|
||||
shell->binding_modifier = weston_config_get_binding_modifier(config, MODIFIER_SUPER);
|
||||
|
||||
weston_config_section_get_string(section, "animation", &s, "none");
|
||||
|
|
@ -888,12 +1061,7 @@ constrain_position(struct weston_move_grab *move)
|
|||
|
||||
if (shsurf->shell->panel_position ==
|
||||
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
|
||||
struct shell_output *shoutput = NULL;
|
||||
|
||||
if (surface->output)
|
||||
shoutput = weston_output_get_shell_private(surface->output);
|
||||
|
||||
get_output_work_area(shsurf->shell, shoutput, &area);
|
||||
get_output_work_area(shsurf->shell, surface->output, &area);
|
||||
geometry =
|
||||
weston_desktop_surface_get_geometry(shsurf->desktop_surface);
|
||||
|
||||
|
|
@ -1534,26 +1702,15 @@ shell_surface_set_output(struct shell_surface *shsurf,
|
|||
{
|
||||
struct weston_surface *es =
|
||||
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||
struct shell_output *shoutput = NULL;
|
||||
|
||||
if (output)
|
||||
shoutput = weston_output_get_shell_private(output);
|
||||
|
||||
/* get the default output, if the client set it as NULL
|
||||
check whether the output is available */
|
||||
if (shoutput)
|
||||
shsurf->output = shoutput;
|
||||
if (output)
|
||||
shsurf->output = output;
|
||||
else if (es->output)
|
||||
shsurf->output = weston_output_get_shell_private(es->output);
|
||||
else {
|
||||
struct shell_output *shoutput = NULL;
|
||||
struct weston_output *w_output;
|
||||
|
||||
w_output = weston_shell_utils_get_default_output(es->compositor);
|
||||
if (w_output)
|
||||
shoutput = weston_output_get_shell_private(w_output);
|
||||
shsurf->output = shoutput;
|
||||
}
|
||||
shsurf->output = es->output;
|
||||
else
|
||||
shsurf->output = weston_shell_utils_get_default_output(es->compositor);
|
||||
|
||||
if (shsurf->output_destroy_listener.notify) {
|
||||
wl_list_remove(&shsurf->output_destroy_listener.link);
|
||||
|
|
@ -1564,7 +1721,7 @@ shell_surface_set_output(struct shell_surface *shsurf,
|
|||
return;
|
||||
|
||||
shsurf->output_destroy_listener.notify = notify_output_destroy;
|
||||
wl_signal_add(&shsurf->output->output->destroy_signal,
|
||||
wl_signal_add(&shsurf->output->destroy_signal,
|
||||
&shsurf->output_destroy_listener);
|
||||
}
|
||||
|
||||
|
|
@ -1710,13 +1867,7 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
|
|||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||
struct weston_compositor *ec = surface->compositor;
|
||||
struct weston_output *output = NULL;
|
||||
|
||||
if (!shsurf->fullscreen_output)
|
||||
return;
|
||||
|
||||
output = shsurf->fullscreen_output->output;
|
||||
|
||||
struct weston_output *output = shsurf->fullscreen_output;
|
||||
struct weston_curtain_params curtain_params = {
|
||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||
.pos = output->pos,
|
||||
|
|
@ -1731,14 +1882,14 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
|
|||
|
||||
weston_view_move_to_layer(shsurf->view,
|
||||
&shsurf->shell->fullscreen_layer.view_list);
|
||||
weston_shell_utils_center_on_output(shsurf->view, output);
|
||||
weston_shell_utils_center_on_output(shsurf->view, shsurf->fullscreen_output);
|
||||
|
||||
if (!shsurf->fullscreen.black_view) {
|
||||
shsurf->fullscreen.black_view =
|
||||
weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||
}
|
||||
weston_view_set_output(shsurf->fullscreen.black_view->view,
|
||||
output);
|
||||
shsurf->fullscreen_output);
|
||||
weston_view_move_to_layer(shsurf->fullscreen.black_view->view,
|
||||
&shsurf->view->layer_link);
|
||||
|
||||
|
|
@ -1904,8 +2055,8 @@ fade_out_done(struct weston_view_animation *animation, void *data)
|
|||
|
||||
if (weston_view_is_mapped(shsurf->wview_anim_fade)) {
|
||||
weston_view_move_to_layer(shsurf->wview_anim_fade, NULL);
|
||||
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
||||
}
|
||||
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
||||
}
|
||||
|
||||
struct shell_surface *
|
||||
|
|
@ -2118,13 +2269,8 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf)
|
|||
shell_surface_update_layer(shsurf);
|
||||
|
||||
if (shsurf->state.maximized) {
|
||||
struct weston_output *w_output = NULL;
|
||||
|
||||
if (shsurf->output)
|
||||
w_output = shsurf->output->output;
|
||||
|
||||
surface->output = w_output;
|
||||
weston_view_set_output(shsurf->view, w_output);
|
||||
surface->output = shsurf->output;
|
||||
weston_view_set_output(shsurf->view, shsurf->output);
|
||||
}
|
||||
|
||||
if (!shell->locked) {
|
||||
|
|
@ -2230,12 +2376,8 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
WESTON_ACTIVATE_FLAG_FULLSCREEN);
|
||||
}
|
||||
} else if (shsurf->state.maximized) {
|
||||
struct weston_output *w_output = NULL;
|
||||
|
||||
set_maximized_position(shell, shsurf);
|
||||
if (surface->output)
|
||||
w_output = shsurf->output->output;
|
||||
surface->output = w_output;
|
||||
surface->output = shsurf->output;
|
||||
} else {
|
||||
struct weston_coord_surface offset = buf_offset;
|
||||
struct weston_coord_global pos;
|
||||
|
|
@ -2635,13 +2777,7 @@ background_committed(struct weston_surface *es,
|
|||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
struct shell_output *sh_output = es->committed_private;
|
||||
struct desktop_shell *shell;
|
||||
|
||||
/* The output was destroyed before the background was committed */
|
||||
if (!sh_output)
|
||||
return;
|
||||
|
||||
shell = sh_output->shell;
|
||||
struct desktop_shell *shell = sh_output->shell;
|
||||
|
||||
if (!weston_surface_has_content(es))
|
||||
return;
|
||||
|
|
@ -2657,7 +2793,6 @@ background_committed(struct weston_surface *es,
|
|||
sh_output->output->pos);
|
||||
weston_view_move_to_layer(sh_output->background_view,
|
||||
&shell->background_layer.view_list);
|
||||
weston_output_set_ready(sh_output->output);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2677,6 +2812,7 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
struct wl_resource *output_resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(surface_resource);
|
||||
struct shell_output *sh_output;
|
||||
|
|
@ -2693,7 +2829,7 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
return;
|
||||
|
||||
surface->output = head->output;
|
||||
sh_output = weston_output_get_shell_private(surface->output);
|
||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
||||
if (sh_output->background_surface) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
|
|
@ -2730,17 +2866,9 @@ panel_committed(struct weston_surface *es,
|
|||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
struct shell_output *sh_output = es->committed_private;
|
||||
struct weston_output *output;
|
||||
struct weston_coord_global pos;
|
||||
struct desktop_shell *shell;
|
||||
|
||||
/* The output was destroyed before the panel was committed */
|
||||
if (!sh_output)
|
||||
return;
|
||||
|
||||
output = sh_output->output;
|
||||
pos = output->pos;
|
||||
shell = sh_output->shell;
|
||||
struct weston_output *output = sh_output->output;
|
||||
struct weston_coord_global pos = output->pos;
|
||||
struct desktop_shell *shell = sh_output->shell;
|
||||
|
||||
if (!weston_surface_has_content(es))
|
||||
return;
|
||||
|
|
@ -2767,14 +2895,13 @@ panel_committed(struct weston_surface *es,
|
|||
weston_surface_map(es);
|
||||
assert(wl_list_empty(&es->views));
|
||||
sh_output->panel_view = weston_view_create(es);
|
||||
|
||||
weston_view_move_to_layer(sh_output->panel_view,
|
||||
&shell->panel_layer.view_list);
|
||||
}
|
||||
|
||||
assert(sh_output->panel_view);
|
||||
pos = weston_coord_global_add(output->pos, sh_output->panel_offset);
|
||||
weston_view_set_position(sh_output->panel_view, pos);
|
||||
weston_view_move_to_layer(sh_output->panel_view,
|
||||
&shell->panel_layer.view_list);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2795,6 +2922,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
struct wl_resource *output_resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(surface_resource);
|
||||
struct shell_output *sh_output;
|
||||
|
|
@ -2811,7 +2939,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
return;
|
||||
|
||||
surface->output = head->output;
|
||||
sh_output = weston_output_get_shell_private(surface->output);
|
||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
||||
|
||||
if (sh_output->panel_surface) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
|
|
@ -3303,6 +3431,7 @@ rotate_grab_motion(struct weston_pointer_grab *grab,
|
|||
}
|
||||
|
||||
weston_view_update_transform(shsurf->view);
|
||||
weston_surface_damage(shsurf->view->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3426,7 +3555,7 @@ rotate_binding(struct weston_pointer *pointer, const struct timespec *time,
|
|||
* the alt-tab switcher, which need to de-promote fullscreen layers. */
|
||||
void
|
||||
lower_fullscreen_layer(struct desktop_shell *shell,
|
||||
struct shell_output *lowering_output)
|
||||
struct weston_output *lowering_output)
|
||||
{
|
||||
struct workspace *ws;
|
||||
struct weston_view *view, *prev;
|
||||
|
|
@ -3846,6 +3975,9 @@ shell_fade_init(struct desktop_shell *shell)
|
|||
if (!shell->fade.curtain)
|
||||
return;
|
||||
|
||||
weston_view_update_transform(shell->fade.curtain->view);
|
||||
weston_surface_damage(shell->fade.curtain->view->surface);
|
||||
|
||||
loop = wl_display_get_event_loop(shell->compositor->wl_display);
|
||||
shell->fade.startup_timer =
|
||||
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
|
||||
|
|
@ -3915,7 +4047,6 @@ weston_view_set_initial_position(struct weston_view *view,
|
|||
int32_t range_x, range_y;
|
||||
int32_t x, y;
|
||||
struct weston_output *output, *target_output = NULL;
|
||||
struct shell_output *shoutput;
|
||||
struct weston_seat *seat;
|
||||
pixman_rectangle32_t area;
|
||||
struct weston_coord_global pos;
|
||||
|
|
@ -3953,9 +4084,7 @@ weston_view_set_initial_position(struct weston_view *view,
|
|||
* If this is negative it means that the surface is bigger than
|
||||
* output.
|
||||
*/
|
||||
assert(target_output);
|
||||
shoutput = weston_output_get_shell_private(target_output);
|
||||
get_output_work_area(shell, shoutput, &area);
|
||||
get_output_work_area(shell, target_output, &area);
|
||||
|
||||
x = area.x;
|
||||
y = area.y;
|
||||
|
|
@ -4337,12 +4466,6 @@ shell_reposition_view_on_output_change(struct weston_view *view)
|
|||
struct shell_surface *shsurf;
|
||||
int visible;
|
||||
|
||||
/* We can't simply reposition popups and such, they must move with
|
||||
* the parent.
|
||||
*/
|
||||
if (view->geometry.parent)
|
||||
return;
|
||||
|
||||
if (wl_list_empty(&ec->output_list))
|
||||
return;
|
||||
|
||||
|
|
@ -4418,18 +4541,12 @@ shell_output_destroy(struct shell_output *shell_output)
|
|||
{
|
||||
struct desktop_shell *shell = shell_output->shell;
|
||||
|
||||
if (!shell->disallow_output_changed_move) {
|
||||
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
|
||||
}
|
||||
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
|
||||
|
||||
if (shell_output->panel_surface) {
|
||||
if (shell_output->panel_surface)
|
||||
wl_list_remove(&shell_output->panel_surface_listener.link);
|
||||
shell_output->panel_surface->committed_private = NULL;
|
||||
}
|
||||
if (shell_output->background_surface) {
|
||||
if (shell_output->background_surface)
|
||||
wl_list_remove(&shell_output->background_surface_listener.link);
|
||||
shell_output->background_surface->committed_private = NULL;
|
||||
}
|
||||
wl_list_remove(&shell_output->destroy_listener.link);
|
||||
wl_list_remove(&shell_output->link);
|
||||
free(shell_output);
|
||||
|
|
@ -4489,7 +4606,7 @@ handle_output_resized(struct wl_listener *listener, void *data)
|
|||
struct desktop_shell *shell =
|
||||
container_of(listener, struct desktop_shell, resized_listener);
|
||||
struct weston_output *output = (struct weston_output *)data;
|
||||
struct shell_output *sh_output = weston_output_get_shell_private(output);
|
||||
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
|
||||
|
||||
handle_output_resized_shsurfs(shell);
|
||||
|
||||
|
|
@ -4507,8 +4624,6 @@ create_shell_output(struct desktop_shell *shell,
|
|||
if (shell_output == NULL)
|
||||
return;
|
||||
|
||||
weston_output_set_shell_private(output, shell_output);
|
||||
|
||||
shell_output->output = output;
|
||||
shell_output->shell = shell;
|
||||
shell_output->destroy_listener.notify = handle_output_destroy;
|
||||
|
|
@ -4516,7 +4631,7 @@ create_shell_output(struct desktop_shell *shell,
|
|||
&shell_output->destroy_listener);
|
||||
wl_list_insert(shell->output_list.prev, &shell_output->link);
|
||||
|
||||
if (!shell->disallow_output_changed_move && wl_list_length(&shell->output_list) == 1)
|
||||
if (wl_list_length(&shell->output_list) == 1)
|
||||
shell_for_each_layer(shell,
|
||||
shell_output_changed_move_layer, NULL);
|
||||
}
|
||||
|
|
@ -4543,12 +4658,6 @@ handle_output_move_layer(struct desktop_shell *shell,
|
|||
if (view->output != output)
|
||||
continue;
|
||||
|
||||
/* We can't simply reposition popups and such, they must move with
|
||||
* the parent.
|
||||
*/
|
||||
if (view->geometry.parent)
|
||||
continue;
|
||||
|
||||
pos = weston_coord_global_add(
|
||||
weston_view_get_pos_offset_global(view),
|
||||
output->move);
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WESTON_DESKTOP_SHELL_H
|
||||
#define WESTON_DESKTOP_SHELL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
|
@ -35,169 +32,6 @@
|
|||
|
||||
#include "weston-desktop-shell-server-protocol.h"
|
||||
|
||||
struct focus_state {
|
||||
struct desktop_shell *shell;
|
||||
struct weston_seat *seat;
|
||||
struct workspace *ws;
|
||||
struct weston_surface *keyboard_focus;
|
||||
struct wl_list link;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
};
|
||||
|
||||
/*
|
||||
* Surface stacking and ordering.
|
||||
*
|
||||
* This is handled using several linked lists of surfaces, organised into
|
||||
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
||||
* above all of the surfaces in the layer below. The set of layers is static and
|
||||
* in the following order (top-most first):
|
||||
* • Lock layer (only ever displayed on its own)
|
||||
* • Cursor layer
|
||||
* • Input panel layer
|
||||
* • Fullscreen layer
|
||||
* • Panel layer
|
||||
* • Workspace layers
|
||||
* • Background layer
|
||||
*
|
||||
* The list of layers may be manipulated to remove whole layers of surfaces from
|
||||
* display. For example, when locking the screen, all layers except the lock
|
||||
* layer are removed.
|
||||
*
|
||||
* A 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 surface_state {
|
||||
bool fullscreen;
|
||||
bool maximized;
|
||||
bool lowered;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
bool is_set;
|
||||
struct weston_coord_global pos;
|
||||
} xwayland;
|
||||
|
||||
int focus_count;
|
||||
|
||||
bool destroying;
|
||||
struct wl_list link; /** desktop_shell::shsurf_list */
|
||||
};
|
||||
|
||||
struct shell_grab {
|
||||
struct weston_pointer_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
};
|
||||
|
||||
struct shell_touch_grab {
|
||||
struct weston_touch_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_touch *touch;
|
||||
};
|
||||
|
||||
struct shell_tablet_tool_grab {
|
||||
struct weston_tablet_tool_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_tablet_tool *tool;
|
||||
};
|
||||
|
||||
struct weston_move_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_coord_global delta;
|
||||
bool client_initiated;
|
||||
};
|
||||
|
||||
struct weston_touch_move_grab {
|
||||
struct shell_touch_grab base;
|
||||
int active;
|
||||
struct weston_coord_global delta;
|
||||
};
|
||||
|
||||
struct weston_tablet_tool_move_grab {
|
||||
struct shell_tablet_tool_grab base;
|
||||
wl_fixed_t dx, dy;
|
||||
};
|
||||
|
||||
struct rotate_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_matrix rotation;
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
} center;
|
||||
};
|
||||
|
||||
struct shell_seat {
|
||||
struct weston_seat *seat;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct weston_surface *focused_surface;
|
||||
|
||||
struct wl_listener caps_changed_listener;
|
||||
struct wl_listener pointer_focus_listener;
|
||||
struct wl_listener keyboard_focus_listener;
|
||||
struct wl_listener tablet_tool_added_listener;
|
||||
|
||||
struct wl_list link; /** shell::seat_list */
|
||||
};
|
||||
|
||||
struct tablet_tool_listener {
|
||||
struct wl_listener base;
|
||||
struct wl_listener removed_listener;
|
||||
};
|
||||
|
||||
enum animation_type {
|
||||
ANIMATION_NONE,
|
||||
|
||||
|
|
@ -306,7 +140,6 @@ struct desktop_shell {
|
|||
} fade;
|
||||
|
||||
bool allow_zap;
|
||||
bool disallow_output_changed_move;
|
||||
uint32_t binding_modifier;
|
||||
enum animation_type win_animation_type;
|
||||
enum animation_type win_close_animation_type;
|
||||
|
|
@ -343,12 +176,12 @@ get_current_workspace(struct desktop_shell *shell);
|
|||
|
||||
void
|
||||
get_output_work_area(struct desktop_shell *shell,
|
||||
struct shell_output *output,
|
||||
struct weston_output *output,
|
||||
pixman_rectangle32_t *area);
|
||||
|
||||
void
|
||||
lower_fullscreen_layer(struct desktop_shell *shell,
|
||||
struct shell_output *lowering_output);
|
||||
struct weston_output *lowering_output);
|
||||
|
||||
void
|
||||
activate(struct desktop_shell *shell, struct weston_view *view,
|
||||
|
|
@ -366,5 +199,3 @@ void
|
|||
shell_for_each_layer(struct desktop_shell *shell,
|
||||
shell_for_each_layer_func_t func,
|
||||
void *data);
|
||||
|
||||
#endif /* WESTON_DESKTOP_SHELL_H */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
--------------------------------
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ Libweston
|
|||
libweston/shell-utils.rst
|
||||
libweston/output-management.rst
|
||||
libweston/log.rst
|
||||
libweston/debug-flight-recorder.rst
|
||||
|
||||
`Libweston` is an effort to separate the re-usable parts of Weston into a
|
||||
library. `Libweston` provides most of the boring and tedious bits of correctly
|
||||
|
|
|
|||
|
|
@ -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,13 +178,6 @@ The following illustrates how to use it:
|
|||
./weston-debug timeline > log.json
|
||||
./wesgr -i log.json -o log.svg
|
||||
|
||||
Weston has experimental support for `Perfetto <https://perfetto.dev>`_ for
|
||||
performance profiling. It can be enabled by using `-Dperfetto=true` during
|
||||
the meson invocation to configure the build.
|
||||
|
||||
If Perfetto support is built in, timeline points are added to Perfetto tracks
|
||||
when Perfetto is running, even when the 'timeline' scope is not enabled.
|
||||
|
||||
Inserting timeline points
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -194,13 +186,6 @@ take the :type:`weston_compositor` instance, followed by the name of the
|
|||
timeline point. What follows next is a variable number of arguments, which
|
||||
**must** end with the macro :c:macro:`TLP_END`.
|
||||
|
||||
Adding Perfetto trace points
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In addition to timeline points, Perfetto can also display timing information
|
||||
for individual functions. The easiest way to add profiling data for a function
|
||||
is to insert the :c:macro:`WESTON_TRACE_FUNC` at the top of the function.
|
||||
|
||||
Debug protocol API
|
||||
------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
1100
frontend/main.c
1100
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,8 +67,7 @@ install_data(
|
|||
install_dir: dir_data / 'wayland-sessions'
|
||||
)
|
||||
|
||||
if get_option('deprecated-screenshare') and get_option('deprecated-shell-fullscreen')
|
||||
warning('deprecated-screenshare. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848. Consider using mirroring (see man page) for same functionality and better performance.')
|
||||
if get_option('screenshare')
|
||||
srcs_screenshare = [
|
||||
'screen-share.c',
|
||||
fullscreen_shell_unstable_v1_client_protocol_h,
|
||||
|
|
|
|||
|
|
@ -371,13 +371,7 @@ ss_seat_create(struct shared_output *so, uint32_t id)
|
|||
if (seat == NULL)
|
||||
return NULL;
|
||||
|
||||
if (so->output) {
|
||||
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
|
||||
} else {
|
||||
weston_log("Skip seat creation the screen share output has not an output compositor\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
weston_seat_init(&seat->base, so->output->compositor, "screen-share");
|
||||
seat->output = so;
|
||||
seat->id = id;
|
||||
seat->parent.seat = wl_registry_bind(so->parent.registry, id,
|
||||
|
|
@ -976,8 +970,6 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
|
|||
if (!so->parent.display)
|
||||
goto err_alloc;
|
||||
|
||||
/* Set Weston output reference in the shared output before registry */
|
||||
so->output = output;
|
||||
so->parent.registry = wl_display_get_registry(so->parent.display);
|
||||
if (!so->parent.registry)
|
||||
goto err_display;
|
||||
|
|
@ -1041,6 +1033,7 @@ shared_output_create(struct weston_output *output, struct screen_share *ss, int
|
|||
wl_list_init(&so->shm.buffers);
|
||||
wl_list_init(&so->shm.free_buffers);
|
||||
|
||||
so->output = output;
|
||||
so->output_destroyed.notify = output_destroyed;
|
||||
wl_signal_add(&so->output->destroy_signal, &so->output_destroyed);
|
||||
|
||||
|
|
@ -1086,8 +1079,7 @@ shared_output_destroy(struct shared_output *so)
|
|||
wl_list_remove(&so->output_destroyed.link);
|
||||
wl_list_remove(&so->frame_listener.link);
|
||||
|
||||
if (so->cache_image)
|
||||
pixman_image_unref(so->cache_image);
|
||||
pixman_image_unref(so->cache_image);
|
||||
free(so->tmp_data);
|
||||
|
||||
free(so);
|
||||
|
|
|
|||
|
|
@ -53,8 +53,3 @@ wet_output_set_colorimetry_mode(struct weston_output *output,
|
|||
|
||||
typedef void (*wet_head_additional_setup)(struct weston_head *head,
|
||||
struct weston_head *head_to_mirror);
|
||||
|
||||
struct weston_color_profile *
|
||||
wet_create_output_color_profile(struct weston_output *output,
|
||||
struct weston_config *wc,
|
||||
const char *prof_name);
|
||||
|
|
|
|||
|
|
@ -260,10 +260,8 @@ wet_load_xwayland(struct weston_compositor *comp)
|
|||
wxw->compositor = comp;
|
||||
wxw->api = api;
|
||||
wxw->xwayland = xwayland;
|
||||
if (api->listen(xwayland, wxw, spawn_xserver) < 0) {
|
||||
free(wxw);
|
||||
if (api->listen(xwayland, wxw, spawn_xserver) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wxw;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -353,8 +353,6 @@ fs_output_create(struct fullscreen_shell *shell, struct weston_output *output)
|
|||
}
|
||||
}
|
||||
|
||||
weston_output_set_ready(output);
|
||||
|
||||
return fsout;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
if get_option('deprecated-shell-fullscreen')
|
||||
warning('deprecated-shell-fullscreen enabled. This will go away, see https://gitlab.freedesktop.org/wayland/weston/-/issues/848')
|
||||
|
||||
if get_option('shell-fullscreen')
|
||||
srcs_shell_fullscreen = [
|
||||
'fullscreen-shell.c',
|
||||
fullscreen_shell_unstable_v1_server_protocol_h,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,358 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2012-2025 Collabora, Ltd.
|
||||
* Copyright © 2017, 2018 General Electric Company
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libweston/linalg-3.h>
|
||||
|
||||
struct weston_compositor;
|
||||
struct weston_color_profile_param_builder;
|
||||
struct weston_color_profile;
|
||||
struct weston_color_transform;
|
||||
|
||||
/** Colorimetry mode for outputs and heads
|
||||
*
|
||||
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
|
||||
*
|
||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||
* supported.
|
||||
*
|
||||
* On outputs, the mode to be used for driving the video sink.
|
||||
*
|
||||
* Default (RGB) colorimetry differs from all the others in that the signal
|
||||
* colorimetry is not defined here. It is defined by the video sink, and it
|
||||
* may be described in e.g. EDID.
|
||||
*/
|
||||
enum weston_colorimetry_mode {
|
||||
/** Invalid colorimetry mode, or none supported. */
|
||||
WESTON_COLORIMETRY_MODE_NONE = 0,
|
||||
|
||||
/** Default (RGB) colorimetry, video sink dependant */
|
||||
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
|
||||
|
||||
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
|
||||
|
||||
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
|
||||
|
||||
/** Rec. ITU-R BT.2020 RGB */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
|
||||
|
||||
/** SMPTE ST 2113 DCI-P3 RGB D65 */
|
||||
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
|
||||
|
||||
/** SMPTE ST 2113 DCI-P3 RGB Theater */
|
||||
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
|
||||
|
||||
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
|
||||
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
|
||||
};
|
||||
|
||||
/** Bitmask of all defined colorimetry modes */
|
||||
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
|
||||
WESTON_COLORIMETRY_MODE_P3D65 | \
|
||||
WESTON_COLORIMETRY_MODE_P3DCI | \
|
||||
WESTON_COLORIMETRY_MODE_ICTCP))
|
||||
|
||||
const char *
|
||||
weston_colorimetry_mode_to_str(enum weston_colorimetry_mode c);
|
||||
|
||||
/** EOTF mode for outputs and heads
|
||||
*
|
||||
* A list of EOTF modes for driving displays, defined by CTA-861-G for
|
||||
* Dynamic Range and Mastering InfoFrame.
|
||||
*
|
||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||
* supported.
|
||||
*
|
||||
* On outputs, the mode to be used for driving the video sink.
|
||||
*
|
||||
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
|
||||
*/
|
||||
enum weston_eotf_mode {
|
||||
/** Invalid EOTF mode, or none supported. */
|
||||
WESTON_EOTF_MODE_NONE = 0,
|
||||
|
||||
/** Traditional gamma, SDR luminance range */
|
||||
WESTON_EOTF_MODE_SDR = 0x01,
|
||||
|
||||
/** Traditional gamma, HDR luminance range */
|
||||
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
|
||||
|
||||
/** Preceptual quantizer, SMPTE ST 2084 */
|
||||
WESTON_EOTF_MODE_ST2084 = 0x04,
|
||||
|
||||
/** Hybrid log-gamma, ITU-R BT.2100 */
|
||||
WESTON_EOTF_MODE_HLG = 0x08,
|
||||
};
|
||||
|
||||
/** Bitmask of all defined EOTF modes */
|
||||
#define WESTON_EOTF_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
|
||||
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
|
||||
|
||||
const char *
|
||||
weston_eotf_mode_to_str(enum weston_eotf_mode e);
|
||||
|
||||
/** CIE 1931 xy chromaticity coordinates */
|
||||
struct weston_CIExy {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
/** Chromaticity coordinates and white point that defines the color gamut */
|
||||
struct weston_color_gamut {
|
||||
struct weston_CIExy primary[3]; /* RGB order */
|
||||
struct weston_CIExy white_point;
|
||||
};
|
||||
|
||||
enum weston_npm_direction {
|
||||
WESTON_NPM_FORWARD,
|
||||
WESTON_NPM_INVERSE
|
||||
};
|
||||
|
||||
bool
|
||||
weston_normalized_primary_matrix_init(struct weston_mat3f *npm,
|
||||
const struct weston_color_gamut *gamut,
|
||||
enum weston_npm_direction dir);
|
||||
|
||||
struct weston_mat3f
|
||||
weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to);
|
||||
|
||||
/** Color primaries known by libweston */
|
||||
enum weston_color_primaries {
|
||||
WESTON_PRIMARIES_CICP_SRGB = 0,
|
||||
WESTON_PRIMARIES_CICP_PAL_M,
|
||||
WESTON_PRIMARIES_CICP_PAL,
|
||||
WESTON_PRIMARIES_CICP_NTSC,
|
||||
WESTON_PRIMARIES_CICP_GENERIC_FILM,
|
||||
WESTON_PRIMARIES_CICP_BT2020,
|
||||
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
|
||||
WESTON_PRIMARIES_CICP_DCI_P3,
|
||||
WESTON_PRIMARIES_CICP_DISPLAY_P3,
|
||||
WESTON_PRIMARIES_ADOBE_RGB,
|
||||
};
|
||||
|
||||
/** Transfer functions known by libweston */
|
||||
enum weston_transfer_function {
|
||||
WESTON_TF_BT1886 = 0,
|
||||
WESTON_TF_GAMMA22,
|
||||
WESTON_TF_GAMMA28,
|
||||
WESTON_TF_SRGB,
|
||||
WESTON_TF_EXT_SRGB,
|
||||
WESTON_TF_ST240,
|
||||
WESTON_TF_ST428,
|
||||
WESTON_TF_ST2084_PQ,
|
||||
WESTON_TF_EXT_LINEAR,
|
||||
WESTON_TF_LOG_100,
|
||||
WESTON_TF_LOG_316,
|
||||
WESTON_TF_XVYCC,
|
||||
WESTON_TF_HLG,
|
||||
WESTON_TF_POWER,
|
||||
};
|
||||
|
||||
enum weston_alpha_mode {
|
||||
WESTON_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL = 0,
|
||||
WESTON_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
|
||||
WESTON_ALPHA_MODE_STRAIGHT,
|
||||
};
|
||||
|
||||
enum weston_color_matrix_coef {
|
||||
WESTON_COLOR_MATRIX_COEF_UNSET = 0,
|
||||
WESTON_COLOR_MATRIX_COEF_IDENTITY,
|
||||
WESTON_COLOR_MATRIX_COEF_BT601,
|
||||
WESTON_COLOR_MATRIX_COEF_BT709,
|
||||
WESTON_COLOR_MATRIX_COEF_BT2020,
|
||||
};
|
||||
|
||||
enum weston_color_quant_range {
|
||||
WESTON_COLOR_QUANT_RANGE_UNSET = 0,
|
||||
WESTON_COLOR_QUANT_RANGE_FULL,
|
||||
WESTON_COLOR_QUANT_RANGE_LIMITED,
|
||||
};
|
||||
|
||||
enum weston_ycbcr_chroma_location {
|
||||
WESTON_YCBCR_CHROMA_LOCATION_UNSET = 0,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_0,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_1,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_2,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_3,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_4,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_5,
|
||||
};
|
||||
|
||||
/** Error codes that the color profile parameters functions may return. */
|
||||
enum weston_color_profile_param_builder_error {
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES_NAMED,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CREATE_FAILED,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
|
||||
};
|
||||
|
||||
struct weston_color_profile_param_builder *
|
||||
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
|
||||
|
||||
void
|
||||
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_profile_param_builder_error *err,
|
||||
char **err_msg);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_primaries primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_transfer_function tf);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
|
||||
float power_exponent);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder,
|
||||
float ref_lum, float min_lum, float max_lum);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *target_primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_primaries target_primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
|
||||
float min_lum, float max_lum);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
|
||||
float maxFALL);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
|
||||
float maxCLL);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
|
||||
const char *name_part,
|
||||
enum weston_color_profile_param_builder_error *err,
|
||||
char **err_msg);
|
||||
|
||||
enum weston_color_characteristics_groups {
|
||||
/** weston_color_characteristics::primary is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
|
||||
|
||||
/** weston_color_characteristics::white is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
|
||||
|
||||
/** weston_color_characteristics::max_luminance is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
|
||||
|
||||
/** weston_color_characteristics::min_luminance is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
|
||||
|
||||
/** weston_color_characteristics::maxFALL is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
|
||||
|
||||
/** all valid bits */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
|
||||
};
|
||||
|
||||
/** Basic display color characteristics
|
||||
*
|
||||
* This is a simple description of a display or output (monitor) color
|
||||
* characteristics. The parameters can be found in EDID, with caveats. They
|
||||
* are particularly useful with HDR monitors.
|
||||
*/
|
||||
struct weston_color_characteristics {
|
||||
/** Which fields are valid
|
||||
*
|
||||
* A bitmask of values from enum weston_color_characteristics_groups.
|
||||
*/
|
||||
uint32_t group_mask;
|
||||
|
||||
/* EOTF is tracked externally with enum weston_eotf_mode */
|
||||
|
||||
/** Chromaticities of the primaries */
|
||||
struct weston_CIExy primary[3];
|
||||
|
||||
/** White point chromaticity */
|
||||
struct weston_CIExy white;
|
||||
|
||||
/** Display's desired maximum content peak luminance, cd/m² */
|
||||
float max_luminance;
|
||||
|
||||
/** Display's desired minimum content luminance, cd/m² */
|
||||
float min_luminance;
|
||||
|
||||
/** Display's desired maximum frame-average light level, cd/m² */
|
||||
float maxFALL;
|
||||
};
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_color_profile_ref(struct weston_color_profile *cprof);
|
||||
|
||||
void
|
||||
weston_color_profile_unref(struct weston_color_profile *cprof);
|
||||
|
||||
const char *
|
||||
weston_color_profile_get_description(struct weston_color_profile *cprof);
|
||||
|
||||
char *
|
||||
weston_color_profile_get_details(struct weston_color_profile *cprof);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_compositor_load_icc_file(struct weston_compositor *compositor,
|
||||
const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ extern "C" {
|
|||
|
||||
#include <libweston/matrix.h>
|
||||
#include <libweston/zalloc.h>
|
||||
#include <libweston/colorimetry.h>
|
||||
|
||||
struct weston_log_pacer {
|
||||
/** This must be set to zero before first use */
|
||||
|
|
@ -74,12 +73,6 @@ struct weston_point2d_device_normalized {
|
|||
double y;
|
||||
};
|
||||
|
||||
struct weston_commit_timing_target {
|
||||
bool valid;
|
||||
bool satisfied;
|
||||
struct timespec time;
|
||||
};
|
||||
|
||||
struct weston_compositor;
|
||||
struct weston_surface;
|
||||
struct weston_buffer;
|
||||
|
|
@ -92,6 +85,9 @@ struct linux_dmabuf_buffer;
|
|||
struct weston_recorder;
|
||||
struct weston_pointer_constraint;
|
||||
struct ro_anonymous_file;
|
||||
struct weston_color_profile_param_builder;
|
||||
struct weston_color_profile;
|
||||
struct weston_color_transform;
|
||||
struct pixel_format_info;
|
||||
struct weston_output_capture_info;
|
||||
struct weston_output_color_outcome;
|
||||
|
|
@ -111,13 +107,9 @@ enum weston_keyboard_locks {
|
|||
};
|
||||
|
||||
enum weston_led {
|
||||
WESTON_LED_NUM_LOCK = (1 << 0),
|
||||
WESTON_LED_CAPS_LOCK = (1 << 1),
|
||||
WESTON_LED_SCROLL_LOCK = (1 << 2),
|
||||
#ifdef HAVE_COMPOSE_AND_KANA
|
||||
WESTON_LED_COMPOSE = (1 << 3),
|
||||
WESTON_LED_KANA = (1 << 4),
|
||||
#endif
|
||||
LED_NUM_LOCK = (1 << 0),
|
||||
LED_CAPS_LOCK = (1 << 1),
|
||||
LED_SCROLL_LOCK = (1 << 2),
|
||||
};
|
||||
|
||||
enum weston_mode_aspect_ratio {
|
||||
|
|
@ -137,17 +129,6 @@ enum weston_surface_protection_mode {
|
|||
WESTON_SURFACE_PROTECTION_MODE_ENFORCED
|
||||
};
|
||||
|
||||
enum weston_output_color_effect_type {
|
||||
WESTON_OUTPUT_COLOR_EFFECT_TYPE_INVERSION = 0,
|
||||
WESTON_OUTPUT_COLOR_EFFECT_TYPE_CVD_CORRECTION,
|
||||
};
|
||||
|
||||
enum weston_cvd_correction_type {
|
||||
WESTON_CVD_CORRECTION_TYPE_DEUTERANOPIA = 0,
|
||||
WESTON_CVD_CORRECTION_TYPE_PROTANOPIA,
|
||||
WESTON_CVD_CORRECTION_TYPE_TRITANOPIA,
|
||||
};
|
||||
|
||||
/** Possible mode of an output
|
||||
*
|
||||
* \ingroup output
|
||||
|
|
@ -166,6 +147,7 @@ struct weston_animation {
|
|||
void (*frame)(struct weston_animation *animation,
|
||||
struct weston_output *output,
|
||||
const struct timespec *time);
|
||||
int frame_counter;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
|
|
@ -217,12 +199,10 @@ enum weston_hdcp_protection {
|
|||
* \ingroup testharness
|
||||
*/
|
||||
struct weston_testsuite_quirks {
|
||||
/** Force GL/Vulkan-renderer to do a full upload of wl_shm buffers. */
|
||||
bool force_full_upload;
|
||||
/** Force GL-renderer to do a full upload of wl_shm buffers. */
|
||||
bool gl_force_full_upload;
|
||||
/** Ensure GL shadow fb is used, and always repaint it fully. */
|
||||
bool gl_force_full_redraw_of_shadow_fb;
|
||||
/** Force GL-renderer to use the internal YUV->RGB shader */
|
||||
bool gl_force_import_yuv_fallback;
|
||||
/** Required enum weston_capability bit mask, otherwise skip run. */
|
||||
uint32_t required_capabilities;
|
||||
};
|
||||
|
|
@ -245,6 +225,248 @@ struct weston_testsuite_data {
|
|||
void *test_private_data;
|
||||
};
|
||||
|
||||
/** Colorimetry mode for outputs and heads
|
||||
*
|
||||
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
|
||||
*
|
||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||
* supported.
|
||||
*
|
||||
* On outputs, the mode to be used for driving the video sink.
|
||||
*
|
||||
* Default (RGB) colorimetry differs from all the others in that the signal
|
||||
* colorimetry is not defined here. It is defined by the video sink, and it
|
||||
* may be described in e.g. EDID.
|
||||
*/
|
||||
enum weston_colorimetry_mode {
|
||||
/** Invalid colorimetry mode, or none supported. */
|
||||
WESTON_COLORIMETRY_MODE_NONE = 0,
|
||||
|
||||
/** Default (RGB) colorimetry, video sink dependant */
|
||||
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
|
||||
|
||||
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
|
||||
|
||||
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
|
||||
|
||||
/** Rec. ITU-R BT.2020 RGB */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
|
||||
|
||||
/** SMPTE ST 2113 DCI-P3 RGB D65 */
|
||||
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
|
||||
|
||||
/** SMPTE ST 2113 DCI-P3 RGB Theater */
|
||||
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
|
||||
|
||||
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
|
||||
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
|
||||
};
|
||||
|
||||
/** Bitmask of all defined colorimetry modes */
|
||||
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
|
||||
WESTON_COLORIMETRY_MODE_P3D65 | \
|
||||
WESTON_COLORIMETRY_MODE_P3DCI | \
|
||||
WESTON_COLORIMETRY_MODE_ICTCP))
|
||||
|
||||
/** EOTF mode for outputs and heads
|
||||
*
|
||||
* A list of EOTF modes for driving displays, defined by CTA-861-G for
|
||||
* Dynamic Range and Mastering InfoFrame.
|
||||
*
|
||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||
* supported.
|
||||
*
|
||||
* On outputs, the mode to be used for driving the video sink.
|
||||
*
|
||||
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
|
||||
*/
|
||||
enum weston_eotf_mode {
|
||||
/** Invalid EOTF mode, or none supported. */
|
||||
WESTON_EOTF_MODE_NONE = 0,
|
||||
|
||||
/** Traditional gamma, SDR luminance range */
|
||||
WESTON_EOTF_MODE_SDR = 0x01,
|
||||
|
||||
/** Traditional gamma, HDR luminance range */
|
||||
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
|
||||
|
||||
/** Preceptual quantizer, SMPTE ST 2084 */
|
||||
WESTON_EOTF_MODE_ST2084 = 0x04,
|
||||
|
||||
/** Hybrid log-gamma, ITU-R BT.2100 */
|
||||
WESTON_EOTF_MODE_HLG = 0x08,
|
||||
};
|
||||
|
||||
/** Bitmask of all defined EOTF modes */
|
||||
#define WESTON_EOTF_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
|
||||
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
|
||||
|
||||
/** CIE 1931 xy chromaticity coordinates */
|
||||
struct weston_CIExy {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
/** Chromaticity coordinates and white point that defines the color gamut */
|
||||
struct weston_color_gamut {
|
||||
struct weston_CIExy primary[3]; /* RGB order */
|
||||
struct weston_CIExy white_point;
|
||||
};
|
||||
|
||||
/** Color primaries known by libweston */
|
||||
enum weston_color_primaries {
|
||||
WESTON_PRIMARIES_CICP_SRGB = 0,
|
||||
WESTON_PRIMARIES_CICP_PAL_M,
|
||||
WESTON_PRIMARIES_CICP_PAL,
|
||||
WESTON_PRIMARIES_CICP_NTSC,
|
||||
WESTON_PRIMARIES_CICP_GENERIC_FILM,
|
||||
WESTON_PRIMARIES_CICP_BT2020,
|
||||
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
|
||||
WESTON_PRIMARIES_CICP_DCI_P3,
|
||||
WESTON_PRIMARIES_CICP_DISPLAY_P3,
|
||||
WESTON_PRIMARIES_ADOBE_RGB,
|
||||
};
|
||||
|
||||
/** Transfer functions known by libweston */
|
||||
enum weston_transfer_function {
|
||||
WESTON_TF_LINEAR = 0,
|
||||
WESTON_TF_GAMMA22,
|
||||
WESTON_TF_GAMMA28,
|
||||
WESTON_TF_SRGB,
|
||||
WESTON_TF_EXT_SRGB,
|
||||
WESTON_TF_BT709,
|
||||
WESTON_TF_BT1361,
|
||||
WESTON_TF_ST240,
|
||||
WESTON_TF_ST428,
|
||||
WESTON_TF_ST2084_PQ,
|
||||
WESTON_TF_LOG_100,
|
||||
WESTON_TF_LOG_316,
|
||||
WESTON_TF_XVYCC,
|
||||
WESTON_TF_HLG,
|
||||
WESTON_TF_POWER,
|
||||
};
|
||||
|
||||
/** Error codes that the color profile parameters functions may return. */
|
||||
enum weston_color_profile_param_builder_error {
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TARGET_PRIMARIES,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
|
||||
};
|
||||
|
||||
struct weston_color_profile_param_builder *
|
||||
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
|
||||
|
||||
void
|
||||
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_profile_param_builder_error *err,
|
||||
char **err_msg);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_primaries primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_transfer_function tf);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
|
||||
float power_exponent);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *target_primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
|
||||
float min_luminance, float max_luminance);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
|
||||
float maxFALL);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
|
||||
float maxCLL);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
|
||||
const char *name_part,
|
||||
enum weston_color_profile_param_builder_error *err,
|
||||
char **err_msg);
|
||||
|
||||
enum weston_color_characteristics_groups {
|
||||
/** weston_color_characteristics::primary is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
|
||||
|
||||
/** weston_color_characteristics::white is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02,
|
||||
|
||||
/** weston_color_characteristics::max_luminance is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04,
|
||||
|
||||
/** weston_color_characteristics::min_luminance is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08,
|
||||
|
||||
/** weston_color_characteristics::maxFALL is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10,
|
||||
|
||||
/** all valid bits */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f
|
||||
};
|
||||
|
||||
/** Basic display color characteristics
|
||||
*
|
||||
* This is a simple description of a display or output (monitor) color
|
||||
* characteristics. The parameters can be found in EDID, with caveats. They
|
||||
* are particularly useful with HDR monitors.
|
||||
*/
|
||||
struct weston_color_characteristics {
|
||||
/** Which fields are valid
|
||||
*
|
||||
* A bitmask of values from enum weston_color_characteristics_groups.
|
||||
*/
|
||||
uint32_t group_mask;
|
||||
|
||||
/* EOTF is tracked externally with enum weston_eotf_mode */
|
||||
|
||||
/** Chromaticities of the primaries */
|
||||
struct weston_CIExy primary[3];
|
||||
|
||||
/** White point chromaticity */
|
||||
struct weston_CIExy white;
|
||||
|
||||
/** Display's desired maximum content peak luminance, cd/m² */
|
||||
float max_luminance;
|
||||
|
||||
/** Display's desired minimum content luminance, cd/m² */
|
||||
float min_luminance;
|
||||
|
||||
/** Display's desired maximum frame-average light level, cd/m² */
|
||||
float maxFALL;
|
||||
};
|
||||
|
||||
/** Represents a head, usually a display connector
|
||||
*
|
||||
* \rst
|
||||
|
|
@ -294,10 +516,6 @@ struct weston_head {
|
|||
* When a client uses this request, we add the wl_resource we create to
|
||||
* this list. */
|
||||
struct wl_list cm_output_resource_list;
|
||||
|
||||
uint32_t supported_vrr_mode_mask;
|
||||
|
||||
uint32_t supported_color_format_mask;
|
||||
};
|
||||
|
||||
enum weston_output_power_state {
|
||||
|
|
@ -307,63 +525,12 @@ enum weston_output_power_state {
|
|||
WESTON_OUTPUT_POWER_NORMAL
|
||||
};
|
||||
|
||||
enum weston_paint_node_status {
|
||||
WESTON_PAINT_NODE_CLEAN = 0,
|
||||
WESTON_PAINT_NODE_OUTPUT_DIRTY = 1 << 0,
|
||||
WESTON_PAINT_NODE_VIEW_DIRTY = 1 << 1,
|
||||
WESTON_PAINT_NODE_VISIBILITY_DIRTY = 1 << 2,
|
||||
WESTON_PAINT_NODE_PLANE_DIRTY = 1 << 3,
|
||||
WESTON_PAINT_NODE_BUFFER_DIRTY = 1 << 4,
|
||||
WESTON_PAINT_NODE_BUFFER_PARAMS_DIRTY = 1 << 5,
|
||||
WESTON_PAINT_NODE_ALL_DIRTY = (1 << 6) - 1,
|
||||
};
|
||||
|
||||
|
||||
enum weston_vrr_mode {
|
||||
/** No VRR */
|
||||
WESTON_VRR_MODE_NONE = 0,
|
||||
/** Game mode VRR */
|
||||
WESTON_VRR_MODE_GAME = 1 << 0,
|
||||
};
|
||||
#define WESTON_VRR_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_VRR_MODE_GAME))
|
||||
|
||||
enum weston_color_format {
|
||||
/** Driver assigned color format automatically */
|
||||
WESTON_COLOR_FORMAT_AUTO = (1 << 0),
|
||||
/** Force RGB color format */
|
||||
WESTON_COLOR_FORMAT_RGB = (1 << 1),
|
||||
/** Force YUV color format with 4:2:2 susampling */
|
||||
WESTON_COLOR_FORMAT_YUV422 = (1 << 2),
|
||||
/** Force YUV color format with no subsampling */
|
||||
WESTON_COLOR_FORMAT_YUV444 = (1 << 3),
|
||||
/** Force YUV color format with 4:2:0 subsampling */
|
||||
WESTON_COLOR_FORMAT_YUV420 = (1 << 4),
|
||||
};
|
||||
|
||||
/** Bitmask of all defined color formats */
|
||||
#define WESTON_COLOR_FORMAT_ALL_MASK \
|
||||
((uint32_t)(WESTON_COLOR_FORMAT_AUTO | WESTON_COLOR_FORMAT_RGB | \
|
||||
WESTON_COLOR_FORMAT_YUV444 | WESTON_COLOR_FORMAT_YUV422 | \
|
||||
WESTON_COLOR_FORMAT_YUV420))
|
||||
|
||||
struct weston_plane {
|
||||
struct weston_compositor *compositor;
|
||||
int32_t x, y;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
/** State of the repaint loop
|
||||
*
|
||||
* \ingroup output
|
||||
*/
|
||||
enum weston_repaint_status {
|
||||
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
|
||||
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
|
||||
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
|
||||
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
|
||||
};
|
||||
|
||||
/** Content producer for heads
|
||||
*
|
||||
* \rst
|
||||
|
|
@ -375,8 +542,6 @@ struct weston_output {
|
|||
uint32_t id;
|
||||
char *name;
|
||||
|
||||
void *shell_private;
|
||||
|
||||
struct weston_backend *backend;
|
||||
|
||||
/** Matches the lifetime from the user perspective */
|
||||
|
|
@ -391,9 +556,6 @@ struct weston_output {
|
|||
/* struct weston_paint_node::output_link */
|
||||
struct wl_list paint_node_list;
|
||||
|
||||
/** Only valid during repaint: changes for this repaint */
|
||||
enum weston_paint_node_status paint_node_changes;
|
||||
|
||||
/** From global to output buffer coordinates. */
|
||||
struct weston_matrix matrix;
|
||||
/** From output buffer to global coordinates. */
|
||||
|
|
@ -403,10 +565,6 @@ struct weston_output {
|
|||
struct weston_coord_global pos;
|
||||
int32_t width, height;
|
||||
|
||||
uint64_t gpu_track_id;
|
||||
uint64_t paint_track_id;
|
||||
uint64_t presentation_track_id;
|
||||
|
||||
/** List of paint nodes in z-order, from top to bottom, maybe pruned
|
||||
*
|
||||
* struct weston_paint_node::z_order_link
|
||||
|
|
@ -434,34 +592,24 @@ struct weston_output {
|
|||
bool repaint_only_on_capture;
|
||||
|
||||
/** State of the repaint loop */
|
||||
enum weston_repaint_status repaint_status;
|
||||
enum {
|
||||
REPAINT_NOT_SCHEDULED = 0, /**< idle; no repaint will occur */
|
||||
REPAINT_BEGIN_FROM_IDLE, /**< start_repaint_loop scheduled */
|
||||
REPAINT_SCHEDULED, /**< repaint is scheduled to occur */
|
||||
REPAINT_AWAITING_COMPLETION, /**< last repaint not yet finished */
|
||||
} repaint_status;
|
||||
|
||||
/** If repaint_status is REPAINT_SCHEDULED, contains the time the
|
||||
* next repaint should be run */
|
||||
struct timespec next_repaint;
|
||||
/** If repaint_statue is REPAINT_SCHEDULED, contains the time the
|
||||
* next repaint should be displayed */
|
||||
struct timespec next_present;
|
||||
|
||||
/** commit-timing protocol will set this for the closest requested
|
||||
* presentation time from a surface on this output. It's only
|
||||
* valid during weston_repaint_timer_arm. */
|
||||
struct weston_commit_timing_target requested_present;
|
||||
/** commit-timing protocol will set this when state containing
|
||||
* a target time is applied. Weston will try to hit this time if
|
||||
* VRR is in use.
|
||||
*/
|
||||
struct weston_commit_timing_target forced_present;
|
||||
|
||||
/** For cancelling the idle_repaint callback on output destruction. */
|
||||
struct wl_event_source *idle_repaint_source;
|
||||
|
||||
struct wl_signal frame_signal;
|
||||
struct wl_signal post_latch_signal;
|
||||
struct wl_signal destroy_signal; /**< sent when disabled */
|
||||
struct weston_coord_global move;
|
||||
struct timespec frame_time; /* presentation timestamp */
|
||||
uint32_t frame_flags; /* presentation flags */
|
||||
uint64_t msc; /* media stream counter */
|
||||
int disable_planes;
|
||||
int destroying;
|
||||
|
|
@ -510,6 +658,13 @@ struct weston_output {
|
|||
void (*set_backlight)(struct weston_output *output, uint32_t value);
|
||||
void (*set_dpms)(struct weston_output *output, enum dpms_enum level);
|
||||
|
||||
uint16_t gamma_size;
|
||||
void (*set_gamma)(struct weston_output *output,
|
||||
uint16_t size,
|
||||
uint16_t *r,
|
||||
uint16_t *g,
|
||||
uint16_t *b);
|
||||
|
||||
bool enabled; /**< is in the output_list, not pending list */
|
||||
|
||||
struct weston_color_profile *color_profile;
|
||||
|
|
@ -521,8 +676,6 @@ struct weston_output {
|
|||
struct weston_output_color_outcome *color_outcome;
|
||||
uint64_t color_outcome_serial;
|
||||
|
||||
struct weston_output_color_effect *color_effect;
|
||||
|
||||
int (*enable)(struct weston_output *output);
|
||||
int (*disable)(struct weston_output *output);
|
||||
|
||||
|
|
@ -553,32 +706,11 @@ struct weston_output {
|
|||
void (*detach_head)(struct weston_output *output,
|
||||
struct weston_head *head);
|
||||
|
||||
/**
|
||||
* Get the DRM formats supported by a compatible writeback connector.
|
||||
*/
|
||||
const struct weston_drm_format_array *(*get_writeback_formats)(struct weston_output *output);
|
||||
|
||||
/**
|
||||
* When set, this output is a mirror-of another output. See
|
||||
* mirror-of key in [output] section.
|
||||
*/
|
||||
struct weston_output *mirror_of;
|
||||
|
||||
enum weston_vrr_mode vrr_mode;
|
||||
|
||||
enum weston_color_format color_format;
|
||||
|
||||
/**
|
||||
* Set by the shell to indicate there's some content for this
|
||||
* output to display.
|
||||
*/
|
||||
bool ready;
|
||||
|
||||
/** Needs to rebuild the paint node z ordered list */
|
||||
bool paint_node_list_needs_rebuild;
|
||||
|
||||
/** fifo_v1 - list of surfaces to clear next repaint */
|
||||
struct wl_list fifo_barrier_surfaces;
|
||||
};
|
||||
|
||||
enum weston_pointer_motion_mask {
|
||||
|
|
@ -921,18 +1053,6 @@ struct weston_tablet {
|
|||
const char *path;
|
||||
};
|
||||
|
||||
struct weston_color_representation {
|
||||
enum weston_alpha_mode alpha_mode;
|
||||
enum weston_color_matrix_coef matrix_coefficients;
|
||||
enum weston_color_quant_range quant_range;
|
||||
enum weston_ycbcr_chroma_location chroma_location;
|
||||
};
|
||||
|
||||
struct weston_color_representation_matrix {
|
||||
struct weston_mat3f matrix;
|
||||
struct weston_vec3f offset;
|
||||
};
|
||||
|
||||
struct weston_coord_global
|
||||
weston_pointer_motion_to_abs(struct weston_pointer *pointer,
|
||||
struct weston_pointer_motion_event *event);
|
||||
|
|
@ -1103,10 +1223,6 @@ struct weston_xkb_info {
|
|||
xkb_led_index_t num_led;
|
||||
xkb_led_index_t caps_led;
|
||||
xkb_led_index_t scroll_led;
|
||||
#ifdef HAVE_COMPOSE_AND_KANA
|
||||
xkb_led_index_t compose_led;
|
||||
xkb_led_index_t kana_led;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct weston_keyboard {
|
||||
|
|
@ -1290,9 +1406,6 @@ enum weston_capability {
|
|||
|
||||
/* renderer supports color management operations */
|
||||
WESTON_CAP_COLOR_OPS = 0x0040,
|
||||
|
||||
/* renderer supports color representation operations */
|
||||
WESTON_CAP_COLOR_REP = 0x0080,
|
||||
};
|
||||
|
||||
/* Configuration struct for a backend.
|
||||
|
|
@ -1359,7 +1472,6 @@ struct weston_color_manager;
|
|||
struct weston_dmabuf_feedback;
|
||||
struct weston_dmabuf_feedback_format_table;
|
||||
struct weston_renderer;
|
||||
struct weston_content_update;
|
||||
|
||||
/** Main object, container-like structure which aggregates all other objects.
|
||||
*
|
||||
|
|
@ -1419,14 +1531,12 @@ struct weston_compositor {
|
|||
struct wl_list debug_binding_list;
|
||||
|
||||
bool view_list_needs_rebuild;
|
||||
int global_weston_surface_disambiguator; /* surface ids to avoid using PID-reuse */
|
||||
|
||||
uint32_t state;
|
||||
struct wl_event_source *idle_source;
|
||||
uint32_t idle_inhibit;
|
||||
int idle_time; /* timeout, s */
|
||||
int repaint_timer_fd;
|
||||
struct wl_event_source *repaint_timer_source;
|
||||
struct wl_event_source *repaint_timer;
|
||||
|
||||
const struct weston_pointer_grab_interface *default_pointer_grab;
|
||||
|
||||
|
|
@ -1482,9 +1592,6 @@ struct weston_compositor {
|
|||
/* Whether to let the compositor run without any input device. */
|
||||
bool require_input;
|
||||
|
||||
/* Ignore all libinput-based input devices */
|
||||
bool disable_input;
|
||||
|
||||
/* Whether to load multiple backends. */
|
||||
bool multi_backend;
|
||||
|
||||
|
|
@ -1508,7 +1615,6 @@ struct weston_compositor {
|
|||
struct weston_log_scope *debug_scene;
|
||||
struct weston_log_scope *timeline;
|
||||
struct weston_log_scope *libseat_debug;
|
||||
struct weston_log_filtered *advertised_log_scopes;
|
||||
|
||||
struct content_protection *content_protection;
|
||||
|
||||
|
|
@ -1520,34 +1626,6 @@ struct weston_compositor {
|
|||
struct wl_global *weston_capture_v1;
|
||||
struct wl_signal ask_auth;
|
||||
} output_capture;
|
||||
|
||||
struct {
|
||||
/** interval which we divide the amount of frames */
|
||||
unsigned int frame_counter_interval;
|
||||
|
||||
/** fires with frame_counter_interval rate */
|
||||
struct wl_event_source *frame_counter_timer;
|
||||
} perf_surface_stats;
|
||||
|
||||
/* if set use this placeholder-color to use instead of the default
|
||||
* grenadier one */
|
||||
uint32_t placeholder_color;
|
||||
|
||||
bool no_xwm_decorations;
|
||||
|
||||
/**
|
||||
* When set the compositor has latched content updates for the
|
||||
* upcoming repaint, and no more updates may be applied until after
|
||||
* that repaint occurs.
|
||||
*/
|
||||
bool latched;
|
||||
|
||||
struct wl_list transaction_queue_list; /* weston_transaction_queue::link */
|
||||
|
||||
/** commit_timing_v1 - target repaint time for content updates for
|
||||
* surfaces with no output
|
||||
*/
|
||||
struct weston_commit_timing_target requested_repaint_fallback;
|
||||
};
|
||||
|
||||
struct weston_solid_buffer_values {
|
||||
|
|
@ -1696,6 +1774,7 @@ struct weston_view {
|
|||
|
||||
unsigned int click_to_activate_serial;
|
||||
|
||||
pixman_region32_t visible; /* Unoccluded region in global space */
|
||||
float alpha; /* part of geometry, see below */
|
||||
|
||||
/* Surface geometry state, mutable.
|
||||
|
|
@ -1759,16 +1838,11 @@ struct weston_view {
|
|||
struct wl_listener output_destroy_listener;
|
||||
|
||||
/*
|
||||
* A bitfield of outputs this view intersects - though it may not be
|
||||
* visible on them.
|
||||
* A more complete representation of all outputs this surface is
|
||||
* displayed on.
|
||||
*/
|
||||
uint32_t output_mask;
|
||||
|
||||
/*
|
||||
* A bitfield of outputs this view is visible (has unoccluded pixels) on.
|
||||
*/
|
||||
uint32_t output_visibility_mask;
|
||||
|
||||
bool is_mapped;
|
||||
struct weston_log_pacer subsurface_parent_log_pacer;
|
||||
};
|
||||
|
|
@ -1793,11 +1867,11 @@ enum weston_surface_status {
|
|||
};
|
||||
|
||||
struct weston_surface_state {
|
||||
uint64_t flow_id;
|
||||
enum weston_surface_status status;
|
||||
|
||||
/* wl_surface.attach */
|
||||
struct weston_buffer_reference buffer_ref;
|
||||
struct weston_buffer *buffer;
|
||||
struct wl_listener buffer_destroy_listener;
|
||||
|
||||
struct weston_coord_surface buf_offset;
|
||||
|
||||
|
|
@ -1840,18 +1914,6 @@ struct weston_surface_state {
|
|||
* color_management_surface_v1_interface.unset_image_description */
|
||||
struct weston_color_profile *color_profile;
|
||||
const struct weston_render_intent_info *render_intent;
|
||||
|
||||
/* wp_color_representation_surface_v1.set_alpha_mode */
|
||||
/* wp_color_representation_surface_v1.set_coefficients_and_range */
|
||||
/* wp_color_representation_surface_v1.set_chroma_location */
|
||||
struct weston_color_representation color_representation;
|
||||
|
||||
/* wp_fifo_v1 */
|
||||
bool fifo_barrier;
|
||||
bool fifo_wait;
|
||||
|
||||
/* commit_timing_v1 */
|
||||
struct weston_commit_timing_target update_time;
|
||||
};
|
||||
|
||||
struct weston_surface_activation_data {
|
||||
|
|
@ -1981,7 +2043,6 @@ struct weston_surface {
|
|||
|
||||
bool is_mapped, is_unmapping, is_mapping;
|
||||
bool is_opaque;
|
||||
uint32_t s_id;
|
||||
|
||||
/* An list of per seat pointer constraints. */
|
||||
struct wl_list pointer_constraints;
|
||||
|
|
@ -2007,41 +2068,8 @@ struct weston_surface {
|
|||
*
|
||||
* When a client uses this request, we add the wl_resource we create to
|
||||
* this list. */
|
||||
struct wl_list cm_surface_feedback_resource_list;
|
||||
struct wl_list cm_feedback_surface_resource_list;
|
||||
struct wl_resource *cm_surface;
|
||||
|
||||
struct wl_resource *color_representation_resource;
|
||||
struct weston_color_representation color_representation;
|
||||
|
||||
uint64_t damage_track_id;
|
||||
uint64_t flow_id;
|
||||
|
||||
|
||||
/** increments for each wl_surface::commit,
|
||||
* reset after each frame counter interval */
|
||||
unsigned int frame_commit_counter;
|
||||
|
||||
/** increments after an output repaint when parsing paint node list;
|
||||
* reset as frame_commit_counter */
|
||||
unsigned int painted_frame_counter;
|
||||
|
||||
/** computed after each frame_counter_interval */
|
||||
float frame_commit_fps_counter;
|
||||
float painted_frame_fps_counter;
|
||||
|
||||
/** Visibility won't be calculated until repaint, but we use this to
|
||||
* track whether we can safely use the last repaint's visibility
|
||||
* calculations when considering this surface's visibility.
|
||||
*/
|
||||
uint32_t output_visibility_dirty_mask;
|
||||
|
||||
/** fifo_v1 */
|
||||
struct weston_fifo *fifo;
|
||||
bool fifo_barrier; /* Cleared after display */
|
||||
struct wl_list fifo_barrier_link; /* output::fifo_barrier_surfaces */
|
||||
|
||||
/** commit_timing_v1 */
|
||||
struct weston_commit_timer *commit_timer;
|
||||
};
|
||||
|
||||
struct weston_subsurface {
|
||||
|
|
@ -2062,10 +2090,14 @@ struct weston_subsurface {
|
|||
bool changed;
|
||||
} position;
|
||||
|
||||
int has_cached_data;
|
||||
struct weston_surface_state cached;
|
||||
struct weston_buffer_reference cached_buffer_ref;
|
||||
|
||||
bool synchronized;
|
||||
bool effectively_synchronized;
|
||||
/* Sub-surface has been reordered; need to apply damage. */
|
||||
bool reordered;
|
||||
|
||||
int synchronized;
|
||||
|
||||
/* Used for constructing the view tree */
|
||||
struct wl_list unused_views;
|
||||
|
|
@ -2154,10 +2186,6 @@ void
|
|||
weston_view_move_to_layer(struct weston_view *view,
|
||||
struct weston_layer_entry *layer);
|
||||
|
||||
void
|
||||
weston_view_move_before_layer_entry(struct weston_view *view,
|
||||
struct weston_layer_entry *layer);
|
||||
|
||||
void
|
||||
weston_layer_init(struct weston_layer *layer,
|
||||
struct weston_compositor *compositor);
|
||||
|
|
@ -2189,6 +2217,8 @@ void
|
|||
weston_output_schedule_repaint_reset(struct weston_output *output);
|
||||
void
|
||||
weston_output_schedule_repaint_restart(struct weston_output *output);
|
||||
enum weston_compositor_backend
|
||||
weston_get_backend_type(struct weston_backend *backend);
|
||||
void
|
||||
weston_compositor_schedule_repaint(struct weston_compositor *compositor);
|
||||
void
|
||||
|
|
@ -2357,6 +2387,12 @@ void
|
|||
weston_surface_set_size(struct weston_surface *surface,
|
||||
int32_t width, int32_t height);
|
||||
|
||||
void
|
||||
weston_surface_damage(struct weston_surface *surface);
|
||||
|
||||
void
|
||||
weston_view_damage_below(struct weston_view *view);
|
||||
|
||||
void
|
||||
weston_view_unmap(struct weston_view *view);
|
||||
|
||||
|
|
@ -2433,15 +2469,12 @@ enum weston_renderer_type {
|
|||
WESTON_RENDERER_NOOP = 1,
|
||||
WESTON_RENDERER_PIXMAN = 2,
|
||||
WESTON_RENDERER_GL = 3,
|
||||
WESTON_RENDERER_VULKAN = 4,
|
||||
};
|
||||
|
||||
struct weston_backend *
|
||||
weston_compositor_load_backend(struct weston_compositor *compositor,
|
||||
enum weston_compositor_backend backend,
|
||||
struct weston_backend_config *config_base);
|
||||
enum weston_compositor_backend
|
||||
weston_get_backend_type(struct weston_backend *backend);
|
||||
void
|
||||
weston_compositor_exit(struct weston_compositor *ec);
|
||||
void *
|
||||
|
|
@ -2666,13 +2699,6 @@ void
|
|||
weston_output_set_transform(struct weston_output *output,
|
||||
uint32_t transform);
|
||||
|
||||
void
|
||||
weston_output_color_effect_inversion(struct weston_output *output);
|
||||
|
||||
void
|
||||
weston_output_color_effect_cvd_correction(struct weston_output *output,
|
||||
enum weston_cvd_correction_type type);
|
||||
|
||||
bool
|
||||
weston_output_set_color_profile(struct weston_output *output,
|
||||
struct weston_color_profile *cprof);
|
||||
|
|
@ -2759,6 +2785,19 @@ void
|
|||
weston_timeline_refresh_subscription_objects(struct weston_compositor *wc,
|
||||
void *object);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_color_profile_ref(struct weston_color_profile *cprof);
|
||||
|
||||
void
|
||||
weston_color_profile_unref(struct weston_color_profile *cprof);
|
||||
|
||||
const char *
|
||||
weston_color_profile_get_description(struct weston_color_profile *cprof);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_compositor_load_icc_file(struct weston_compositor *compositor,
|
||||
const char *path);
|
||||
|
||||
/** Describes who is trying to capture and which output */
|
||||
struct weston_output_capture_client {
|
||||
struct wl_client *client;
|
||||
|
|
@ -2795,33 +2834,6 @@ int
|
|||
weston_output_mode_set_native(struct weston_output *output,
|
||||
struct weston_mode *mode,
|
||||
int32_t scale);
|
||||
|
||||
int
|
||||
weston_output_set_vrr_mode(struct weston_output *output,
|
||||
enum weston_vrr_mode vrr_mode);
|
||||
|
||||
uint32_t
|
||||
weston_output_get_supported_vrr_modes(struct weston_output *output);
|
||||
|
||||
const struct weston_drm_format_array *
|
||||
weston_output_get_writeback_formats(struct weston_output *output);
|
||||
|
||||
void
|
||||
weston_compositor_arm_surface_counter_fps(struct weston_compositor *ec);
|
||||
|
||||
void
|
||||
weston_compositor_disarm_surface_counter_fps(struct weston_compositor *ec);
|
||||
|
||||
void
|
||||
weston_output_set_color_format(struct weston_output *output,
|
||||
enum weston_color_format color_format);
|
||||
|
||||
uint32_t
|
||||
weston_output_get_supported_color_formats(struct weston_output *output);
|
||||
|
||||
void
|
||||
weston_output_set_ready(struct weston_output *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,228 +0,0 @@
|
|||
/*
|
||||
* Copyright 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libweston/linalg-types.h>
|
||||
|
||||
/* ================= 3-vectors and 3x3 matrices ============== */
|
||||
|
||||
/** Construct a column vector from elements */
|
||||
#define WESTON_VEC3F(x, y, z) ((struct weston_vec3f){ .el = { (x), (y), (z) }})
|
||||
|
||||
/** Construct the [0, 0, 0]^T vector */
|
||||
#define WESTON_VEC3F_ZERO ((struct weston_vec3f){ .el = {}})
|
||||
|
||||
/** Construct matrix from elements a{row}{column} */
|
||||
#define WESTON_MAT3F(a00, a01, a02, \
|
||||
a10, a11, a12, \
|
||||
a20, a21, a22) \
|
||||
((struct weston_mat3f){ .colmaj = { \
|
||||
a00, a10, a20, \
|
||||
a01, a11, a21, \
|
||||
a02, a12, a22, \
|
||||
}})
|
||||
|
||||
/** Construct the identity 3x3 matrix */
|
||||
#define WESTON_MAT3F_IDENTITY \
|
||||
((struct weston_mat3f){ .colmaj = { \
|
||||
1.0f, 0.0f, 0.0f, \
|
||||
0.0f, 1.0f, 0.0f, \
|
||||
0.0f, 0.0f, 1.0f, \
|
||||
}})
|
||||
|
||||
/** Construct a diagonal matrix */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_diag(struct weston_vec3f d)
|
||||
{
|
||||
return WESTON_MAT3F(
|
||||
d.x, 0.0f, 0.0f,
|
||||
0.0f, d.y, 0.0f,
|
||||
0.0f, 0.0f, d.z);
|
||||
}
|
||||
|
||||
/** Copy the top-left 3x3 from 4x4 */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_from_m4f_xyz(struct weston_mat4f M)
|
||||
{
|
||||
return WESTON_MAT3F(
|
||||
M.col[0].el[0], M.col[1].el[0], M.col[2].el[0],
|
||||
M.col[0].el[1], M.col[1].el[1], M.col[2].el[1],
|
||||
M.col[0].el[2], M.col[1].el[2], M.col[2].el[2]
|
||||
);
|
||||
}
|
||||
|
||||
/** Drop w from vec4f */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_from_v4f_xyz(struct weston_vec4f v)
|
||||
{
|
||||
return WESTON_VEC3F(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
/** 3-vector dot product */
|
||||
static inline float
|
||||
weston_v3f_dot_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of vec3f into planar format
|
||||
*
|
||||
* Takes an array of RGB triplets and converts it into a planar format where all R
|
||||
* values come first, then all G values, then all B values.
|
||||
*
|
||||
* \param planar The destination array for planar data, must have space for 3 * len floats
|
||||
* \param arr Array of RGB triplets as vec3f structs
|
||||
* \param len Number of RGB triplets in the array
|
||||
*/
|
||||
static inline void
|
||||
weston_v3f_array_to_planar(float *planar, const struct weston_vec3f *arr, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
planar[i ] = arr[i].r;
|
||||
planar[i + len] = arr[i].g;
|
||||
planar[i + 2 * len] = arr[i].b;
|
||||
}
|
||||
}
|
||||
|
||||
/** Clamp each element to the range [a, b], replacing NaN with a. */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_clamp(struct weston_vec3f v, float a, float b)
|
||||
{
|
||||
return WESTON_VEC3F(v.x >= a ? (v.x <= b ? v.x : b) : a,
|
||||
v.y >= a ? (v.y <= b ? v.y : b) : a,
|
||||
v.z >= a ? (v.z <= b ? v.z : b) : a);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrix infinity-norm
|
||||
*
|
||||
* http://www.netlib.org/lapack/lug/node75.html
|
||||
*/
|
||||
static inline float
|
||||
weston_m3f_inf_norm(struct weston_mat3f M)
|
||||
{
|
||||
unsigned row;
|
||||
double infnorm = -1.0;
|
||||
|
||||
for (row = 0; row < 3; row++) {
|
||||
unsigned col;
|
||||
double sum = 0.0;
|
||||
|
||||
for (col = 0; col < 3; col++)
|
||||
sum += fabsf(M.col[col].el[row]);
|
||||
|
||||
if (infnorm < sum)
|
||||
infnorm = sum;
|
||||
}
|
||||
|
||||
return infnorm;
|
||||
}
|
||||
|
||||
/** Transpose 3x3 matrix */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_transpose(struct weston_mat3f M)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
R.col[j].el[i] = M.col[i].el[j];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
/** Matrix-vector multiplication A * b */
|
||||
static inline struct weston_vec3f
|
||||
weston_m3f_mul_v3f(struct weston_mat3f A, struct weston_vec3f b)
|
||||
{
|
||||
struct weston_vec3f result;
|
||||
unsigned r;
|
||||
|
||||
for (r = 0; r < 3; r++) {
|
||||
struct weston_vec3f row =
|
||||
WESTON_VEC3F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r]);
|
||||
result.el[r] = weston_v3f_dot_v3f(row, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Matrix multiplication A * B */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_mul_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||
{
|
||||
struct weston_mat3f result;
|
||||
unsigned c;
|
||||
|
||||
for (c = 0; c < 3; c++)
|
||||
result.col[c] = weston_m3f_mul_v3f(A, B.col[c]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Element-wise matrix subtraction A - B */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_sub_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 3 * 3; i++)
|
||||
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
/** Element-wise scalar multiplication */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_mul_scalar(struct weston_mat3f M, float scalar)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 3 * 3; i++)
|
||||
R.colmaj[i] = scalar * M.colmaj[i];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
bool
|
||||
weston_m3f_invert(struct weston_mat3f *out, struct weston_mat3f M);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -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
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/*
|
||||
* Copyright 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Column 3-vector */
|
||||
struct weston_vec3f {
|
||||
union {
|
||||
float el[3];
|
||||
struct {
|
||||
float x, y, z;
|
||||
};
|
||||
struct {
|
||||
float r, g, b;
|
||||
};
|
||||
struct {
|
||||
float Y, Cb, Cr;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/** 3x3 matrix, column-major */
|
||||
struct weston_mat3f {
|
||||
union {
|
||||
struct weston_vec3f col[3];
|
||||
float colmaj[3 * 3];
|
||||
};
|
||||
};
|
||||
|
||||
/** Column 4-vector */
|
||||
struct weston_vec4f {
|
||||
union {
|
||||
float el[4];
|
||||
struct {
|
||||
float x, y, z, w;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/** 4x4 matrix, column-major */
|
||||
struct weston_mat4f {
|
||||
union {
|
||||
struct weston_vec4f col[4];
|
||||
float colmaj[4 * 4];
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -75,13 +75,6 @@ weston_shell_utils_curtain_destroy(struct weston_curtain *curtain);
|
|||
enum weston_layer_position
|
||||
weston_shell_utils_view_get_layer_position(struct weston_view *view);
|
||||
|
||||
void
|
||||
weston_output_set_shell_private(struct weston_output *output,
|
||||
void *private_data);
|
||||
|
||||
void *
|
||||
weston_output_get_shell_private(struct weston_output *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -146,12 +146,6 @@ struct weston_log_scope *
|
|||
weston_log_scopes_iterate(struct weston_log_context *log_ctx,
|
||||
struct weston_log_scope *nscope);
|
||||
|
||||
void
|
||||
weston_add_scope_to_advertised_list(struct weston_log_context *ctx,
|
||||
const char *name);
|
||||
bool
|
||||
weston_log_scope_to_be_advertised(struct weston_log_context *ctx, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include "shared/helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "frontend/weston.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
|
||||
/* Representation of ivi_surface protocol object. */
|
||||
struct ivi_shell_surface
|
||||
|
|
@ -215,7 +214,7 @@ ivi_shell_surface_get_label(struct weston_surface *surface,
|
|||
{
|
||||
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
|
||||
|
||||
return snprintf(buf, len, "ivi-surface %u", shell_surf->id_surface);
|
||||
return snprintf(buf, len, "ivi-surface %#x", shell_surf->id_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -623,7 +622,7 @@ static void
|
|||
desktop_surface_ping_timeout(struct weston_desktop_client *client,
|
||||
void *user_data)
|
||||
{
|
||||
ivi_layout_desktop_surface_ping_timeout(client);
|
||||
/* Not supported */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -647,8 +646,6 @@ desktop_surface_added(struct weston_desktop_surface *surface,
|
|||
|
||||
ivisurf = xzalloc(sizeof *ivisurf);
|
||||
|
||||
weston_surface_set_label_func(weston_surf, weston_shell_utils_surface_get_label);
|
||||
|
||||
ivisurf->shell = shell;
|
||||
ivisurf->id_surface = IVI_INVALID_ID;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ xwayland_get_xwayland_name(struct kiosk_shell_surface *shsurf, enum window_atom_
|
|||
|
||||
static void
|
||||
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_output *shoutput);
|
||||
struct weston_output *output);
|
||||
static void
|
||||
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_surface *parent);
|
||||
|
|
@ -147,6 +147,9 @@ kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
|
|||
static void
|
||||
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
|
||||
struct kiosk_shell_surface *shroot);
|
||||
static struct kiosk_shell_output *
|
||||
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
|
||||
struct weston_output *output);
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
|
||||
|
|
@ -180,7 +183,7 @@ kiosk_shell_surface_get_parent_root(struct kiosk_shell_surface *shsurf)
|
|||
static bool
|
||||
kiosk_shell_output_has_app_id(char *config_app_ids, const char *app_id);
|
||||
|
||||
static struct kiosk_shell_output *
|
||||
static struct weston_output *
|
||||
kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput;
|
||||
|
|
@ -205,7 +208,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
|
||||
if (found_wm_name && found_wm_class) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -216,7 +219,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_name_app_ids,
|
||||
wm_name)) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -226,7 +229,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_class_app_ids,
|
||||
wm_class)) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -234,7 +237,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct kiosk_shell_output *
|
||||
static struct weston_output *
|
||||
kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct weston_output *output;
|
||||
|
|
@ -252,14 +255,14 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
|||
wl_list_for_each(shoutput, &shsurf->shell->output_list, link) {
|
||||
if (kiosk_shell_output_has_app_id(shoutput->app_ids, app_id)) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shoutput = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
|
||||
if (shoutput)
|
||||
return shoutput;
|
||||
output = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
|
||||
if (output)
|
||||
return output;
|
||||
|
||||
/* Group all related windows in the same output. */
|
||||
root = kiosk_shell_surface_get_parent_root(shsurf);
|
||||
|
|
@ -268,20 +271,20 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
|||
|
||||
output = weston_shell_utils_get_focused_output(shsurf->shell->compositor);
|
||||
if (output)
|
||||
return weston_output_get_shell_private(output);
|
||||
return output;
|
||||
|
||||
output = weston_shell_utils_get_default_output(shsurf->shell->compositor);
|
||||
if (output)
|
||||
return weston_output_get_shell_private(output);
|
||||
return output;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_output *shoutput)
|
||||
struct weston_output *output)
|
||||
{
|
||||
shsurf->output = shoutput;
|
||||
shsurf->output = output;
|
||||
|
||||
if (shsurf->output_destroy_listener.notify) {
|
||||
wl_list_remove(&shsurf->output_destroy_listener.link);
|
||||
|
|
@ -293,39 +296,39 @@ kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
|||
|
||||
shsurf->output_destroy_listener.notify =
|
||||
kiosk_shell_surface_notify_output_destroy;
|
||||
wl_signal_add(&shsurf->output->output->destroy_signal,
|
||||
wl_signal_add(&shsurf->output->destroy_signal,
|
||||
&shsurf->output_destroy_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_set_fullscreen(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_output *shoutput)
|
||||
struct weston_output *output)
|
||||
{
|
||||
if (!shoutput)
|
||||
shoutput = kiosk_shell_surface_find_best_output(shsurf);
|
||||
if (!output)
|
||||
output = kiosk_shell_surface_find_best_output(shsurf);
|
||||
|
||||
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_output(shsurf, output);
|
||||
|
||||
weston_desktop_surface_set_fullscreen(shsurf->desktop_surface, true);
|
||||
if (shsurf->output)
|
||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||
shsurf->output->output->width,
|
||||
shsurf->output->output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_set_maximized(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput =
|
||||
struct weston_output *output =
|
||||
kiosk_shell_surface_find_best_output(shsurf);
|
||||
|
||||
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_output(shsurf, output);
|
||||
|
||||
weston_desktop_surface_set_maximized(shsurf->desktop_surface, true);
|
||||
if (shsurf->output)
|
||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||
shsurf->output->output->width,
|
||||
shsurf->output->output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -379,7 +382,9 @@ static void
|
|||
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_surface *parent)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
kiosk_shell_find_shell_output(shsurf->shell,
|
||||
shsurf->output);
|
||||
struct kiosk_shell_surface *shroot = parent ?
|
||||
kiosk_shell_surface_get_parent_root(parent) :
|
||||
kiosk_shell_surface_get_parent_root(shsurf);
|
||||
|
|
@ -431,22 +436,20 @@ static void
|
|||
kiosk_shell_surface_reconfigure_for_output(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface;
|
||||
struct weston_output *w_output;
|
||||
|
||||
if (!shsurf->output)
|
||||
return;
|
||||
|
||||
w_output = shsurf->output->output;
|
||||
desktop_surface = shsurf->desktop_surface;
|
||||
|
||||
if (weston_desktop_surface_get_maximized(desktop_surface) ||
|
||||
weston_desktop_surface_get_fullscreen(desktop_surface)) {
|
||||
weston_desktop_surface_set_size(desktop_surface,
|
||||
w_output->width,
|
||||
w_output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
}
|
||||
|
||||
weston_shell_utils_center_on_output(shsurf->view, w_output);
|
||||
weston_shell_utils_center_on_output(shsurf->view, shsurf->output);
|
||||
weston_view_update_transform(shsurf->view);
|
||||
}
|
||||
|
||||
|
|
@ -527,7 +530,8 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
|
|||
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(dsurface);
|
||||
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
|
||||
|
||||
/* keyboard focus */
|
||||
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
|
||||
|
|
@ -820,11 +824,8 @@ kiosk_shell_output_create(struct kiosk_shell *shell, struct weston_output *outpu
|
|||
|
||||
wl_list_insert(shell->output_list.prev, &shoutput->link);
|
||||
|
||||
weston_output_set_shell_private(output, shoutput);
|
||||
|
||||
kiosk_shell_output_recreate_background(shoutput);
|
||||
kiosk_shell_output_configure(shoutput);
|
||||
weston_output_set_ready(output);
|
||||
|
||||
return shoutput;
|
||||
}
|
||||
|
|
@ -869,9 +870,6 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
|
|||
struct weston_layer *layer;
|
||||
struct weston_view *view;
|
||||
|
||||
if (!shsurf->output)
|
||||
return NULL;
|
||||
|
||||
wl_list_for_each(layer, layers, link) {
|
||||
struct kiosk_shell *shell = shsurf->shell;
|
||||
|
||||
|
|
@ -887,7 +885,7 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
|
|||
continue;
|
||||
|
||||
/* pick views only on the same output */
|
||||
if (view->output != shsurf->output->output)
|
||||
if (view->output != shsurf->output)
|
||||
continue;
|
||||
|
||||
view_shsurf = get_kiosk_shell_surface(view->surface);
|
||||
|
|
@ -949,7 +947,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
|
|||
|
||||
successor = find_focus_successor(shsurf,
|
||||
kiosk_seat->focused_surface);
|
||||
shoutput = shsurf->output;
|
||||
shoutput = kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
|
||||
if (shoutput && successor) {
|
||||
enum weston_layer_position succesor_view_layer_pos;
|
||||
|
||||
|
|
@ -993,17 +991,17 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
return;
|
||||
|
||||
if (!shsurf->appid_output_assigned && app_id) {
|
||||
struct kiosk_shell_output *shoutput = NULL;
|
||||
struct weston_output *output = NULL;
|
||||
|
||||
/* reset previous output being set in _added() as the output is
|
||||
* being cached */
|
||||
shsurf->output = NULL;
|
||||
shoutput = kiosk_shell_surface_find_best_output(shsurf);
|
||||
output = kiosk_shell_surface_find_best_output(shsurf);
|
||||
|
||||
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_output(shsurf, output);
|
||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||
shoutput->output->width,
|
||||
shoutput->output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
/* even if we couldn't find an appid set for a particular
|
||||
* output still flag the shsurf as to a avoid changing the
|
||||
* output every time */
|
||||
|
|
@ -1023,7 +1021,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
if (!weston_surface_is_mapped(surface) || (is_resized && is_fullscreen)) {
|
||||
if (is_fullscreen || !shsurf->xwayland.is_set) {
|
||||
weston_shell_utils_center_on_output(shsurf->view,
|
||||
shsurf->output->output);
|
||||
shsurf->output);
|
||||
} else {
|
||||
struct weston_coord_surface offset;
|
||||
struct weston_geometry geometry =
|
||||
|
|
@ -1042,7 +1040,9 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
if (!weston_surface_is_mapped(surface)) {
|
||||
struct weston_seat *seat =
|
||||
get_kiosk_shell_first_seat(shsurf->shell);
|
||||
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
kiosk_shell_find_shell_output(shsurf->shell,
|
||||
shsurf->output);
|
||||
struct kiosk_shell_seat *kiosk_seat;
|
||||
|
||||
weston_surface_map(surface);
|
||||
|
|
@ -1134,10 +1134,6 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
|
|||
{
|
||||
struct kiosk_shell_surface *shsurf =
|
||||
weston_desktop_surface_get_user_data(desktop_surface);
|
||||
struct kiosk_shell_output *shoutput = NULL;
|
||||
|
||||
if (output)
|
||||
shoutput = weston_output_get_shell_private(output);
|
||||
|
||||
/* We should normally be able to ignore fullscreen requests for
|
||||
* top-level surfaces, since we set them as fullscreen at creation
|
||||
|
|
@ -1152,7 +1148,7 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
|
|||
*/
|
||||
|
||||
if (!shsurf->parent || fullscreen)
|
||||
kiosk_shell_surface_set_fullscreen(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_fullscreen(shsurf, output);
|
||||
else
|
||||
kiosk_shell_surface_set_normal(shsurf);
|
||||
}
|
||||
|
|
@ -1236,6 +1232,20 @@ static const struct weston_desktop_api kiosk_shell_desktop_api = {
|
|||
* kiosk_shell
|
||||
*/
|
||||
|
||||
static struct kiosk_shell_output *
|
||||
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
|
||||
struct weston_output *output)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput;
|
||||
|
||||
wl_list_for_each(shoutput, &shell->output_list, link) {
|
||||
if (shoutput->output == output)
|
||||
return shoutput;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_activate_view(struct kiosk_shell *shell,
|
||||
struct weston_view *view,
|
||||
|
|
@ -1324,7 +1334,7 @@ kiosk_shell_handle_output_resized(struct wl_listener *listener, void *data)
|
|||
container_of(listener, struct kiosk_shell, output_resized_listener);
|
||||
struct weston_output *output = data;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
weston_output_get_shell_private(output);
|
||||
kiosk_shell_find_shell_output(shell, output);
|
||||
struct weston_view *view;
|
||||
|
||||
kiosk_shell_output_recreate_background(shoutput);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,26 @@
|
|||
#include "pixman-renderer.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "shared/weston-assert.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "linux-dmabuf.h"
|
||||
#include "linux-explicit-synchronization.h"
|
||||
#include "shared/xalloc.h"
|
||||
|
||||
static struct gbm_device *
|
||||
create_gbm_device(int fd)
|
||||
{
|
||||
struct gbm_device *gbm;
|
||||
|
||||
/* GBM will load a dri driver, but even though they need symbols from
|
||||
* libglapi, in some version of Mesa they are not linked to it. Since
|
||||
* only the gl-renderer module links to it, the call above won't make
|
||||
* these symbols globally available, and loading the DRI driver fails.
|
||||
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
|
||||
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
gbm = gbm_create_device(fd);
|
||||
|
||||
return gbm;
|
||||
}
|
||||
|
||||
/* When initializing EGL, if the preferred buffer format isn't available
|
||||
* we may be able to substitute an ARGB format for an XRGB one.
|
||||
|
|
@ -85,32 +99,12 @@ drm_backend_create_gl_renderer(struct drm_backend *b)
|
|||
&options.base);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_backend_create_vulkan_renderer(struct drm_backend *b)
|
||||
{
|
||||
const struct pixel_format_info *format[3] = {
|
||||
b->format,
|
||||
fallback_format_for(b->format),
|
||||
};
|
||||
struct vulkan_renderer_display_options options = {
|
||||
.formats = format,
|
||||
.formats_count = 1,
|
||||
};
|
||||
|
||||
if (format[1])
|
||||
options.formats_count = 2;
|
||||
|
||||
return weston_compositor_init_renderer(b->compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base);
|
||||
}
|
||||
|
||||
int
|
||||
init_egl(struct drm_backend *b)
|
||||
{
|
||||
struct drm_device *device = b->drm;
|
||||
|
||||
b->gbm = gbm_create_device(device->drm.fd);
|
||||
b->gbm = create_gbm_device(device->drm.fd);
|
||||
if (!b->gbm)
|
||||
return -1;
|
||||
|
||||
|
|
@ -123,24 +117,6 @@ init_egl(struct drm_backend *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
init_vulkan(struct drm_backend *b)
|
||||
{
|
||||
struct drm_device *device = b->drm;
|
||||
|
||||
b->gbm = gbm_create_device(device->drm.fd);
|
||||
if (!b->gbm)
|
||||
return -1;
|
||||
|
||||
if (drm_backend_create_vulkan_renderer(b) < 0) {
|
||||
gbm_device_destroy(b->gbm);
|
||||
b->gbm = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_output_fini_cursor_egl(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
|
@ -154,19 +130,6 @@ static void drm_output_fini_cursor_egl(struct drm_output *output)
|
|||
}
|
||||
}
|
||||
|
||||
static void drm_output_fini_cursor_vulkan(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
/* This cursor does not have a GBM device */
|
||||
if (output->gbm_cursor_fb[i] && !output->gbm_cursor_fb[i]->bo)
|
||||
output->gbm_cursor_fb[i]->type = BUFFER_PIXMAN_DUMB;
|
||||
drm_fb_unref(output->gbm_cursor_fb[i]);
|
||||
output->gbm_cursor_fb[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
|
|
@ -216,55 +179,6 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_cursor_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
struct drm_device *device = output->device;
|
||||
unsigned int i;
|
||||
|
||||
/* No point creating cursors if we don't have a plane for them. */
|
||||
if (!output->cursor_plane)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
struct gbm_bo *bo;
|
||||
|
||||
if (gbm_device_get_fd(b->gbm) != output->device->drm.fd) {
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_create_dumb(output->device,
|
||||
device->cursor_width,
|
||||
device->cursor_height,
|
||||
DRM_FORMAT_ARGB8888);
|
||||
/* Override buffer type, since we know it is a cursor */
|
||||
output->gbm_cursor_fb[i]->type = BUFFER_CURSOR;
|
||||
output->gbm_cursor_handle[i] =
|
||||
output->gbm_cursor_fb[i]->handles[0];
|
||||
} else {
|
||||
bo = gbm_bo_create(b->gbm, device->cursor_width, device->cursor_height,
|
||||
GBM_FORMAT_ARGB8888,
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
if (!bo)
|
||||
goto err;
|
||||
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_get_from_bo(bo, device, false, BUFFER_CURSOR);
|
||||
if (!output->gbm_cursor_fb[i]) {
|
||||
gbm_bo_destroy(bo);
|
||||
goto err;
|
||||
}
|
||||
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
weston_log("cursor buffers unavailable, using vulkan cursors\n");
|
||||
device->cursors_are_broken = true;
|
||||
drm_output_fini_cursor_vulkan(output);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
||||
{
|
||||
|
|
@ -315,213 +229,26 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
|||
output->gbm_bo_flags);
|
||||
}
|
||||
|
||||
enum format_alpha_required {
|
||||
FORMAT_ALPHA_REQUIRED = true,
|
||||
FORMAT_ALPHA_NOT_REQUIRED = false,
|
||||
};
|
||||
|
||||
enum format_component_type {
|
||||
FORMAT_COMPONENT_TYPE_ANY,
|
||||
FORMAT_COMPONENT_TYPE_FLOAT_ONLY,
|
||||
};
|
||||
|
||||
static const struct pixel_format_info *
|
||||
find_compatible_format(struct weston_compositor *compositor,
|
||||
struct wl_array *formats, int min_bpc,
|
||||
enum format_component_type component_type,
|
||||
enum format_alpha_required alpha_required)
|
||||
{
|
||||
const struct pixel_format_info **tmp, *p;
|
||||
const struct pixel_format_info *candidate = NULL;
|
||||
|
||||
/**
|
||||
* Given a format array, this looks for a format respecting a few
|
||||
* criteria. First of all, this ignores formats that do not contain an
|
||||
* alpha channel when alpha_required == FORMAT_ALPHA_REQUIRED. Similar
|
||||
* for formats that are not floating point when component_type ==
|
||||
* FORMAT_COMPONENT_TYPE_FLOAT_ONLY. Also, it ignores formats that do
|
||||
* not have bits per color channel (bpc) bigger or equal to min_bpc.
|
||||
*
|
||||
* When we have multiple formats matching these criteria, we use the
|
||||
* following to choose:
|
||||
*
|
||||
* 1. a format with lower bytes per pixel (bpp) is favored.
|
||||
*
|
||||
* 2. if FORMAT_ALPHA_REQUIRED:
|
||||
* we prefer the format with more bits on the alpha channel
|
||||
* else
|
||||
* we prefer the format with more bits on the color channels
|
||||
*/
|
||||
wl_array_for_each(tmp, formats) {
|
||||
p = *tmp;
|
||||
|
||||
/* Skip candidates that do not match minimum criteria. */
|
||||
if (component_type == FORMAT_COMPONENT_TYPE_FLOAT_ONLY &&
|
||||
p->component_type != PIXEL_COMPONENT_TYPE_FLOAT)
|
||||
continue;
|
||||
if (alpha_required == FORMAT_ALPHA_REQUIRED && p->bits.a == 0)
|
||||
continue;
|
||||
if (p->bits.r < min_bpc || p->bits.g < min_bpc || p->bits.b < min_bpc)
|
||||
continue;
|
||||
|
||||
/* No other good candidate so far, so pick this one. */
|
||||
if (!candidate) {
|
||||
candidate = p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* New candidate, let's compare with old and untie.
|
||||
*/
|
||||
|
||||
if (p->bpp > candidate->bpp)
|
||||
continue;
|
||||
|
||||
if (alpha_required == FORMAT_ALPHA_REQUIRED) {
|
||||
if (p->bits.a <= candidate->bits.a)
|
||||
continue;
|
||||
} else {
|
||||
if (p->bits.r + p->bits.g + p->bits.b <=
|
||||
candidate->bits.r + candidate->bits.g + candidate->bits.b)
|
||||
continue;
|
||||
}
|
||||
|
||||
candidate = p;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
static bool
|
||||
drm_output_pick_format_egl(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_backend *b = device->backend;
|
||||
struct weston_compositor *compositor = b->compositor;
|
||||
const struct weston_renderer *renderer = compositor->renderer;
|
||||
const struct pixel_format_info **renderer_formats;
|
||||
const struct pixel_format_info **f;
|
||||
unsigned int renderer_formats_count;
|
||||
struct wl_array supported_formats;
|
||||
enum format_component_type component_type;
|
||||
uint32_t min_bpc;
|
||||
unsigned int i;
|
||||
bool ret = true;
|
||||
bool found;
|
||||
|
||||
wl_array_init(&supported_formats);
|
||||
|
||||
/**
|
||||
* This computes the intersection between renderer formats supported by
|
||||
* EGL and the output->scanout_plane supported formats. We need that as
|
||||
* we want to select a format supported by both.
|
||||
*/
|
||||
renderer_formats =
|
||||
renderer->gl->get_supported_rendering_formats(b->compositor,
|
||||
&renderer_formats_count);
|
||||
for (i = 0; i < renderer_formats_count; i++) {
|
||||
if (!weston_drm_format_array_find_format(&output->scanout_plane->formats,
|
||||
renderer_formats[i]->format))
|
||||
continue;
|
||||
|
||||
f = wl_array_add(&supported_formats, sizeof(*f));
|
||||
*f = renderer_formats[i];
|
||||
}
|
||||
|
||||
if (output->base.from_blend_to_output_by_backend) {
|
||||
component_type = FORMAT_COMPONENT_TYPE_FLOAT_ONLY;
|
||||
min_bpc = 16;
|
||||
} else if (output->base.eotf_mode != WESTON_EOTF_MODE_SDR) {
|
||||
component_type = FORMAT_COMPONENT_TYPE_ANY;
|
||||
min_bpc = 10;
|
||||
} else {
|
||||
/**
|
||||
* If no requirements, we simply use b->format instead of
|
||||
* looking for a format with bpc >= min_bpc.
|
||||
*/
|
||||
min_bpc = 0;
|
||||
}
|
||||
|
||||
if (min_bpc != 0) {
|
||||
if (b->has_underlay) {
|
||||
output->format =
|
||||
find_compatible_format(compositor, &supported_formats,
|
||||
min_bpc, component_type,
|
||||
FORMAT_ALPHA_REQUIRED);
|
||||
if (output->format)
|
||||
goto done;
|
||||
|
||||
weston_log("Disabling underlay planes: EGL GBM or the primary plane for output '%s'\n" \
|
||||
"does not support format with min bpc %u and alpha channel.\n",
|
||||
output->base.name, min_bpc);
|
||||
b->has_underlay = false;
|
||||
}
|
||||
|
||||
output->format =
|
||||
find_compatible_format(compositor, &supported_formats,
|
||||
min_bpc, component_type,
|
||||
FORMAT_ALPHA_NOT_REQUIRED);
|
||||
if (output->format)
|
||||
goto done;
|
||||
|
||||
weston_log("Error: EGL GBM or the primary plane for output '%s' does not support format\n" \
|
||||
"with min bpc %u.\n", output->base.name, min_bpc);
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
found = false;
|
||||
wl_array_for_each(f, &supported_formats) {
|
||||
if ((*f)->format == b->format->format) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
weston_log("Error: format %s unsupported by EGL GBM or the primary plane for output '%s'.\n",
|
||||
b->format->drm_format_name, output->base.name);
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (b->has_underlay && (b->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: b->format %s does not have alpha channel,\n"
|
||||
"which is required to support underlay planes.\n",
|
||||
b->format->drm_format_name);
|
||||
b->has_underlay = false;
|
||||
}
|
||||
|
||||
output->format = b->format;
|
||||
|
||||
done:
|
||||
wl_array_release(&supported_formats);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Init output state that depends on gl or gbm */
|
||||
int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
const struct weston_mode *mode = output->base.current_mode;
|
||||
const struct pixel_format_info *format[2] = { 0 };
|
||||
struct gl_renderer_output_options options;
|
||||
|
||||
if (!output->format && !drm_output_pick_format_egl(output))
|
||||
return -1;
|
||||
|
||||
format[0] = output->format;
|
||||
if (!b->has_underlay)
|
||||
format[1] = fallback_format_for(output->format);
|
||||
|
||||
options.formats = format;
|
||||
options.formats_count = format[1] ? 2 : 1;
|
||||
options.area.x = 0;
|
||||
options.area.y = 0;
|
||||
options.area.width = mode->width;
|
||||
options.area.height = mode->height;
|
||||
options.fb_size.width = mode->width;
|
||||
options.fb_size.height = mode->height;
|
||||
const struct pixel_format_info *format[2] = {
|
||||
output->format,
|
||||
fallback_format_for(output->format),
|
||||
};
|
||||
struct gl_renderer_output_options options = {
|
||||
.formats = format,
|
||||
.formats_count = 1,
|
||||
.area.x = 0,
|
||||
.area.y = 0,
|
||||
.area.width = mode->width,
|
||||
.area.height = mode->height,
|
||||
.fb_size.width = mode->width,
|
||||
.fb_size.height = mode->height,
|
||||
};
|
||||
|
||||
assert(output->gbm_surface == NULL);
|
||||
create_gbm_surface(b->gbm, output);
|
||||
|
|
@ -530,6 +257,8 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (options.formats[1])
|
||||
options.formats_count = 2;
|
||||
options.window_for_legacy = (EGLNativeWindowType) output->gbm_surface;
|
||||
options.window_for_platform = output->gbm_surface;
|
||||
if (renderer->gl->output_window_create(&output->base, &options) < 0) {
|
||||
|
|
@ -544,208 +273,6 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct gbm_bo *
|
||||
drm_gbm_create_bo(struct gbm_device *gbm, struct drm_output *output)
|
||||
{
|
||||
struct weston_mode *mode = output->base.current_mode;
|
||||
struct drm_plane *plane = output->scanout_plane;
|
||||
struct weston_drm_format *fmt;
|
||||
const uint64_t *modifiers;
|
||||
unsigned int num_modifiers;
|
||||
struct gbm_bo *bo = NULL;
|
||||
|
||||
/*
|
||||
* TODO: Currently, this method allocates a buffer based on the list
|
||||
* of acceptable modifiers received from the DRM backend but does not
|
||||
* check it against formats renderable by the renderer.
|
||||
* To support cases where the renderer may not support the same
|
||||
* modifiers (e.g. Vulkan software renderer) it should match against
|
||||
* renderer modifiers.
|
||||
*/
|
||||
|
||||
fmt = weston_drm_format_array_find_format(&plane->formats,
|
||||
output->format->format);
|
||||
if (!fmt) {
|
||||
weston_log("format %s not supported by output %s\n",
|
||||
output->format->drm_format_name,
|
||||
output->base.name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
|
||||
modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
|
||||
bo = gbm_bo_create_with_modifiers(gbm, mode->width, mode->height,
|
||||
output->format->format,
|
||||
modifiers, num_modifiers);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we cannot use modifiers to allocate the GBM surface and
|
||||
* the GBM device differs from the KMS display device, try to
|
||||
* use linear buffers and hope that the allocated GBM surface
|
||||
* is correctly displayed on the KMS device.
|
||||
*/
|
||||
if (gbm_device_get_fd(gbm) != output->device->drm.fd)
|
||||
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
|
||||
|
||||
if (!bo) {
|
||||
bo = gbm_bo_create(gbm, mode->width, mode->height,
|
||||
output->format->format, output->gbm_bo_flags);
|
||||
}
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
struct drm_gbm_dmabuf {
|
||||
struct linux_dmabuf_memory base;
|
||||
struct gbm_bo *bo;
|
||||
};
|
||||
|
||||
static void
|
||||
drm_gbm_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
|
||||
{
|
||||
struct dmabuf_attributes *attributes;
|
||||
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||
struct gbm_bo *bo;
|
||||
|
||||
drm_gbm_dmabuf = container_of(dmabuf, struct drm_gbm_dmabuf, base);
|
||||
bo = drm_gbm_dmabuf->bo;
|
||||
assert(bo);
|
||||
|
||||
gbm_bo_destroy(bo);
|
||||
|
||||
attributes = dmabuf->attributes;
|
||||
for (int i = 0; i < attributes->n_planes; ++i)
|
||||
close(attributes->fd[i]);
|
||||
free(dmabuf->attributes);
|
||||
|
||||
free(dmabuf);
|
||||
}
|
||||
|
||||
static struct drm_gbm_dmabuf *
|
||||
drm_gbm_bo_get_dmabuf(struct gbm_device *gbm, struct drm_output *output, struct gbm_bo *bo)
|
||||
{
|
||||
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||
struct dmabuf_attributes *attributes;
|
||||
|
||||
attributes = xzalloc(sizeof(*attributes));
|
||||
attributes->width = gbm_bo_get_width(bo);
|
||||
attributes->height = gbm_bo_get_height(bo);
|
||||
attributes->format = gbm_bo_get_format(bo);
|
||||
attributes->n_planes = gbm_bo_get_plane_count(bo);
|
||||
for (int i = 0; i < attributes->n_planes; ++i) {
|
||||
attributes->fd[i] = gbm_bo_get_fd(bo);
|
||||
attributes->stride[i] = gbm_bo_get_stride_for_plane(bo, i);
|
||||
attributes->offset[i] = gbm_bo_get_offset(bo, i);
|
||||
}
|
||||
attributes->modifier = gbm_bo_get_modifier(bo);
|
||||
|
||||
drm_gbm_dmabuf = xzalloc(sizeof(*drm_gbm_dmabuf));
|
||||
drm_gbm_dmabuf->base.attributes = attributes;
|
||||
drm_gbm_dmabuf->base.destroy = drm_gbm_dmabuf_destroy;
|
||||
drm_gbm_dmabuf->bo = bo;
|
||||
|
||||
return drm_gbm_dmabuf;
|
||||
}
|
||||
|
||||
static void
|
||||
create_renderbuffers(struct gbm_device *gbm, struct drm_output *output, unsigned int n)
|
||||
{
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||
struct gbm_bo *bo;
|
||||
|
||||
bo = drm_gbm_create_bo(gbm, output);
|
||||
if (!bo) {
|
||||
weston_log("failed to allocate bo\n");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_gbm_dmabuf = drm_gbm_bo_get_dmabuf(gbm, output, bo);
|
||||
if (!drm_gbm_dmabuf) {
|
||||
weston_log("failed to allocate dmabuf\n");
|
||||
return;
|
||||
}
|
||||
|
||||
output->renderbuffer[i] =
|
||||
renderer->create_renderbuffer_dmabuf(&output->base,
|
||||
&drm_gbm_dmabuf->base,
|
||||
NULL, NULL);
|
||||
if (!output->renderbuffer[i]) {
|
||||
weston_log("failed to allocate renderbuffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
output->linux_dmabuf_memory[i] = &drm_gbm_dmabuf->base;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
drm_output_pick_format_vulkan(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_backend *b = device->backend;
|
||||
|
||||
/* Any other value of eotf_mode requires color-management, which is not
|
||||
* yet supported by vulkan-renderer. */
|
||||
assert(output->base.eotf_mode == WESTON_EOTF_MODE_SDR);
|
||||
|
||||
if (!b->format->vulkan_format) {
|
||||
weston_log("Error: failed to pick format for output '%s', format %s unsupported by vulkan-renderer.\n",
|
||||
output->base.name, b->format->drm_format_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(b->format);
|
||||
output->format = b->format;
|
||||
|
||||
if (b->has_underlay && (output->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: output '%s' with format %s does not have alpha channel,\n"
|
||||
"which is required to support underlay planes.\n",
|
||||
output->base.name, output->format->drm_format_name);
|
||||
b->has_underlay = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Init output state that depends on vulkan */
|
||||
int
|
||||
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
const struct weston_mode *mode = output->base.current_mode;
|
||||
struct weston_renderer *renderer = b->compositor->renderer;
|
||||
|
||||
if (!output->format && !drm_output_pick_format_vulkan(output))
|
||||
return -1;
|
||||
|
||||
const struct vulkan_renderer_surfaceless_options options = {
|
||||
.area.x = 0,
|
||||
.area.y = 0,
|
||||
.area.width = mode->width,
|
||||
.area.height = mode->height,
|
||||
.fb_size.width = mode->width,
|
||||
.fb_size.height = mode->height,
|
||||
};
|
||||
|
||||
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||
weston_log("failed to create vulkan renderer output state\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
create_renderbuffers(b->gbm, output, ARRAY_LENGTH(output->renderbuffer));
|
||||
if (!output->linux_dmabuf_memory[0]) {
|
||||
weston_log("failed to create dmabufs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
drm_output_init_cursor_vulkan(output, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
drm_output_fini_egl(struct drm_output *output)
|
||||
{
|
||||
|
|
@ -766,26 +293,6 @@ drm_output_fini_egl(struct drm_output *output)
|
|||
drm_output_fini_cursor_egl(output);
|
||||
}
|
||||
|
||||
void
|
||||
drm_output_fini_vulkan(struct drm_output *output)
|
||||
{
|
||||
struct drm_backend *b = output->backend;
|
||||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
|
||||
if (!b->compositor->shutting_down &&
|
||||
output->scanout_plane->state_cur->fb &&
|
||||
output->scanout_plane->state_cur->fb->type == BUFFER_DMABUF_BACKEND) {
|
||||
drm_plane_reset_state(output->scanout_plane);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH(output->renderbuffer); i++)
|
||||
renderer->destroy_renderbuffer(output->renderbuffer[i]);
|
||||
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
|
||||
drm_output_fini_cursor_vulkan(output);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
|
|
@ -817,36 +324,3 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct drm_device *device = output->device;
|
||||
struct linux_dmabuf_memory *dmabuf;
|
||||
struct drm_fb *ret;
|
||||
|
||||
output->base.compositor->renderer->repaint_output(&output->base,
|
||||
damage,
|
||||
output->renderbuffer[output->current_image]);
|
||||
|
||||
dmabuf = output->linux_dmabuf_memory[output->current_image];
|
||||
if (!dmabuf) {
|
||||
weston_log("failed to get dmabuf\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Output transparent/opaque image according to the format required by
|
||||
* the client. */
|
||||
ret = drm_fb_get_from_dmabuf_attributes(dmabuf->attributes, device,
|
||||
!output->format->opaque_substitute,
|
||||
false, true, NULL);
|
||||
if (!ret) {
|
||||
weston_log("failed to get drm_fb for dmabuf\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
output->current_image = (output->current_image + 1) % ARRAY_LENGTH(output->renderbuffer);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,10 +78,6 @@
|
|||
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
|
||||
#endif
|
||||
|
||||
#ifndef MAX_DMABUF_PLANES
|
||||
#define MAX_DMABUF_PLANES 4
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A small wrapper to print information into the 'drm-backend' debug scope.
|
||||
*
|
||||
|
|
@ -153,6 +149,27 @@ struct drm_property_info {
|
|||
uint64_t range_values[2];
|
||||
};
|
||||
|
||||
/**
|
||||
* Reasons why placing a view on a plane failed. Needed by the dma-buf feedback.
|
||||
*/
|
||||
enum try_view_on_plane_failure_reasons {
|
||||
FAILURE_REASONS_NONE = 0,
|
||||
FAILURE_REASONS_FORCE_RENDERER = 1 << 0,
|
||||
FAILURE_REASONS_FB_FORMAT_INCOMPATIBLE = 1 << 1,
|
||||
FAILURE_REASONS_DMABUF_MODIFIER_INVALID = 1 << 2,
|
||||
FAILURE_REASONS_ADD_FB_FAILED = 1 << 3,
|
||||
FAILURE_REASONS_NO_PLANES_AVAILABLE = 1 << 4,
|
||||
FAILURE_REASONS_PLANES_REJECTED = 1 << 5,
|
||||
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION = 1 << 6,
|
||||
FAILURE_REASONS_INCOMPATIBLE_TRANSFORM = 1 << 7,
|
||||
FAILURE_REASONS_NO_BUFFER = 1 << 8,
|
||||
FAILURE_REASONS_BUFFER_TYPE = 1 << 9,
|
||||
FAILURE_REASONS_GLOBAL_ALPHA = 1 << 10,
|
||||
FAILURE_REASONS_NO_GBM = 1 << 11,
|
||||
FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 12,
|
||||
FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 13,
|
||||
};
|
||||
|
||||
/**
|
||||
* We use this to keep track of actions we need to do with the dma-buf feedback
|
||||
* in order to keep it up-to-date with the info we get from the DRM-backend.
|
||||
|
|
@ -163,12 +180,6 @@ enum actions_needed_dmabuf_feedback {
|
|||
ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
|
||||
};
|
||||
|
||||
enum drm_plane_subtype {
|
||||
PLANE_SUBTYPE_OVERLAY_ONLY = 0,
|
||||
PLANE_SUBTYPE_UNDERLAY_ONLY = 1,
|
||||
PLANE_SUBTYPE_BOTH = 2,
|
||||
};
|
||||
|
||||
struct drm_device {
|
||||
struct drm_backend *backend;
|
||||
|
||||
|
|
@ -221,9 +232,6 @@ struct drm_device {
|
|||
|
||||
/* drm_backend::kms_list */
|
||||
struct wl_list link;
|
||||
|
||||
/* struct drm_colorop_3x1d_lut::link */
|
||||
struct wl_list drm_colorop_3x1d_lut_list;
|
||||
};
|
||||
|
||||
struct drm_backend {
|
||||
|
|
@ -245,8 +253,6 @@ struct drm_backend {
|
|||
|
||||
bool use_pixman_shadow;
|
||||
|
||||
bool offload_blend_to_output;
|
||||
|
||||
struct udev_input input;
|
||||
|
||||
uint32_t pageflip_timeout;
|
||||
|
|
@ -255,15 +261,6 @@ struct drm_backend {
|
|||
bool has_underlay;
|
||||
|
||||
struct weston_log_scope *debug;
|
||||
|
||||
struct {
|
||||
uint32_t frame_counter_interval;
|
||||
struct wl_event_source *pageflip_timer_counter;
|
||||
bool timer_armed;
|
||||
} perf_page_flips_stats;
|
||||
|
||||
/* True if we need a workaround for some very old kernels */
|
||||
bool stale_timestamp_workaround;
|
||||
};
|
||||
|
||||
struct drm_mode {
|
||||
|
|
@ -276,7 +273,6 @@ enum drm_fb_type {
|
|||
BUFFER_INVALID = 0, /**< never used */
|
||||
BUFFER_CLIENT, /**< directly sourced from client */
|
||||
BUFFER_DMABUF, /**< imported from linux_dmabuf client */
|
||||
BUFFER_DMABUF_BACKEND, /**< imported from dmabuf renderbuffer */
|
||||
BUFFER_PIXMAN_DUMB, /**< internal Pixman rendering */
|
||||
BUFFER_GBM_SURFACE, /**< internal EGL rendering */
|
||||
BUFFER_CURSOR, /**< internal cursor buffer */
|
||||
|
|
@ -291,9 +287,9 @@ struct drm_fb {
|
|||
int refcnt;
|
||||
|
||||
uint32_t fb_id, size;
|
||||
uint32_t handles[MAX_DMABUF_PLANES];
|
||||
uint32_t strides[MAX_DMABUF_PLANES];
|
||||
uint32_t offsets[MAX_DMABUF_PLANES];
|
||||
uint32_t handles[4];
|
||||
uint32_t strides[4];
|
||||
uint32_t offsets[4];
|
||||
int num_planes;
|
||||
const struct pixel_format_info *format;
|
||||
uint64_t modifier;
|
||||
|
|
@ -306,12 +302,6 @@ struct drm_fb {
|
|||
struct gbm_bo *bo;
|
||||
struct gbm_surface *gbm_surface;
|
||||
|
||||
/* Used when direct-display extension is turned on for that dmabuf */
|
||||
bool direct_display;
|
||||
int fds[MAX_DMABUF_PLANES];
|
||||
/* tracks how many fds we've dup'ed */
|
||||
int num_duped_fds;
|
||||
|
||||
/* Used by dumb fbs */
|
||||
void *map;
|
||||
};
|
||||
|
|
@ -339,15 +329,6 @@ struct drm_pending_state {
|
|||
struct wl_list output_list;
|
||||
};
|
||||
|
||||
enum drm_output_propose_state_mode {
|
||||
DRM_OUTPUT_PROPOSE_STATE_INVALID = 0, /**< Invalid state */
|
||||
DRM_OUTPUT_PROPOSE_STATE_MIXED, /**< mix renderer & planes */
|
||||
DRM_OUTPUT_PROPOSE_STATE_RENDERER_AND_CURSOR, /**< only assign to renderer & cursor plane */
|
||||
DRM_OUTPUT_PROPOSE_STATE_RENDERER_ONLY, /**< only assign to renderer */
|
||||
DRM_OUTPUT_PROPOSE_STATE_PLANES_ONLY, /**< no renderer use, only planes */
|
||||
DRM_OUTPUT_PROPOSE_STATE_REUSE = 128, /**< bit indicates reuse prior state with new buffers */
|
||||
};
|
||||
|
||||
/*
|
||||
* Output state holds the dynamic state for one Weston output, i.e. a KMS CRTC,
|
||||
* plus >= 1 each of encoder/connector/plane. Since everything but the planes
|
||||
|
|
@ -361,13 +342,11 @@ enum drm_output_propose_state_mode {
|
|||
struct drm_output_state {
|
||||
struct drm_pending_state *pending_state;
|
||||
struct drm_output *output;
|
||||
enum drm_output_propose_state_mode mode;
|
||||
struct wl_list link;
|
||||
enum dpms_enum dpms;
|
||||
enum weston_hdcp_protection protection;
|
||||
struct wl_list plane_list;
|
||||
bool tear;
|
||||
bool planes_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -400,9 +379,6 @@ struct drm_plane_state {
|
|||
uint64_t zpos;
|
||||
uint16_t alpha;
|
||||
|
||||
enum wdrm_plane_color_encoding color_encoding;
|
||||
enum wdrm_plane_color_range color_range;
|
||||
|
||||
bool complete;
|
||||
|
||||
/* We don't own the fd, so we shouldn't close it */
|
||||
|
|
@ -434,8 +410,6 @@ struct drm_plane {
|
|||
struct drm_device *device;
|
||||
|
||||
enum wdrm_plane_type type;
|
||||
/* Whether this plane supports overlay, underlay, or both */
|
||||
enum drm_plane_subtype subtype;
|
||||
|
||||
uint32_t possible_crtcs;
|
||||
uint32_t plane_id;
|
||||
|
|
@ -443,6 +417,8 @@ struct drm_plane {
|
|||
uint32_t crtc_id;
|
||||
|
||||
struct drm_property_info props[WDRM_PLANE__COUNT];
|
||||
/* True if the plane's zpos_max < primary plane's zpos_min. */
|
||||
bool is_underlay;
|
||||
|
||||
/* The last state submitted to the kernel for this plane. */
|
||||
struct drm_plane_state *state_cur;
|
||||
|
|
@ -516,19 +492,6 @@ struct drm_writeback {
|
|||
struct weston_drm_format_array formats;
|
||||
};
|
||||
|
||||
struct drm_colorop_3x1d_lut {
|
||||
/* drm_device::drm_colorop_3x1d_lut_list */
|
||||
struct wl_list link;
|
||||
struct drm_device *device;
|
||||
|
||||
uint64_t lut_size;
|
||||
|
||||
struct weston_color_transform *xform;
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
uint32_t blob_id;
|
||||
};
|
||||
|
||||
struct drm_head {
|
||||
struct weston_head base;
|
||||
struct drm_connector connector;
|
||||
|
|
@ -559,9 +522,6 @@ struct drm_crtc {
|
|||
|
||||
/* Holds the properties for the CRTC */
|
||||
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
|
||||
|
||||
/* CRTC prop WDRM_CRTC_GAMMA_LUT_SIZE */
|
||||
uint32_t lut_size;
|
||||
};
|
||||
|
||||
struct drm_output {
|
||||
|
|
@ -588,7 +548,6 @@ struct drm_output {
|
|||
int current_cursor;
|
||||
|
||||
struct gbm_surface *gbm_surface;
|
||||
struct linux_dmabuf_memory *linux_dmabuf_memory[2];
|
||||
const struct pixel_format_info *format;
|
||||
uint32_t gbm_bo_flags;
|
||||
|
||||
|
|
@ -598,9 +557,8 @@ struct drm_output {
|
|||
unsigned max_bpc;
|
||||
enum wdrm_colorspace connector_colorspace;
|
||||
|
||||
bool deprecated_gamma_is_set;
|
||||
bool legacy_gamma_not_supported;
|
||||
uint16_t legacy_gamma_size;
|
||||
struct drm_colorop_3x1d_lut *blend_to_output_xform;
|
||||
|
||||
/* Plane being displayed directly on the CRTC */
|
||||
struct drm_plane *scanout_plane;
|
||||
|
|
@ -615,7 +573,7 @@ struct drm_output {
|
|||
struct drm_writeback_state *wb_state;
|
||||
|
||||
struct drm_fb *dumb[2];
|
||||
weston_renderbuffer_t renderbuffer[2];
|
||||
struct weston_renderbuffer *renderbuffer[2];
|
||||
int current_image;
|
||||
|
||||
struct vaapi_recorder *recorder;
|
||||
|
|
@ -623,12 +581,6 @@ struct drm_output {
|
|||
|
||||
struct wl_event_source *pageflip_timer;
|
||||
|
||||
/* how many page flips */
|
||||
uint32_t page_flips_counted;
|
||||
|
||||
/* how many page flips / interval */
|
||||
float page_flips_per_timer_interval;
|
||||
|
||||
bool is_virtual;
|
||||
void (*virtual_destroy)(struct weston_output *base);
|
||||
|
||||
|
|
@ -704,18 +656,7 @@ drm_output_get_plane_type_name(struct drm_plane *p)
|
|||
case WDRM_PLANE_TYPE_CURSOR:
|
||||
return "cursor";
|
||||
case WDRM_PLANE_TYPE_OVERLAY:
|
||||
switch (p->subtype) {
|
||||
case PLANE_SUBTYPE_OVERLAY_ONLY:
|
||||
return "overlay";
|
||||
case PLANE_SUBTYPE_UNDERLAY_ONLY:
|
||||
return "underlay";
|
||||
case PLANE_SUBTYPE_BOTH:
|
||||
return "over/underlay";
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
// fall through
|
||||
return p->is_underlay ? "underlay" : "overlay";
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
|
|
@ -807,6 +748,10 @@ drm_pending_state_apply(struct drm_pending_state *pending_state);
|
|||
int
|
||||
drm_pending_state_apply_sync(struct drm_pending_state *pending_state);
|
||||
|
||||
void
|
||||
drm_output_set_gamma(struct weston_output *output_base,
|
||||
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
|
||||
|
||||
void
|
||||
drm_output_update_msc(struct drm_output *output, unsigned int seq);
|
||||
void
|
||||
|
|
@ -823,11 +768,6 @@ drm_fb_unref(struct drm_fb *fb);
|
|||
struct drm_fb *
|
||||
drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
||||
uint32_t format);
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
uint32_t *try_view_on_plane_failure_reasons);
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
||||
bool is_opaque, enum drm_fb_type type);
|
||||
|
|
@ -844,23 +784,15 @@ wdrm_colorspace_from_output(struct weston_output *output);
|
|||
#ifdef BUILD_DRM_GBM
|
||||
extern struct drm_fb *
|
||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
uint32_t *try_view_on_plane_failure_reasons);
|
||||
struct weston_paint_node *pnode);
|
||||
|
||||
extern bool
|
||||
drm_can_scanout_dmabuf(struct weston_backend *backend,
|
||||
struct linux_dmabuf_buffer *dmabuf);
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
bool direct_display, bool is_internal,
|
||||
uint32_t *try_view_on_plane_failure_reasons);
|
||||
#else
|
||||
static inline struct drm_fb *
|
||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
struct weston_paint_node *pnode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -917,7 +849,7 @@ void
|
|||
drm_plane_state_free(struct drm_plane_state *state, bool force);
|
||||
void
|
||||
drm_plane_state_put_back(struct drm_plane_state *state);
|
||||
void
|
||||
bool
|
||||
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||
struct weston_paint_node *node,
|
||||
uint64_t zpos);
|
||||
|
|
@ -930,14 +862,6 @@ drm_assign_planes(struct weston_output *output_base);
|
|||
bool
|
||||
drm_plane_is_available(struct drm_plane *plane, struct drm_output *output);
|
||||
|
||||
bool
|
||||
drm_plane_supports_color_encoding(struct drm_plane *plane,
|
||||
enum wdrm_plane_color_encoding encoding);
|
||||
|
||||
bool
|
||||
drm_plane_supports_color_range(struct drm_plane *plane,
|
||||
enum wdrm_plane_color_range range);
|
||||
|
||||
void
|
||||
drm_output_render(struct drm_output_state *state);
|
||||
|
||||
|
|
@ -969,18 +893,6 @@ drm_output_fini_egl(struct drm_output *output);
|
|||
struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage);
|
||||
|
||||
int
|
||||
init_vulkan(struct drm_backend *b);
|
||||
|
||||
int
|
||||
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b);
|
||||
|
||||
void
|
||||
drm_output_fini_vulkan(struct drm_output *output);
|
||||
|
||||
struct drm_fb *
|
||||
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage);
|
||||
|
||||
#else
|
||||
inline static int
|
||||
init_egl(struct drm_backend *b)
|
||||
|
|
@ -1005,29 +917,4 @@ drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inline static int
|
||||
init_vulkan(struct drm_backend *b)
|
||||
{
|
||||
weston_log("Compiled without GBM support\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline static int
|
||||
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline static void
|
||||
drm_output_fini_vulkan(struct drm_output *output)
|
||||
{
|
||||
}
|
||||
|
||||
inline static struct drm_fb *
|
||||
drm_output_render_vulkan(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ enum wdrm_plane_property {
|
|||
WDRM_PLANE_ZPOS,
|
||||
WDRM_PLANE_ROTATION,
|
||||
WDRM_PLANE_ALPHA,
|
||||
WDRM_PLANE_COLOR_ENCODING,
|
||||
WDRM_PLANE_COLOR_RANGE,
|
||||
WDRM_PLANE__COUNT
|
||||
};
|
||||
|
||||
|
|
@ -84,27 +82,6 @@ enum wdrm_plane_rotation {
|
|||
WDRM_PLANE_ROTATION__COUNT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Possible values for the WDRM_PLANE_COLOR_ENCODING property.
|
||||
*/
|
||||
enum wdrm_plane_color_encoding {
|
||||
WDRM_PLANE_COLOR_ENCODING_BT601 = 0,
|
||||
WDRM_PLANE_COLOR_ENCODING_BT709,
|
||||
WDRM_PLANE_COLOR_ENCODING_BT2020,
|
||||
WDRM_PLANE_COLOR_ENCODING__COUNT
|
||||
};
|
||||
#define WDRM_PLANE_COLOR_ENCODING_DEFAULT WDRM_PLANE_COLOR_ENCODING_BT709
|
||||
|
||||
/**
|
||||
* Possible values for the WDRM_PLANE_COLOR_RANGE property.
|
||||
*/
|
||||
enum wdrm_plane_color_range {
|
||||
WDRM_PLANE_COLOR_RANGE_LIMITED = 0,
|
||||
WDRM_PLANE_COLOR_RANGE_FULL,
|
||||
WDRM_PLANE_COLOR_RANGE__COUNT
|
||||
};
|
||||
#define WDRM_PLANE_COLOR_RANGE_DEFAULT WDRM_PLANE_COLOR_RANGE_LIMITED
|
||||
|
||||
/**
|
||||
* List of properties attached to a DRM connector
|
||||
*/
|
||||
|
|
@ -123,7 +100,6 @@ enum wdrm_connector_property {
|
|||
WDRM_CONNECTOR_MAX_BPC,
|
||||
WDRM_CONNECTOR_CONTENT_TYPE,
|
||||
WDRM_CONNECTOR_COLORSPACE,
|
||||
WDRM_CONNECTOR_VRR_CAPABLE,
|
||||
WDRM_CONNECTOR__COUNT
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include "drm-internal.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "shared/weston-assert.h"
|
||||
|
||||
#define POISON_PTR ((void *)8)
|
||||
|
||||
|
|
@ -206,7 +205,6 @@ static int
|
|||
drm_virtual_output_repaint(struct weston_output *output_base)
|
||||
{
|
||||
struct drm_output_state *state = NULL;
|
||||
struct weston_compositor *compositor = output_base->compositor;
|
||||
struct drm_output *output = to_drm_output(output_base);
|
||||
struct drm_plane *scanout_plane = output->scanout_plane;
|
||||
struct drm_plane_state *scanout_state;
|
||||
|
|
@ -229,10 +227,14 @@ drm_virtual_output_repaint(struct weston_output *output_base)
|
|||
|
||||
assert(!output->state_last);
|
||||
|
||||
/* assign_planes() is always called before a repaint, so we must have a
|
||||
* valid output state here. */
|
||||
/* If planes have been disabled in the core, we might not have
|
||||
* hit assign_planes at all, so might not have valid output state
|
||||
* here. */
|
||||
state = drm_pending_state_get_output(pending_state, output);
|
||||
weston_assert_ptr_not_null(compositor, state);
|
||||
if (!state)
|
||||
state = drm_output_state_duplicate(output->state_cur,
|
||||
pending_state,
|
||||
DRM_OUTPUT_STATE_CLEAR_PLANES);
|
||||
|
||||
drm_output_render(state);
|
||||
scanout_state = drm_output_state_get_plane(state, scanout_plane);
|
||||
|
|
@ -316,6 +318,8 @@ drm_virtual_output_enable(struct weston_output *output_base)
|
|||
output->base.assign_planes = drm_assign_planes;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = NULL;
|
||||
output->base.gamma_size = 0;
|
||||
output->base.set_gamma = NULL;
|
||||
|
||||
weston_compositor_stack_plane(b->compositor,
|
||||
&output->scanout_plane->base,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -114,21 +114,13 @@ static void gem_handle_put(struct drm_device *device, int handle)
|
|||
static int
|
||||
drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
||||
{
|
||||
int bo_fd = -1;
|
||||
int bo_fd;
|
||||
uint32_t handle;
|
||||
int ret;
|
||||
|
||||
/* neither a BO nor a direct-display means we shouldn't be calling this */
|
||||
assert(!!fb->bo ^ fb->direct_display);
|
||||
|
||||
if (fb->bo) {
|
||||
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
|
||||
if (bo_fd < 0)
|
||||
return bo_fd;
|
||||
}
|
||||
|
||||
if (fb->direct_display)
|
||||
bo_fd = fb->fds[plane];
|
||||
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
|
||||
if (bo_fd < 0)
|
||||
return bo_fd;
|
||||
|
||||
/*
|
||||
* drmPrimeFDToHandle is dangerous, because the GEM handles are
|
||||
|
|
@ -155,10 +147,7 @@ drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
|||
fb->handles[plane] = gem_handle_get(device, handle);
|
||||
|
||||
out:
|
||||
/* on the direct-display path the dup'ed fds will be closed by
|
||||
* drm_fb_destroy_dmabuf */
|
||||
if (fb->bo)
|
||||
close(bo_fd);
|
||||
close(bo_fd);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -182,32 +171,23 @@ drm_fb_maybe_import(struct drm_device *device, struct drm_fb *fb)
|
|||
struct gbm_device *gbm_device;
|
||||
int ret = 0;
|
||||
int plane;
|
||||
int num_planes;
|
||||
|
||||
/* No import possible, if there is no gbm bo or fb is not using
|
||||
* direct-display */
|
||||
if (!fb->bo && !fb->direct_display)
|
||||
/* No import possible, if there is no gbm bo */
|
||||
if (!fb->bo)
|
||||
return 0;
|
||||
|
||||
if (fb->bo) {
|
||||
/* No import necessary, if the gbm bo and the fb use the same device */
|
||||
gbm_device = gbm_bo_get_device(fb->bo);
|
||||
if (gbm_device_get_fd(gbm_device) == fb->fd)
|
||||
return 0;
|
||||
/* No import necessary, if the gbm bo and the fb use the same device */
|
||||
gbm_device = gbm_bo_get_device(fb->bo);
|
||||
if (gbm_device_get_fd(gbm_device) == fb->fd)
|
||||
return 0;
|
||||
|
||||
if (fb->fd != device->drm.fd) {
|
||||
weston_log("fb was not allocated for scanout device %s\n",
|
||||
device->drm.filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_planes = gbm_bo_get_plane_count(fb->bo);
|
||||
if (fb->fd != device->drm.fd) {
|
||||
weston_log("fb was not allocated for scanout device %s\n",
|
||||
device->drm.filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fb->direct_display)
|
||||
num_planes = fb->num_planes;
|
||||
|
||||
for (plane = 0; plane < num_planes; plane++) {
|
||||
for (plane = 0; plane < gbm_bo_get_plane_count(fb->bo); plane++) {
|
||||
ret = drm_fb_import_plane(device, fb, plane);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
|
@ -384,35 +364,27 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb)
|
|||
* If we imported the dmabuf into a scanout device, we are responsible
|
||||
* for closing the GEM handle.
|
||||
*/
|
||||
for (i = 0; i < MAX_DMABUF_PLANES; i++) {
|
||||
if (fb->scanout_device && fb->handles[i] != 0) {
|
||||
for (i = 0; i < 4; i++)
|
||||
if (fb->scanout_device && fb->handles[i] != 0)
|
||||
gem_handle_put(fb->scanout_device, fb->handles[i]);
|
||||
fb->handles[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < fb->num_duped_fds; i++)
|
||||
close(fb->fds[i]);
|
||||
|
||||
drm_fb_destroy(fb);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
bool direct_display, bool is_internal,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
static struct drm_fb *
|
||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
{
|
||||
struct drm_backend *backend = device->backend;
|
||||
struct drm_fb *fb;
|
||||
int i;
|
||||
struct gbm_import_fd_modifier_data import_mod = {
|
||||
.width = attributes->width,
|
||||
.height = attributes->height,
|
||||
.format = attributes->format,
|
||||
.num_fds = attributes->n_planes,
|
||||
.modifier = attributes->modifier,
|
||||
.width = dmabuf->attributes.width,
|
||||
.height = dmabuf->attributes.height,
|
||||
.format = dmabuf->attributes.format,
|
||||
.num_fds = dmabuf->attributes.n_planes,
|
||||
.modifier = dmabuf->attributes.modifier,
|
||||
};
|
||||
|
||||
/* We should not import to KMS a buffer that has been allocated using no
|
||||
|
|
@ -422,7 +394,7 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
* KMS driver can't know. So giving the buffer to KMS is not safe, as
|
||||
* not knowing its layout can result in garbage being displayed. In
|
||||
* short, importing a buffer to KMS requires explicit modifiers. */
|
||||
if (attributes->modifier == DRM_FORMAT_MOD_INVALID) {
|
||||
if (dmabuf->attributes.modifier == DRM_FORMAT_MOD_INVALID) {
|
||||
if (try_view_on_plane_failure_reasons)
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
|
||||
|
|
@ -438,7 +410,7 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
* these types of buffers should be handled through buffer
|
||||
* transforms and not as spot-checks requiring specific
|
||||
* knowledge. */
|
||||
if (attributes->flags)
|
||||
if (dmabuf->attributes.flags)
|
||||
return NULL;
|
||||
|
||||
fb = zalloc(sizeof *fb);
|
||||
|
|
@ -446,30 +418,12 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
return NULL;
|
||||
|
||||
fb->refcnt = 1;
|
||||
fb->type = is_internal ? BUFFER_DMABUF_BACKEND : BUFFER_DMABUF;
|
||||
fb->type = BUFFER_DMABUF;
|
||||
fb->backend = device->backend;
|
||||
|
||||
ARRAY_COPY(import_mod.fds, attributes->fd);
|
||||
ARRAY_COPY(import_mod.strides, attributes->stride);
|
||||
ARRAY_COPY(import_mod.offsets, attributes->offset);
|
||||
|
||||
/* skip bo import if dmabuf is using direct-display extension */
|
||||
if (direct_display) {
|
||||
fb->direct_display = true;
|
||||
/* we're making a dup of the fds from attributes->fd as
|
||||
* opposed to just copying the fds with ARRAY_COPY() */
|
||||
for (i = 0; i < attributes->n_planes; i++) {
|
||||
fb->fds[i] = dup(attributes->fd[i]);
|
||||
if (fb->fds[i] == -1) {
|
||||
weston_log("failed to dup dmabuf attribute fd: %s\n",
|
||||
strerror(errno));
|
||||
goto err_free;
|
||||
}
|
||||
fb->num_duped_fds++;
|
||||
}
|
||||
|
||||
goto bo_import_skip;
|
||||
}
|
||||
ARRAY_COPY(import_mod.fds, dmabuf->attributes.fd);
|
||||
ARRAY_COPY(import_mod.strides, dmabuf->attributes.stride);
|
||||
ARRAY_COPY(import_mod.offsets, dmabuf->attributes.offset);
|
||||
|
||||
fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
|
||||
&import_mod, GBM_BO_USE_SCANOUT);
|
||||
|
|
@ -480,20 +434,19 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
bo_import_skip:
|
||||
fb->width = attributes->width;
|
||||
fb->height = attributes->height;
|
||||
fb->modifier = attributes->modifier;
|
||||
fb->width = dmabuf->attributes.width;
|
||||
fb->height = dmabuf->attributes.height;
|
||||
fb->modifier = dmabuf->attributes.modifier;
|
||||
fb->size = 0;
|
||||
fb->fd = device->drm.fd;
|
||||
|
||||
ARRAY_COPY(fb->strides, attributes->stride);
|
||||
ARRAY_COPY(fb->offsets, attributes->offset);
|
||||
ARRAY_COPY(fb->strides, dmabuf->attributes.stride);
|
||||
ARRAY_COPY(fb->offsets, dmabuf->attributes.offset);
|
||||
|
||||
fb->format = pixel_format_get_info(attributes->format);
|
||||
fb->format = pixel_format_get_info(dmabuf->attributes.format);
|
||||
if (!fb->format) {
|
||||
weston_log("couldn't look up format info for 0x%lx\n",
|
||||
(unsigned long) attributes->format);
|
||||
(unsigned long) dmabuf->attributes.format);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
@ -508,8 +461,8 @@ bo_import_skip:
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
fb->num_planes = attributes->n_planes;
|
||||
for (i = 0; fb->bo && i < attributes->n_planes; i++) {
|
||||
fb->num_planes = dmabuf->attributes.n_planes;
|
||||
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
|
||||
union gbm_bo_handle handle;
|
||||
|
||||
handle = gbm_bo_get_handle_for_plane(fb->bo, i);
|
||||
|
|
@ -535,18 +488,6 @@ err_free:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
{
|
||||
return drm_fb_get_from_dmabuf_attributes(&dmabuf->attributes,
|
||||
device, is_opaque,
|
||||
dmabuf->direct_display,
|
||||
false,
|
||||
try_view_on_plane_failure_reasons);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
||||
bool is_opaque, enum drm_fb_type type)
|
||||
|
|
@ -641,7 +582,6 @@ drm_fb_unref(struct drm_fb *fb)
|
|||
gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
|
||||
break;
|
||||
case BUFFER_DMABUF:
|
||||
case BUFFER_DMABUF_BACKEND:
|
||||
drm_fb_destroy_dmabuf(fb);
|
||||
break;
|
||||
#endif
|
||||
|
|
@ -734,8 +674,7 @@ drm_fb_handle_buffer_destroy(struct wl_listener *listener, void *data)
|
|||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
struct weston_paint_node *pnode)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct drm_backend *b = output->backend;
|
||||
|
|
@ -750,13 +689,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
||||
ev->surface->desired_protection > output->base.current_protection) {
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
pnode->try_view_on_plane_failure_reasons |=
|
||||
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
|
||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +711,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
wl_list_for_each(buf_fb, &private->buffer_fb_list, link) {
|
||||
if (buf_fb->device == device) {
|
||||
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
return buf_fb->fb ? drm_fb_ref(buf_fb->fb) : NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -783,7 +722,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
/* GBM is used for dmabuf import as well as from client wl_buffer. */
|
||||
if (!b->gbm) {
|
||||
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
|
||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
|
||||
goto unsuitable;
|
||||
}
|
||||
|
||||
|
|
@ -802,13 +741,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
|
||||
if (!fb) {
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
FAILURE_REASONS_ADD_FB_FAILED;
|
||||
pnode->try_view_on_plane_failure_reasons |=
|
||||
(1 << FAILURE_REASONS_ADD_FB_FAILED);
|
||||
gbm_bo_destroy(bo);
|
||||
goto unsuitable;
|
||||
}
|
||||
} else {
|
||||
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
|
||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
|
||||
goto unsuitable;
|
||||
}
|
||||
|
||||
|
|
@ -837,7 +776,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
return fb;
|
||||
|
||||
unsuitable:
|
||||
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -79,27 +79,6 @@ struct drm_property_enum_info plane_rotation_enums[] = {
|
|||
},
|
||||
};
|
||||
|
||||
struct drm_property_enum_info plane_color_encoding_enums[] = {
|
||||
[WDRM_PLANE_COLOR_ENCODING_BT601] = {
|
||||
.name = "ITU-R BT.601 YCbCr",
|
||||
},
|
||||
[WDRM_PLANE_COLOR_ENCODING_BT709] = {
|
||||
.name = "ITU-R BT.709 YCbCr",
|
||||
},
|
||||
[WDRM_PLANE_COLOR_ENCODING_BT2020] = {
|
||||
.name = "ITU-R BT.2020 YCbCr",
|
||||
},
|
||||
};
|
||||
|
||||
struct drm_property_enum_info plane_color_range_enums[] = {
|
||||
[WDRM_PLANE_COLOR_RANGE_LIMITED] = {
|
||||
.name = "YCbCr limited range",
|
||||
},
|
||||
[WDRM_PLANE_COLOR_RANGE_FULL] = {
|
||||
.name = "YCbCr full range",
|
||||
},
|
||||
};
|
||||
|
||||
const struct drm_property_info plane_props[] = {
|
||||
[WDRM_PLANE_TYPE] = {
|
||||
.name = "type",
|
||||
|
|
@ -124,18 +103,8 @@ const struct drm_property_info plane_props[] = {
|
|||
.name = "rotation",
|
||||
.enum_values = plane_rotation_enums,
|
||||
.num_enum_values = WDRM_PLANE_ROTATION__COUNT,
|
||||
},
|
||||
},
|
||||
[WDRM_PLANE_ALPHA] = { .name = "alpha" },
|
||||
[WDRM_PLANE_COLOR_ENCODING] = {
|
||||
.name = "COLOR_ENCODING",
|
||||
.enum_values = plane_color_encoding_enums,
|
||||
.num_enum_values = WDRM_PLANE_COLOR_ENCODING__COUNT,
|
||||
},
|
||||
[WDRM_PLANE_COLOR_RANGE] = {
|
||||
.name = "COLOR_RANGE",
|
||||
.enum_values = plane_color_range_enums,
|
||||
.num_enum_values = WDRM_PLANE_COLOR_RANGE__COUNT,
|
||||
},
|
||||
};
|
||||
|
||||
struct drm_property_enum_info dpms_state_enums[] = {
|
||||
|
|
@ -249,9 +218,6 @@ const struct drm_property_info connector_props[] = {
|
|||
.enum_values = colorspace_enums,
|
||||
.num_enum_values = WDRM_COLORSPACE__COUNT,
|
||||
},
|
||||
[WDRM_CONNECTOR_VRR_CAPABLE] = {
|
||||
.name = "vrr_capable",
|
||||
},
|
||||
};
|
||||
|
||||
const struct drm_property_info crtc_props[] = {
|
||||
|
|
@ -429,17 +395,6 @@ drm_rotation_from_output_transform(struct drm_plane *plane,
|
|||
return out;
|
||||
}
|
||||
|
||||
static int
|
||||
wdrm_vrr_enabled_from_output(struct drm_output *drm_output)
|
||||
{
|
||||
struct weston_output *output = &drm_output->base;
|
||||
|
||||
if (output->vrr_mode == WESTON_VRR_MODE_GAME)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache DRM property values
|
||||
*
|
||||
|
|
@ -671,36 +626,26 @@ fallback:
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
drm_plane_supports_color_encoding(struct drm_plane *plane,
|
||||
enum wdrm_plane_color_encoding encoding)
|
||||
void
|
||||
drm_output_set_gamma(struct weston_output *output_base,
|
||||
uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
|
||||
{
|
||||
const struct drm_property_info *info;
|
||||
const struct drm_property_enum_info *enum_info;
|
||||
int rc;
|
||||
struct drm_output *output = to_drm_output(output_base);
|
||||
struct drm_device *device = output->device;
|
||||
|
||||
assert(encoding >= 0);
|
||||
assert(encoding < WDRM_PLANE_COLOR_ENCODING__COUNT);
|
||||
assert(output);
|
||||
|
||||
info = &plane->props[WDRM_PLANE_COLOR_ENCODING];
|
||||
enum_info = &info->enum_values[encoding];
|
||||
/* check */
|
||||
if (output_base->gamma_size != size)
|
||||
return;
|
||||
|
||||
return enum_info->valid;
|
||||
}
|
||||
|
||||
bool
|
||||
drm_plane_supports_color_range(struct drm_plane *plane,
|
||||
enum wdrm_plane_color_range range)
|
||||
{
|
||||
const struct drm_property_info *info;
|
||||
const struct drm_property_enum_info *enum_info;
|
||||
|
||||
assert(range >= 0);
|
||||
assert(range < WDRM_PLANE_COLOR_RANGE__COUNT);
|
||||
|
||||
info = &plane->props[WDRM_PLANE_COLOR_RANGE];
|
||||
enum_info = &info->enum_values[range];
|
||||
|
||||
return enum_info->valid;
|
||||
output->deprecated_gamma_is_set = true;
|
||||
rc = drmModeCrtcSetGamma(device->drm.fd,
|
||||
output->crtc->crtc_id,
|
||||
size, r, g, b);
|
||||
if (rc)
|
||||
weston_log("set gamma failed: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -820,7 +765,7 @@ err:
|
|||
static void
|
||||
drm_output_reset_legacy_gamma(struct drm_output *output)
|
||||
{
|
||||
uint32_t len = output->legacy_gamma_size;
|
||||
uint32_t len = output->base.gamma_size;
|
||||
uint16_t *lut;
|
||||
uint32_t i;
|
||||
int ret;
|
||||
|
|
@ -875,6 +820,18 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
connectors[n_conn++] = head->connector.connector_id;
|
||||
}
|
||||
|
||||
/* If disable_planes is set then assign_planes() wasn't
|
||||
* called for this render, so we could still have a stale
|
||||
* cursor plane set up.
|
||||
*/
|
||||
if (output->base.disable_planes) {
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
if (output->cursor_plane) {
|
||||
output->cursor_plane->base.x = INT32_MIN;
|
||||
output->cursor_plane->base.y = INT32_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->dpms != WESTON_DPMS_ON) {
|
||||
if (output->cursor_plane) {
|
||||
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,
|
||||
|
|
@ -933,7 +890,8 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
goto err;
|
||||
}
|
||||
|
||||
drm_output_reset_legacy_gamma(output);
|
||||
if (!output->deprecated_gamma_is_set)
|
||||
drm_output_reset_legacy_gamma(output);
|
||||
}
|
||||
|
||||
pinfo = scanout_state->fb->format;
|
||||
|
|
@ -1239,47 +1197,6 @@ drm_connector_set_colorspace(struct drm_connector *connector,
|
|||
WDRM_CONNECTOR_COLORSPACE, enum_info->value);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_plane_set_color_encoding(struct drm_plane *plane,
|
||||
enum wdrm_plane_color_encoding color_encoding,
|
||||
drmModeAtomicReq *req)
|
||||
{
|
||||
if (color_encoding == WDRM_PLANE_COLOR_ENCODING__COUNT)
|
||||
return 0;
|
||||
|
||||
if (plane->props[WDRM_PLANE_COLOR_ENCODING].prop_id == 0) {
|
||||
if (color_encoding == WDRM_PLANE_COLOR_ENCODING_DEFAULT)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(drm_plane_supports_color_encoding(plane, color_encoding));
|
||||
|
||||
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_ENCODING,
|
||||
color_encoding);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_plane_set_color_range(struct drm_plane *plane,
|
||||
enum wdrm_plane_color_range color_range,
|
||||
drmModeAtomicReq *req)
|
||||
{
|
||||
if (color_range == WDRM_PLANE_COLOR_RANGE__COUNT)
|
||||
return 0;
|
||||
|
||||
if (plane->props[WDRM_PLANE_COLOR_RANGE].prop_id == 0) {
|
||||
if (color_range == WDRM_PLANE_COLOR_RANGE_DEFAULT)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(drm_plane_supports_color_range(plane, color_range));
|
||||
|
||||
return plane_add_prop(req, plane, WDRM_PLANE_COLOR_RANGE, color_range);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_apply_state_atomic(struct drm_output_state *state,
|
||||
drmModeAtomicReq *req,
|
||||
|
|
@ -1321,18 +1238,14 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
|||
current_mode->blob_id);
|
||||
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_ACTIVE, 1);
|
||||
|
||||
if (output->base.from_blend_to_output_by_backend &&
|
||||
output->blend_to_output_xform)
|
||||
ret |= crtc_add_prop(req, crtc, WDRM_CRTC_GAMMA_LUT,
|
||||
output->blend_to_output_xform->blob_id);
|
||||
else
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_GAMMA_LUT, 0);
|
||||
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_DEGAMMA_LUT, 0);
|
||||
|
||||
if (!output->deprecated_gamma_is_set) {
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc,
|
||||
WDRM_CRTC_GAMMA_LUT, 0);
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc,
|
||||
WDRM_CRTC_DEGAMMA_LUT, 0);
|
||||
}
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_CTM, 0);
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED,
|
||||
wdrm_vrr_enabled_from_output(output));
|
||||
ret |= crtc_add_prop_zero_ok(req, crtc, WDRM_CRTC_VRR_ENABLED, 0);
|
||||
|
||||
/* No need for the DPMS property, since it is implicit in
|
||||
* routing and CRTC activity. */
|
||||
|
|
@ -1352,11 +1265,6 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
|||
ret |= connector_add_prop(req, &wb_state->wb->connector,
|
||||
WDRM_CONNECTOR_WRITEBACK_OUT_FENCE_PTR,
|
||||
(uintptr_t)&wb_state->out_fence_fd);
|
||||
|
||||
drm_debug(b, "\t\t\t[CONN:%lu] FORMAT: %s\n",
|
||||
(unsigned long) wb_state->wb->connector.connector_id,
|
||||
wb_state->fb->format->drm_format_name);
|
||||
|
||||
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY))
|
||||
wb_state->state = DRM_OUTPUT_WB_SCREENSHOT_CHECK_FENCE;
|
||||
}
|
||||
|
|
@ -1374,13 +1282,11 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
|||
wl_list_for_each(head, &output->base.head_list, base.output_link)
|
||||
ret |= connector_add_prop(req, &head->connector,
|
||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||
}
|
||||
|
||||
wl_list_for_each_safe(head, tmp, &output->disable_head, disable_head_link) {
|
||||
ret |= connector_add_prop(req, &head->connector,
|
||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||
*flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
if (!(*flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
|
||||
wl_list_for_each_safe(head, tmp, &output->disable_head,
|
||||
disable_head_link) {
|
||||
ret |= connector_add_prop(req, &head->connector,
|
||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||
wl_list_remove(&head->disable_head_link);
|
||||
wl_list_init(&head->disable_head_link);
|
||||
}
|
||||
|
|
@ -1467,13 +1373,6 @@ drm_output_apply_state_atomic(struct drm_output_state *state,
|
|||
WDRM_PLANE_ALPHA,
|
||||
plane_state->alpha);
|
||||
|
||||
ret |= drm_plane_set_color_encoding(plane,
|
||||
plane_state->color_encoding,
|
||||
req);
|
||||
|
||||
ret |= drm_plane_set_color_range(plane,
|
||||
plane_state->color_range, req);
|
||||
|
||||
if (ret != 0) {
|
||||
weston_log("couldn't set plane state\n");
|
||||
return ret;
|
||||
|
|
@ -1625,10 +1524,7 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
|
||||
if (ret != 0) {
|
||||
weston_log("atomic: couldn't compile atomic state\n");
|
||||
if (mode == DRM_STATE_TEST_ONLY)
|
||||
goto out_test_only;
|
||||
else
|
||||
goto out;
|
||||
goto out;
|
||||
}
|
||||
if (may_tear)
|
||||
tear_flag = DRM_MODE_PAGE_FLIP_ASYNC;
|
||||
|
|
@ -1646,8 +1542,12 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
if (ret == 0)
|
||||
drm_pending_state_clear_tearing(pending_state);
|
||||
}
|
||||
if (mode == DRM_STATE_TEST_ONLY)
|
||||
goto out_test_only;
|
||||
/* Test commits do not take ownership of the state; return
|
||||
* without freeing here. */
|
||||
if (mode == DRM_STATE_TEST_ONLY) {
|
||||
drmModeAtomicFree(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
wl_list_for_each(output_state, &pending_state->output_list, link)
|
||||
|
|
@ -1668,11 +1568,8 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
assert(wl_list_empty(&pending_state->output_list));
|
||||
|
||||
out:
|
||||
drm_pending_state_free(pending_state);
|
||||
/* Test commits do not take ownership of the state; return
|
||||
* without freeing here. */
|
||||
out_test_only:
|
||||
drmModeAtomicFree(req);
|
||||
drm_pending_state_free(pending_state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1768,9 +1665,6 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
|||
if (b->compositor->renderer->type == WESTON_RENDERER_GL) {
|
||||
drm_output_fini_egl(output);
|
||||
drm_output_init_egl(output, b);
|
||||
} else if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
|
||||
drm_output_fini_vulkan(output);
|
||||
drm_output_init_vulkan(output, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1864,7 +1758,6 @@ page_flip_handler(int fd, unsigned int frame,
|
|||
assert(output->page_flip_pending);
|
||||
output->page_flip_pending = false;
|
||||
|
||||
output->page_flips_counted++;
|
||||
drm_output_update_complete(output, flags, sec, usec);
|
||||
}
|
||||
|
||||
|
|
@ -1878,8 +1771,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
|||
struct drm_crtc *crtc;
|
||||
struct drm_output *output;
|
||||
struct timespec now;
|
||||
float page_flips_per_timer_interval;
|
||||
uint32_t frame_counter_interval;
|
||||
uint32_t flags = WP_PRESENTATION_FEEDBACK_KIND_VSYNC |
|
||||
WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION |
|
||||
WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
|
||||
|
|
@ -1895,14 +1786,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
|||
if (!output || !output->base.enabled)
|
||||
return;
|
||||
|
||||
output->page_flips_counted++;
|
||||
/* store them temporarily as drm_output_update_complete might destroy
|
||||
* the output */
|
||||
page_flips_per_timer_interval = output->page_flips_per_timer_interval;
|
||||
frame_counter_interval =
|
||||
output->backend->perf_page_flips_stats.frame_counter_interval;
|
||||
|
||||
|
||||
drm_output_update_msc(output, frame);
|
||||
|
||||
if (output->state_cur->tear) {
|
||||
|
|
@ -1923,8 +1806,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
|||
|
||||
drm_output_update_complete(output, flags, sec, usec);
|
||||
drm_debug(b, "[atomic][CRTC:%u] flip processing completed\n", crtc_id);
|
||||
drm_debug(b, "[atomic][CRTC:%u] %.2f page flips computed in %d seconds\n",
|
||||
crtc_id, page_flips_per_timer_interval, frame_counter_interval);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1994,29 +1875,10 @@ init_kms_caps(struct drm_device *device)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
|
||||
if (ret != 0)
|
||||
cap = 0;
|
||||
|
||||
/* Between Linux 3.16 and Linux 4.1 there was a bug that
|
||||
* could result in a stale timestamp being returned.
|
||||
*
|
||||
* The workaround for this has can make it impossible
|
||||
* to display images with precise timing.
|
||||
*
|
||||
* It's somewhat difficult to determine whether we need
|
||||
* that workaround or not, but we know that the
|
||||
* DRM_CAP_CRTC_IN_VBLANK_EVENT drm cap exists in 4.12
|
||||
* and on. We'll use its presence to gate the workaround.
|
||||
*/
|
||||
if (!cap) {
|
||||
weston_log("DRM Warning: stale timestamp workaround for Kernel older than 4.12\n");
|
||||
device->backend->stale_timestamp_workaround = true;
|
||||
} else {
|
||||
device->backend->stale_timestamp_workaround = false;
|
||||
}
|
||||
|
||||
if (!getenv("WESTON_DISABLE_ATOMIC")) {
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_CRTC_IN_VBLANK_EVENT, &cap);
|
||||
if (ret != 0)
|
||||
cap = 0;
|
||||
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
||||
device->atomic_modeset = ((ret == 0) && (cap == 1));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,20 @@ if not get_option('backend-drm')
|
|||
subdir_done()
|
||||
endif
|
||||
|
||||
dep_libdisplay_info = dependency(
|
||||
'libdisplay-info',
|
||||
version: ['>= 0.1.1', '< 0.3.0'],
|
||||
fallback: ['display-info', 'di_dep'],
|
||||
default_options: [
|
||||
'werror=false',
|
||||
],
|
||||
required: true,
|
||||
not_found_message: 'Required by DRM-backend.',
|
||||
)
|
||||
if dep_libdisplay_info.version().version_compare('>= 0.2.0')
|
||||
config_h.set('HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY', '1')
|
||||
endif
|
||||
|
||||
lib_backlight = static_library(
|
||||
'backlight',
|
||||
'libbacklight.c',
|
||||
|
|
@ -34,7 +48,6 @@ srcs_drm = [
|
|||
|
||||
deps_drm = [
|
||||
dep_egl, # optional
|
||||
dep_vulkan, # optional
|
||||
dep_libm,
|
||||
dep_libdl,
|
||||
dep_libshared,
|
||||
|
|
@ -56,17 +69,7 @@ if get_option('renderer-gl')
|
|||
config_h.set('BUILD_DRM_GBM', '1')
|
||||
endif
|
||||
|
||||
if get_option('renderer-vulkan')
|
||||
if not dep_gbm.found()
|
||||
error('drm-backend with Vulkan renderer requires gbm which was not found. Or, you can use \'-Drenderer-vulkan=false\'.')
|
||||
endif
|
||||
deps_drm += dep_gbm
|
||||
srcs_drm += 'drm-gbm.c'
|
||||
config_h.set('BUILD_DRM_GBM', '1')
|
||||
endif
|
||||
|
||||
if get_option('deprecated-backend-drm-screencast-vaapi')
|
||||
warning('deprecated-backend-drm-screencast-vaapi enabled. This option will be removed in future versions.')
|
||||
if get_option('backend-drm-screencast-vaapi')
|
||||
foreach name : [ 'libva', 'libva-drm' ]
|
||||
d = dependency(name, version: '>= 0.34.0', required: false)
|
||||
if not d.found()
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <libdisplay-info/cta.h>
|
||||
#include <libdisplay-info/edid.h>
|
||||
#include <libdisplay-info/info.h>
|
||||
|
||||
#include "drm-internal.h"
|
||||
|
|
@ -53,10 +51,6 @@ struct drm_head_info {
|
|||
* enum weston_colorimetry_mode bits.
|
||||
*/
|
||||
uint32_t colorimetry_mask;
|
||||
|
||||
/* The monitor supported color foramts, combination of
|
||||
* enum_weston_color_format bits. */
|
||||
uint32_t color_format_mask;
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -233,6 +227,8 @@ parse_modeline(const char *s, drmModeModeInfo *mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY
|
||||
|
||||
static uint32_t
|
||||
get_eotf_mask(const struct di_info *info)
|
||||
{
|
||||
|
|
@ -288,76 +284,22 @@ get_colorimetry_mask(const struct di_info *info)
|
|||
return mask;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_yuv420_cap_map(const struct di_edid_cta *cta)
|
||||
#else /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
|
||||
|
||||
static uint32_t
|
||||
get_eotf_mask(const struct di_info *info)
|
||||
{
|
||||
const struct di_cta_data_block *const *data_blocks;
|
||||
enum di_cta_data_block_tag db_tag;
|
||||
int i;
|
||||
|
||||
data_blocks = di_edid_cta_get_data_blocks(cta);
|
||||
for (i = 0; data_blocks[i] != NULL; i++) {
|
||||
db_tag = di_cta_data_block_get_tag(data_blocks[i]);
|
||||
if (db_tag == DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return WESTON_EOTF_MODE_SDR;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_color_format_mask(const struct di_info *info)
|
||||
get_colorimetry_mask(const struct di_info *info)
|
||||
{
|
||||
const struct di_edid *edid = di_info_get_edid(info);
|
||||
const struct di_edid_color_encoding_formats *fmts =
|
||||
di_edid_get_color_encoding_formats(edid);
|
||||
const struct di_edid_ext *const *exts = di_edid_get_extensions(edid);
|
||||
uint32_t mask = WESTON_COLOR_FORMAT_AUTO;
|
||||
int i;
|
||||
|
||||
if (fmts) {
|
||||
if (fmts->rgb444)
|
||||
mask |= WESTON_COLOR_FORMAT_RGB;
|
||||
|
||||
if (fmts->ycrcb444)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV444;
|
||||
|
||||
if (fmts->ycrcb422)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||
}
|
||||
|
||||
for (i = 0; exts[i] ; i++) {
|
||||
const struct di_edid_cta *cta;
|
||||
const struct di_edid_cta_flags *cta_flags;
|
||||
|
||||
switch (di_edid_ext_get_tag(exts[i])) {
|
||||
case DI_EDID_EXT_CEA:
|
||||
cta = di_edid_ext_get_cta(exts[i]);
|
||||
cta_flags = di_edid_cta_get_flags(cta);
|
||||
|
||||
mask |= WESTON_COLOR_FORMAT_RGB;
|
||||
|
||||
if (cta_flags->ycc444)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV444;
|
||||
|
||||
if (cta_flags->ycc422)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||
|
||||
/* FIXME: YUV420 detection is really complicated,
|
||||
* do it properly at some point...
|
||||
*/
|
||||
if (has_yuv420_cap_map(cta))
|
||||
mask |= WESTON_COLOR_FORMAT_YUV420;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
return WESTON_COLORIMETRY_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
|
||||
|
||||
static struct di_info *
|
||||
drm_head_info_from_edid(struct drm_head_info *dhi,
|
||||
const uint8_t *data,
|
||||
|
|
@ -383,7 +325,6 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
|
|||
dhi->serial_number = di_info_get_serial(di_ctx);
|
||||
dhi->eotf_mask = get_eotf_mask(di_ctx);
|
||||
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
|
||||
dhi->color_format_mask = get_color_format_mask(di_ctx);
|
||||
|
||||
return di_ctx;
|
||||
}
|
||||
|
|
@ -656,46 +597,26 @@ void
|
|||
update_head_from_connector(struct drm_head *head)
|
||||
{
|
||||
struct drm_connector *connector = &head->connector;
|
||||
struct drm_backend *b = head->connector.device->backend;
|
||||
drmModeObjectProperties *props = connector->props_drm;
|
||||
drmModeConnector *conn = connector->conn;
|
||||
int vrr_capable;
|
||||
uint32_t vrr_mode_mask = 0;
|
||||
uint32_t conn_id = head->connector.connector_id;
|
||||
bool ret;
|
||||
|
||||
ret = weston_head_set_non_desktop(&head->base,
|
||||
weston_head_set_non_desktop(&head->base,
|
||||
check_non_desktop(connector, props));
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] non-desktop property changed\n", conn_id);
|
||||
|
||||
ret = weston_head_set_subpixel(&head->base,
|
||||
weston_head_set_subpixel(&head->base,
|
||||
drm_subpixel_to_wayland(conn->subpixel));
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] subpixel property changed\n", conn_id);
|
||||
|
||||
ret = weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] physical size changed\n", conn_id);
|
||||
weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
|
||||
|
||||
ret = weston_head_set_transform(&head->base,
|
||||
weston_head_set_transform(&head->base,
|
||||
get_panel_orientation(connector, props));
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] transform property changed\n", conn_id);
|
||||
|
||||
/* Unknown connection status is assumed disconnected. */
|
||||
ret = weston_head_set_connection_status(&head->base,
|
||||
weston_head_set_connection_status(&head->base,
|
||||
conn->connection == DRM_MODE_CONNECTED);
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] connection status changed\n", conn_id);
|
||||
|
||||
/* If EDID did not change, skip everything about it */
|
||||
if (!drm_head_maybe_update_display_data(head, props)) {
|
||||
if (!ret)
|
||||
drm_debug(b, "\t[CONN:%d] Hot-plug event received "
|
||||
"but no connector changes detected\n", conn_id);
|
||||
if (!drm_head_maybe_update_display_data(head, props))
|
||||
return;
|
||||
}
|
||||
|
||||
struct drm_head_info dhi;
|
||||
|
||||
|
|
@ -709,18 +630,11 @@ update_head_from_connector(struct drm_head *head)
|
|||
dhi.serial_number);
|
||||
|
||||
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
|
||||
|
||||
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
|
||||
|
||||
dhi.colorimetry_mask &= drm_head_get_kms_colorimetry_modes(head);
|
||||
weston_head_set_supported_colorimetry_mask(&head->base, dhi.colorimetry_mask);
|
||||
|
||||
vrr_capable = drm_property_get_value(&head->connector.props[WDRM_CONNECTOR_VRR_CAPABLE],
|
||||
head->connector.props_drm, 0);
|
||||
if (vrr_capable)
|
||||
vrr_mode_mask = WESTON_VRR_MODE_GAME;
|
||||
weston_head_set_supported_vrr_modes_mask(&head->base, vrr_mode_mask);
|
||||
|
||||
drm_head_info_fini(&dhi);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,9 +55,6 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
|
|||
state->alpha = (plane->alpha_max < DRM_PLANE_ALPHA_OPAQUE) ?
|
||||
plane->alpha_max : DRM_PLANE_ALPHA_OPAQUE;
|
||||
|
||||
state->color_encoding = WDRM_PLANE_COLOR_ENCODING__COUNT;
|
||||
state->color_range = WDRM_PLANE_COLOR_RANGE__COUNT;
|
||||
|
||||
/* Here we only add the plane state to the desired link, and not
|
||||
* set the member. Having an output pointer set means that the
|
||||
* plane will be displayed on the output; this won't be the case
|
||||
|
|
@ -216,7 +213,7 @@ drm_plane_state_put_back(struct drm_plane_state *state)
|
|||
* Given a weston_view, fill the drm_plane_state's co-ordinates to display on
|
||||
* a given plane.
|
||||
*/
|
||||
void
|
||||
bool
|
||||
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||
struct weston_paint_node *node,
|
||||
uint64_t zpos)
|
||||
|
|
@ -231,11 +228,8 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
|||
uint16_t min_alpha = state->plane->alpha_min;
|
||||
uint16_t max_alpha = state->plane->alpha_max;
|
||||
|
||||
/* The caller has already checked supported transforms when creating
|
||||
* a list of candidate planes, so we should only ever get here with
|
||||
* a supported transform.
|
||||
*/
|
||||
assert(drm_paint_node_transform_supported(node, state->plane));
|
||||
if (!drm_paint_node_transform_supported(node, state->plane))
|
||||
return false;
|
||||
|
||||
assert(node->valid_transform);
|
||||
state->rotation = drm_rotation_from_output_transform(state->plane, node->transform);
|
||||
|
|
@ -318,6 +312,8 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
|||
* never exceed max_alpha if ev->alpha <= 1.0.
|
||||
*/
|
||||
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -407,9 +403,6 @@ drm_output_state_duplicate(struct drm_output_state *src,
|
|||
|
||||
assert(dst);
|
||||
|
||||
/* The reuse bit isn't stored in the state */
|
||||
assert(!(src->mode & DRM_OUTPUT_PROPOSE_STATE_REUSE));
|
||||
|
||||
/* Copy the whole structure, then individually modify the
|
||||
* pending_state, as well as the list link into our pending
|
||||
* state. */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -42,8 +42,7 @@
|
|||
#include "pixel-formats.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "renderer-borders.h"
|
||||
#include "gl-borders.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "shared/cairo-util.h"
|
||||
|
|
@ -70,8 +69,6 @@ struct headless_backend {
|
|||
|
||||
int refresh;
|
||||
bool repaint_only_on_capture;
|
||||
|
||||
bool use_fake_seat;
|
||||
};
|
||||
|
||||
struct headless_head {
|
||||
|
|
@ -84,10 +81,12 @@ struct headless_output {
|
|||
|
||||
struct weston_mode mode;
|
||||
struct wl_event_source *finish_frame_timer;
|
||||
weston_renderbuffer_t renderbuffer;
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
|
||||
struct frame *frame;
|
||||
struct weston_renderer_borders borders;
|
||||
struct {
|
||||
struct weston_gl_borders borders;
|
||||
} gl;
|
||||
};
|
||||
|
||||
static const uint32_t headless_formats[] = {
|
||||
|
|
@ -145,15 +144,15 @@ finish_frame_handler(void *data)
|
|||
}
|
||||
|
||||
static void
|
||||
headless_output_update_renderer_border(struct headless_output *output)
|
||||
headless_output_update_gl_border(struct headless_output *output)
|
||||
{
|
||||
if (!output->frame)
|
||||
return;
|
||||
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
|
||||
return;
|
||||
|
||||
weston_renderer_borders_update(&output->borders, output->frame,
|
||||
&output->base);
|
||||
weston_gl_borders_update(&output->gl.borders, output->frame,
|
||||
&output->base);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -162,12 +161,13 @@ headless_output_repaint(struct weston_output *output_base)
|
|||
struct headless_output *output = to_headless_output(output_base);
|
||||
struct weston_compositor *ec;
|
||||
pixman_region32_t damage;
|
||||
int delay_msec;
|
||||
|
||||
assert(output);
|
||||
|
||||
ec = output->base.compositor;
|
||||
|
||||
headless_output_update_renderer_border(output);
|
||||
headless_output_update_gl_border(output);
|
||||
|
||||
pixman_region32_init(&damage);
|
||||
|
||||
|
|
@ -178,7 +178,8 @@ headless_output_repaint(struct weston_output *output_base)
|
|||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
|
||||
delay_msec = millihz_to_nsec(output->mode.refresh) / 1000000;
|
||||
wl_event_source_timer_update(output->finish_frame_timer, delay_msec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -189,9 +190,9 @@ headless_output_disable_gl(struct headless_output *output)
|
|||
struct weston_compositor *compositor = output->base.compositor;
|
||||
const struct weston_renderer *renderer = compositor->renderer;
|
||||
|
||||
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||
weston_gl_borders_fini(&output->gl.borders, &output->base);
|
||||
|
||||
renderer->destroy_renderbuffer(output->renderbuffer);
|
||||
weston_renderbuffer_unref(output->renderbuffer);
|
||||
output->renderbuffer = NULL;
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
|
||||
|
|
@ -201,30 +202,12 @@ headless_output_disable_gl(struct headless_output *output)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
headless_output_disable_vulkan(struct headless_output *output)
|
||||
{
|
||||
struct weston_compositor *compositor = output->base.compositor;
|
||||
const struct weston_renderer *renderer = compositor->renderer;
|
||||
|
||||
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||
|
||||
renderer->destroy_renderbuffer(output->renderbuffer);
|
||||
output->renderbuffer = NULL;
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
|
||||
if (output->frame) {
|
||||
frame_destroy(output->frame);
|
||||
output->frame = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
headless_output_disable_pixman(struct headless_output *output)
|
||||
{
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
|
||||
renderer->destroy_renderbuffer(output->renderbuffer);
|
||||
weston_renderbuffer_unref(output->renderbuffer);
|
||||
output->renderbuffer = NULL;
|
||||
renderer->pixman->output_destroy(&output->base);
|
||||
}
|
||||
|
|
@ -248,9 +231,6 @@ headless_output_disable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL:
|
||||
headless_output_disable_gl(output);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
headless_output_disable_vulkan(output);
|
||||
break;
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
headless_output_disable_pixman(output);
|
||||
break;
|
||||
|
|
@ -321,8 +301,9 @@ headless_output_enable_gl(struct headless_output *output)
|
|||
}
|
||||
|
||||
output->renderbuffer =
|
||||
renderer->create_renderbuffer(&output->base, b->formats[0],
|
||||
NULL, 0, NULL, NULL);
|
||||
renderer->gl->create_fbo(&output->base, b->formats[0],
|
||||
options.fb_size.width,
|
||||
options.fb_size.height, NULL);
|
||||
if (!output->renderbuffer)
|
||||
goto err_renderbuffer;
|
||||
|
||||
|
|
@ -334,67 +315,10 @@ err_renderbuffer:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
headless_output_enable_vulkan(struct headless_output *output)
|
||||
{
|
||||
struct headless_backend *b = output->backend;
|
||||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
const struct weston_mode *mode = output->base.current_mode;
|
||||
struct vulkan_renderer_surfaceless_options options = { 0 };
|
||||
|
||||
if (b->decorate) {
|
||||
/*
|
||||
* Start with a dummy exterior size and then resize, because
|
||||
* there is no frame_create() with interior size.
|
||||
*/
|
||||
output->frame = frame_create(b->theme, 100, 100,
|
||||
FRAME_BUTTON_CLOSE, NULL, NULL);
|
||||
if (!output->frame) {
|
||||
weston_log("failed to create frame for output\n");
|
||||
return -1;
|
||||
}
|
||||
frame_resize_inside(output->frame, mode->width, mode->height);
|
||||
|
||||
options.fb_size.width = frame_width(output->frame);
|
||||
options.fb_size.height = frame_height(output->frame);
|
||||
frame_interior(output->frame, &options.area.x, &options.area.y,
|
||||
&options.area.width, &options.area.height);
|
||||
} else {
|
||||
options.area.x = 0;
|
||||
options.area.y = 0;
|
||||
options.area.width = mode->width;
|
||||
options.area.height = mode->height;
|
||||
options.fb_size.width = mode->width;
|
||||
options.fb_size.height = mode->height;
|
||||
}
|
||||
|
||||
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||
weston_log("failed to create vulkan renderer output state\n");
|
||||
if (output->frame) {
|
||||
frame_destroy(output->frame);
|
||||
output->frame = NULL;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
output->renderbuffer =
|
||||
renderer->create_renderbuffer(&output->base, b->formats[0],
|
||||
NULL, 0, NULL, NULL);
|
||||
if (!output->renderbuffer)
|
||||
goto err_renderbuffer;
|
||||
|
||||
return 0;
|
||||
|
||||
err_renderbuffer:
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
headless_output_enable_pixman(struct headless_output *output)
|
||||
{
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
const struct pixman_renderer_interface *pixman;
|
||||
const struct pixman_renderer_output_options options = {
|
||||
.use_shadow = true,
|
||||
.fb_size = {
|
||||
|
|
@ -404,19 +328,22 @@ headless_output_enable_pixman(struct headless_output *output)
|
|||
.format = pixel_format_get_info(headless_formats[0])
|
||||
};
|
||||
|
||||
if (renderer->pixman->output_create(&output->base, &options) < 0)
|
||||
pixman = output->base.compositor->renderer->pixman;
|
||||
|
||||
if (pixman->output_create(&output->base, &options) < 0)
|
||||
return -1;
|
||||
|
||||
output->renderbuffer =
|
||||
renderer->create_renderbuffer(&output->base, options.format,
|
||||
NULL, 0, NULL, NULL);
|
||||
pixman->create_image(&output->base, options.format,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height);
|
||||
if (!output->renderbuffer)
|
||||
goto err_renderer;
|
||||
|
||||
return 0;
|
||||
|
||||
err_renderer:
|
||||
renderer->pixman->output_destroy(&output->base);
|
||||
pixman->output_destroy(&output->base);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -446,9 +373,6 @@ headless_output_enable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL:
|
||||
ret = headless_output_enable_gl(output);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
ret = headless_output_enable_vulkan(output);
|
||||
break;
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
ret = headless_output_enable_pixman(output);
|
||||
break;
|
||||
|
|
@ -466,19 +390,6 @@ headless_output_enable(struct weston_output *base)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
headless_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||
{
|
||||
struct headless_output *output = to_headless_output(base);
|
||||
|
||||
if (level == WESTON_DPMS_ON)
|
||||
weston_output_schedule_repaint(base);
|
||||
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||
weston_output_schedule_repaint_reset(base);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
headless_output_set_size(struct weston_output *base,
|
||||
int width, int height)
|
||||
|
|
@ -520,7 +431,7 @@ headless_output_set_size(struct weston_output *base,
|
|||
output->base.repaint = headless_output_repaint;
|
||||
output->base.assign_planes = NULL;
|
||||
output->base.set_backlight = NULL;
|
||||
output->base.set_dpms = headless_set_dpms;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = NULL;
|
||||
|
||||
return 0;
|
||||
|
|
@ -600,25 +511,6 @@ headless_head_destroy(struct weston_head *base)
|
|||
free(head);
|
||||
}
|
||||
|
||||
static bool
|
||||
headless_input_create(struct headless_backend *b)
|
||||
{
|
||||
weston_seat_init(&b->fake_seat, b->compositor, "default");
|
||||
|
||||
weston_seat_init_pointer(&b->fake_seat);
|
||||
|
||||
if (weston_seat_init_keyboard(&b->fake_seat, NULL) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
headless_input_destroy(struct headless_backend *b)
|
||||
{
|
||||
weston_seat_release(&b->fake_seat);
|
||||
}
|
||||
|
||||
static void
|
||||
headless_destroy(struct weston_backend *backend)
|
||||
{
|
||||
|
|
@ -636,9 +528,6 @@ headless_destroy(struct weston_backend *backend)
|
|||
if (b->theme)
|
||||
theme_destroy(b->theme);
|
||||
|
||||
if (b->use_fake_seat)
|
||||
headless_input_destroy(b);
|
||||
|
||||
free(b->formats);
|
||||
free(b);
|
||||
|
||||
|
|
@ -670,12 +559,6 @@ headless_backend_create(struct weston_compositor *compositor,
|
|||
b->base.supported_presentation_clocks =
|
||||
WESTON_PRESENTATION_CLOCKS_SOFTWARE;
|
||||
|
||||
if (config->fake_seat) {
|
||||
b->use_fake_seat = headless_input_create(b);
|
||||
if (!b->use_fake_seat)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
b->base.destroy = headless_destroy;
|
||||
b->base.create_output = headless_output_create;
|
||||
|
||||
|
|
@ -717,16 +600,6 @@ headless_backend_create(struct weston_compositor *compositor,
|
|||
&options.base);
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_display_options options = {
|
||||
.formats = b->formats,
|
||||
.formats_count = b->formats_count,
|
||||
};
|
||||
ret = weston_compositor_init_renderer(compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base);
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
if (config->decorate) {
|
||||
weston_log("Error: Pixman renderer does not support decorations.\n");
|
||||
|
|
@ -774,8 +647,6 @@ err_input:
|
|||
if (b->theme)
|
||||
theme_destroy(b->theme);
|
||||
err_free:
|
||||
if (b->use_fake_seat)
|
||||
headless_input_destroy(b);
|
||||
wl_list_remove(&b->base.link);
|
||||
free(b);
|
||||
return NULL;
|
||||
|
|
@ -785,7 +656,6 @@ static void
|
|||
config_init_to_defaults(struct weston_headless_backend_config *config)
|
||||
{
|
||||
config->refresh = DEFAULT_OUTPUT_REPAINT_REFRESH;
|
||||
config->fake_seat = false;
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ plugin_headless = shared_library(
|
|||
dep_libweston_private,
|
||||
dep_libdrm_headers,
|
||||
dep_lib_cairo_shared,
|
||||
dep_lib_renderer_borders,
|
||||
dep_lib_gl_borders,
|
||||
],
|
||||
name_prefix: '',
|
||||
install: true,
|
||||
|
|
|
|||
|
|
@ -56,11 +56,9 @@
|
|||
#include <libweston/backend-pipewire.h>
|
||||
#include <libweston/linux-dmabuf.h>
|
||||
#include <libweston/weston-log.h>
|
||||
#include "output-capture.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
|
||||
struct pipewire_backend {
|
||||
|
|
@ -103,7 +101,7 @@ struct pipewire_head {
|
|||
};
|
||||
|
||||
struct pipewire_frame_data {
|
||||
weston_renderbuffer_t renderbuffer;
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
struct pipewire_memfd *memfd;
|
||||
struct pipewire_dmabuf *dmabuf;
|
||||
};
|
||||
|
|
@ -268,16 +266,14 @@ pipewire_output_connect(struct pipewire_output *output)
|
|||
/* TODO: Add support for modifier discovery and negotiation. */
|
||||
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
||||
params[i++] = spa_pod_build_format(&builder,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
output->base.width, output->base.height,
|
||||
output->base.current_mode->refresh / 1000,
|
||||
output->pixel_format->format,
|
||||
modifier);
|
||||
}
|
||||
|
||||
params[i++] = spa_pod_build_format(&builder,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
output->base.width, output->base.height,
|
||||
output->base.current_mode->refresh / 1000,
|
||||
output->pixel_format->format, NULL);
|
||||
|
||||
|
|
@ -311,8 +307,8 @@ pipewire_output_enable_pixman(struct pipewire_output *output)
|
|||
const struct pixman_renderer_output_options options = {
|
||||
.use_shadow = true,
|
||||
.fb_size = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
.width = output->base.width,
|
||||
.height = output->base.height,
|
||||
},
|
||||
.format = output->pixel_format,
|
||||
};
|
||||
|
|
@ -351,29 +347,6 @@ pipewire_output_enable_gl(struct pipewire_output *output)
|
|||
return renderer->gl->output_fbo_create(&output->base, &options);
|
||||
}
|
||||
|
||||
static int
|
||||
pipewire_output_enable_vulkan(struct pipewire_output *output)
|
||||
{
|
||||
struct pipewire_backend *b = output->backend;
|
||||
struct weston_renderer *renderer = b->compositor->renderer;
|
||||
const struct weston_size fb_size = {
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height
|
||||
};
|
||||
const struct weston_geometry area = {
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
.width = fb_size.width,
|
||||
.height = fb_size.height
|
||||
};
|
||||
const struct vulkan_renderer_surfaceless_options options = {
|
||||
.fb_size = fb_size,
|
||||
.area = area,
|
||||
};
|
||||
|
||||
return renderer->vulkan->output_surfaceless_create(&output->base, &options);
|
||||
}
|
||||
|
||||
static void
|
||||
pipewire_output_disable_gl(struct pipewire_output *output)
|
||||
{
|
||||
|
|
@ -382,14 +355,6 @@ pipewire_output_disable_gl(struct pipewire_output *output)
|
|||
renderer->gl->output_destroy(&output->base);
|
||||
}
|
||||
|
||||
static void
|
||||
pipewire_output_disable_vulkan(struct pipewire_output *output)
|
||||
{
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
}
|
||||
|
||||
static int
|
||||
pipewire_output_enable(struct weston_output *base)
|
||||
{
|
||||
|
|
@ -408,9 +373,6 @@ pipewire_output_enable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL:
|
||||
ret = pipewire_output_enable_gl(output);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
ret = pipewire_output_enable_vulkan(output);
|
||||
break;
|
||||
default:
|
||||
unreachable("Valid renderer should have been selected");
|
||||
}
|
||||
|
|
@ -436,9 +398,6 @@ err:
|
|||
case WESTON_RENDERER_GL:
|
||||
pipewire_output_disable_gl(output);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
pipewire_output_disable_vulkan(output);
|
||||
break;
|
||||
default:
|
||||
unreachable("Valid renderer should have been selected");
|
||||
}
|
||||
|
|
@ -467,9 +426,6 @@ pipewire_output_disable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL:
|
||||
pipewire_output_disable_gl(output);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
pipewire_output_disable_vulkan(output);
|
||||
break;
|
||||
default:
|
||||
unreachable("Valid renderer should have been selected");
|
||||
}
|
||||
|
|
@ -534,8 +490,8 @@ pipewire_output_create_dmabuf(struct pipewire_output *output)
|
|||
uint64_t modifier[] = { DRM_FORMAT_MOD_LINEAR };
|
||||
|
||||
format = output->pixel_format;
|
||||
width = output->base.current_mode->width;
|
||||
height = output->base.current_mode->height;
|
||||
width = output->base.width;
|
||||
height = output->base.height;
|
||||
|
||||
linux_dmabuf_memory = renderer->dmabuf_alloc(renderer, width, height,
|
||||
format->format,
|
||||
|
|
@ -637,6 +593,59 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
|
|||
pw_stream_update_params(output->stream, params, 2);
|
||||
}
|
||||
|
||||
static struct weston_renderbuffer *
|
||||
pipewire_output_stream_add_buffer_pixman(struct pipewire_output *output,
|
||||
struct pw_buffer *buffer)
|
||||
{
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
const struct weston_renderer *renderer = ec->renderer;
|
||||
struct spa_buffer *buf = buffer->buffer;
|
||||
struct spa_data *d = buf->datas;
|
||||
const struct pixel_format_info *format;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int stride;
|
||||
void *ptr;
|
||||
|
||||
format = output->pixel_format;
|
||||
width = output->base.width;
|
||||
height = output->base.height;
|
||||
stride = width * format->bpp / 8;
|
||||
ptr = d[0].data;
|
||||
|
||||
return renderer->pixman->create_image_from_ptr(&output->base,
|
||||
format, width, height,
|
||||
ptr, stride);
|
||||
}
|
||||
|
||||
static struct weston_renderbuffer *
|
||||
pipewire_output_stream_add_buffer_gl(struct pipewire_output *output,
|
||||
struct pw_buffer *buffer)
|
||||
{
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
const struct weston_renderer *renderer = ec->renderer;
|
||||
struct spa_buffer *buf = buffer->buffer;
|
||||
struct spa_data *d = buf->datas;
|
||||
const struct pixel_format_info *format;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
void *ptr;
|
||||
struct pipewire_frame_data *frame_data = buffer->user_data;
|
||||
struct pipewire_dmabuf *dmabuf = frame_data->dmabuf;
|
||||
|
||||
if (dmabuf)
|
||||
return renderer->create_renderbuffer_dmabuf(&output->base,
|
||||
dmabuf->linux_dmabuf_memory);
|
||||
|
||||
format = output->pixel_format;
|
||||
width = output->base.width;
|
||||
height = output->base.height;
|
||||
ptr = d[0].data;
|
||||
|
||||
return renderer->gl->create_fbo(&output->base,
|
||||
format, width, height, ptr);
|
||||
}
|
||||
|
||||
struct pipewire_memfd {
|
||||
int fd;
|
||||
unsigned int size;
|
||||
|
|
@ -656,8 +665,8 @@ pipewire_output_create_memfd(struct pipewire_output *output)
|
|||
memfd = xzalloc(sizeof *memfd);
|
||||
|
||||
format = output->pixel_format;
|
||||
width = output->base.current_mode->width;
|
||||
height = output->base.current_mode->height;
|
||||
width = output->base.width;
|
||||
height = output->base.height;
|
||||
stride = width * format->bpp / 8;
|
||||
size = height * stride;
|
||||
|
||||
|
|
@ -746,15 +755,8 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
|||
return;
|
||||
}
|
||||
pipewire_output_setup_dmabuf(output, buffer, dmabuf);
|
||||
|
||||
frame_data->renderbuffer =
|
||||
renderer->create_renderbuffer_dmabuf(&output->base,
|
||||
dmabuf->linux_dmabuf_memory,
|
||||
NULL, NULL);
|
||||
frame_data->dmabuf = dmabuf;
|
||||
} else if (buffertype & (1u << SPA_DATA_MemFd)) {
|
||||
const struct pixel_format_info *format = output->pixel_format;
|
||||
int stride = output->base.current_mode->width * format->bpp / 8;
|
||||
struct pipewire_memfd *memfd;
|
||||
|
||||
memfd = pipewire_output_create_memfd(output);
|
||||
|
|
@ -764,13 +766,19 @@ pipewire_output_stream_add_buffer(void *data, struct pw_buffer *buffer)
|
|||
return;
|
||||
}
|
||||
pipewire_output_setup_memfd(output, buffer, memfd);
|
||||
|
||||
frame_data->renderbuffer =
|
||||
renderer->create_renderbuffer(&output->base, format,
|
||||
d[0].data, stride, NULL,
|
||||
NULL);
|
||||
frame_data->memfd = memfd;
|
||||
}
|
||||
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
frame_data->renderbuffer = pipewire_output_stream_add_buffer_pixman(output, buffer);
|
||||
break;
|
||||
case WESTON_RENDERER_GL:
|
||||
frame_data->renderbuffer = pipewire_output_stream_add_buffer_gl(output, buffer);
|
||||
break;
|
||||
default:
|
||||
unreachable("Valid renderer should have been selected");
|
||||
}
|
||||
}
|
||||
|
||||
struct pipewire_fence_data {
|
||||
|
|
@ -792,20 +800,21 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
|
|||
|
||||
pipewire_output_debug(output, "remove buffer: %p", buffer);
|
||||
|
||||
if (frame_data->dmabuf)
|
||||
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
|
||||
if (frame_data->dmabuf) {
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
const struct weston_renderer *renderer = ec->renderer;
|
||||
|
||||
renderer->remove_renderbuffer_dmabuf(&output->base,
|
||||
frame_data->renderbuffer);
|
||||
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
|
||||
}
|
||||
if (frame_data->memfd) {
|
||||
munmap(d[0].data, d[0].maxsize);
|
||||
pipewire_destroy_memfd(output, frame_data->memfd);
|
||||
}
|
||||
|
||||
if (frame_data->renderbuffer) {
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
const struct weston_renderer *renderer = ec->renderer;
|
||||
|
||||
renderer->destroy_renderbuffer(frame_data->renderbuffer);
|
||||
}
|
||||
if (frame_data->renderbuffer)
|
||||
weston_renderbuffer_unref(frame_data->renderbuffer);
|
||||
wl_list_for_each(fence_data, &output->fence_list, link) {
|
||||
if (fence_data->buffer == buffer)
|
||||
fence_data->buffer = NULL;
|
||||
|
|
@ -946,7 +955,7 @@ pipewire_submit_buffer(struct pipewire_output *output,
|
|||
if (dmabuf)
|
||||
stride = dmabuf->linux_dmabuf_memory->attributes->stride[0];
|
||||
else
|
||||
stride = output->base.current_mode->width * pixel_format->bpp / 8;
|
||||
stride = output->base.width * pixel_format->bpp / 8;
|
||||
size = output->base.height * stride;
|
||||
|
||||
spa_buffer = buffer->buffer;
|
||||
|
|
@ -999,20 +1008,9 @@ pipewire_schedule_submit_buffer(struct pipewire_output *output,
|
|||
struct wl_event_loop *loop;
|
||||
int fence_sync_fd;
|
||||
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_GL:
|
||||
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
|
||||
if (fence_sync_fd == -1)
|
||||
return -1;
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
fence_sync_fd = renderer->vulkan->create_fence_fd(&output->base);
|
||||
if (fence_sync_fd == -1)
|
||||
return -1;
|
||||
break;
|
||||
default:
|
||||
unreachable("invalid renderer");
|
||||
}
|
||||
fence_sync_fd = renderer->gl->create_fence_fd(&output->base);
|
||||
if (fence_sync_fd == -1)
|
||||
return -1;
|
||||
|
||||
fence_data = zalloc(sizeof *fence_data);
|
||||
if (!fence_data) {
|
||||
|
|
@ -1044,7 +1042,6 @@ pipewire_output_repaint(struct weston_output *base)
|
|||
struct pipewire_frame_data *frame_data;
|
||||
pixman_region32_t damage;
|
||||
bool submit_scheduled = false;
|
||||
bool rendered = false;
|
||||
|
||||
assert(output);
|
||||
|
||||
|
|
@ -1055,8 +1052,7 @@ pipewire_output_repaint(struct weston_output *base)
|
|||
|
||||
weston_output_flush_damage_for_primary_plane(base, &damage);
|
||||
|
||||
if (!pixman_region32_not_empty(&damage) &&
|
||||
!weston_output_has_renderer_capture_tasks(base))
|
||||
if (!pixman_region32_not_empty(&damage))
|
||||
goto out;
|
||||
|
||||
buffer = pw_stream_dequeue_buffer(output->stream);
|
||||
|
|
@ -1067,10 +1063,9 @@ pipewire_output_repaint(struct weston_output *base)
|
|||
pipewire_output_debug(output, "dequeued buffer: %p", buffer);
|
||||
|
||||
frame_data = buffer->user_data;
|
||||
if (frame_data->renderbuffer) {
|
||||
if (frame_data->renderbuffer)
|
||||
ec->renderer->repaint_output(&output->base, &damage, frame_data->renderbuffer);
|
||||
rendered = true;
|
||||
} else
|
||||
else
|
||||
output->base.full_repaint_needed = true;
|
||||
|
||||
if (buffer->buffer->datas[0].type == SPA_DATA_DmaBuf) {
|
||||
|
|
@ -1081,21 +1076,6 @@ pipewire_output_repaint(struct weston_output *base)
|
|||
pipewire_submit_buffer(output, buffer);
|
||||
|
||||
out:
|
||||
/* We didn't have anywhere to render to, so capture tasks could be
|
||||
* left dangling. Shoot them down.
|
||||
*/
|
||||
if (!rendered && weston_output_has_renderer_capture_tasks(base)) {
|
||||
int width = base->current_mode->width;
|
||||
int height = base->current_mode->height;
|
||||
struct weston_capture_task *ct;
|
||||
|
||||
while ((ct = weston_output_pull_capture_task(base,
|
||||
WESTON_OUTPUT_CAPTURE_SOURCE_FRAMEBUFFER,
|
||||
width, height,
|
||||
ec->read_format,
|
||||
NULL)))
|
||||
weston_capture_task_retire_failed(ct, "No pipewire buffer");
|
||||
}
|
||||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
|
|
@ -1136,19 +1116,6 @@ pipewire_ensure_matching_mode(struct weston_output *output, struct weston_mode *
|
|||
target->refresh);
|
||||
}
|
||||
|
||||
static void
|
||||
pipewire_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||
{
|
||||
struct pipewire_output *output = to_pipewire_output(base);
|
||||
|
||||
if (level == WESTON_DPMS_ON)
|
||||
weston_output_schedule_repaint(base);
|
||||
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||
weston_output_schedule_repaint_reset(base);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
||||
{
|
||||
|
|
@ -1175,13 +1142,14 @@ pipewire_switch_mode(struct weston_output *base, struct weston_mode *target_mode
|
|||
}
|
||||
|
||||
static int
|
||||
pipewire_output_set_size(struct weston_output *base, int width, int height, int framerate)
|
||||
pipewire_output_set_size(struct weston_output *base, int width, int height)
|
||||
{
|
||||
struct pipewire_output *output = to_pipewire_output(base);
|
||||
struct weston_head *head;
|
||||
struct pipewire_head *pw_head;
|
||||
struct weston_mode *current_mode;
|
||||
struct weston_mode init_mode;
|
||||
int framerate = -1;
|
||||
|
||||
/* We can only be called once. */
|
||||
assert(!output->base.current_mode);
|
||||
|
|
@ -1193,8 +1161,7 @@ pipewire_output_set_size(struct weston_output *base, int width, int height, int
|
|||
width = pw_head->config.width;
|
||||
if (height == -1)
|
||||
height = pw_head->config.height;
|
||||
if (framerate == -1)
|
||||
framerate = pw_head->config.framerate;
|
||||
framerate = pw_head->config.framerate;
|
||||
}
|
||||
if (framerate == -1 || width == -1 || height == -1)
|
||||
return -1;
|
||||
|
|
@ -1212,7 +1179,7 @@ pipewire_output_set_size(struct weston_output *base, int width, int height, int
|
|||
output->base.repaint = pipewire_output_repaint;
|
||||
output->base.assign_planes = NULL;
|
||||
output->base.set_backlight = NULL;
|
||||
output->base.set_dpms = pipewire_set_dpms;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = pipewire_switch_mode;
|
||||
|
||||
return 0;
|
||||
|
|
@ -1385,16 +1352,6 @@ pipewire_backend_create(struct weston_compositor *compositor,
|
|||
&options.base);
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_display_options options = {
|
||||
.formats = backend->formats,
|
||||
.formats_count = backend->formats_count,
|
||||
};
|
||||
ret = weston_compositor_init_renderer(compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
weston_log("Unsupported renderer requested\n");
|
||||
goto err_compositor;
|
||||
|
|
@ -1460,7 +1417,6 @@ weston_backend_init(struct weston_compositor *compositor,
|
|||
switch (compositor->renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
case WESTON_RENDERER_GL:
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
break;
|
||||
default:
|
||||
weston_log("Renderer not supported by PipeWire backend\n");
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ dep_frdp2 = dependency('freerdp2', version: '>= 2.3.0', required: false)
|
|||
|
||||
if dep_frdp3.found()
|
||||
config_h.set('USE_FREERDP_VERSION', '3')
|
||||
config_h.set('WITHOUT_FREERDP_3x_DEPRECATED', '1')
|
||||
dep_frdp = dep_frdp3
|
||||
dep_frdp_server = dependency('freerdp-server3', version: '>= 3.0.0', required: false)
|
||||
if not dep_frdp_server.found()
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@
|
|||
#include <libweston/pixel-formats.h>
|
||||
#include "pixman-renderer.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
|
||||
/* These can be removed when we bump FreeRDP dependency past 3.0.0 in the future */
|
||||
|
|
@ -59,12 +58,6 @@
|
|||
|
||||
extern PWtsApiFunctionTable FreeRDP_InitWtsApi(void);
|
||||
|
||||
static struct rdp_buffer *
|
||||
rdp_buffer_create(struct rdp_output *output);
|
||||
|
||||
static void
|
||||
rdp_buffer_destroy(struct rdp_buffer *buffer);
|
||||
|
||||
static BOOL
|
||||
xf_peer_adjust_monitor_layout(freerdp_peer *client);
|
||||
|
||||
|
|
@ -268,11 +261,11 @@ rdp_peer_refresh_region(pixman_region32_t *region, freerdp_peer *peer)
|
|||
rdpSettings *settings = peer->context->settings;
|
||||
|
||||
if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec))
|
||||
rdp_peer_refresh_rfx(region, output->buffer->shadow_surface, peer);
|
||||
rdp_peer_refresh_rfx(region, output->shadow_surface, peer);
|
||||
else if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec))
|
||||
rdp_peer_refresh_nsc(region, output->buffer->shadow_surface, peer);
|
||||
rdp_peer_refresh_nsc(region, output->shadow_surface, peer);
|
||||
else
|
||||
rdp_peer_refresh_raw(region, output->buffer->shadow_surface, peer);
|
||||
rdp_peer_refresh_raw(region, output->shadow_surface, peer);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -302,7 +295,7 @@ rdp_output_repaint(struct weston_output *output_base)
|
|||
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||
|
||||
ec->renderer->repaint_output(&output->base, &damage,
|
||||
output->buffer->rb);
|
||||
output->renderbuffer);
|
||||
|
||||
if (pixman_region32_not_empty(&damage)) {
|
||||
pixman_region32_t transformed_damage;
|
||||
|
|
@ -353,15 +346,53 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
|
|||
struct weston_output *output = base;
|
||||
struct rdp_peers_item *rdpPeer;
|
||||
rdpSettings *settings;
|
||||
struct weston_renderbuffer *new_renderbuffer;
|
||||
|
||||
mode->refresh = b->rdp_monitor_refresh_rate;
|
||||
weston_output_set_single_mode(base, mode);
|
||||
|
||||
if (base->enabled)
|
||||
if (base->enabled) {
|
||||
const struct weston_renderer *renderer;
|
||||
pixman_image_t *new_image;
|
||||
|
||||
weston_renderer_resize_output(output, &(struct weston_size){
|
||||
.width = output->current_mode->width,
|
||||
.height = output->current_mode->height }, NULL);
|
||||
|
||||
new_image = pixman_image_create_bits(b->formats[0]->pixman_format,
|
||||
mode->width, mode->height,
|
||||
NULL, mode->width * 4);
|
||||
renderer = b->compositor->renderer;
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN: {
|
||||
const struct pixman_renderer_interface *pixman;
|
||||
|
||||
pixman = renderer->pixman;
|
||||
new_renderbuffer =
|
||||
pixman->create_image_from_ptr(output, b->formats[0],
|
||||
mode->width, mode->height,
|
||||
pixman_image_get_data(new_image),
|
||||
mode->width * 4);
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_GL:
|
||||
new_renderbuffer =
|
||||
renderer->gl->create_fbo(output, b->formats[0],
|
||||
mode->width, mode->height,
|
||||
pixman_image_get_data(new_image));
|
||||
break;
|
||||
default:
|
||||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
pixman_image_composite32(PIXMAN_OP_SRC, rdpOutput->shadow_surface,
|
||||
0, new_image, 0, 0, 0, 0, 0, 0,
|
||||
mode->width, mode->height);
|
||||
weston_renderbuffer_unref(rdpOutput->renderbuffer);
|
||||
rdpOutput->renderbuffer = new_renderbuffer;
|
||||
pixman_image_unref(rdpOutput->shadow_surface);
|
||||
rdpOutput->shadow_surface = new_image;
|
||||
}
|
||||
|
||||
/* Apparently settings->DesktopWidth is supposed to be primary only.
|
||||
* For now we only work with a single monitor, so we don't need to
|
||||
* check that we're primary here.
|
||||
|
|
@ -384,19 +415,6 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rdp_output_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||
{
|
||||
struct rdp_output *output = to_rdp_output(base);
|
||||
|
||||
if (level == WESTON_DPMS_ON)
|
||||
weston_output_schedule_repaint(base);
|
||||
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||
weston_output_schedule_repaint_reset(base);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rdp_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
||||
{
|
||||
|
|
@ -418,88 +436,11 @@ rdp_head_get_monitor(struct weston_head *base,
|
|||
monitor->desktop_scale = h->config.attributes.desktopScaleFactor;
|
||||
}
|
||||
|
||||
static bool
|
||||
rdp_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||
{
|
||||
struct rdp_buffer *buffer = (struct rdp_buffer *) data;
|
||||
struct rdp_output *output = buffer->output;
|
||||
|
||||
rdp_buffer_destroy(buffer);
|
||||
output->buffer = rdp_buffer_create(output);
|
||||
if (output->buffer == NULL)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct rdp_buffer *
|
||||
rdp_buffer_create(struct rdp_output *output)
|
||||
{
|
||||
const struct pixel_format_info *format = output->backend->formats[0];
|
||||
struct weston_renderer *rdr = output->base.compositor->renderer;
|
||||
pixman_image_t *shadow_surface;
|
||||
weston_renderbuffer_t rb;
|
||||
struct rdp_buffer *buffer;
|
||||
|
||||
shadow_surface = pixman_image_create_bits(format->pixman_format,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
NULL,
|
||||
output->base.current_mode->width * 4);
|
||||
buffer = xmalloc(sizeof *buffer);
|
||||
|
||||
rb = rdr->create_renderbuffer(&output->base, format,
|
||||
pixman_image_get_data(shadow_surface),
|
||||
output->base.current_mode->width * 4,
|
||||
rdp_rb_discarded_cb, buffer);
|
||||
if (rb == NULL) {
|
||||
weston_log("Failed to create offscreen renderbuffer.\n");
|
||||
pixman_image_unref(shadow_surface);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->output = output;
|
||||
buffer->shadow_surface = shadow_surface;
|
||||
buffer->rb = rb;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
rdp_buffer_destroy(struct rdp_buffer *buffer)
|
||||
{
|
||||
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
|
||||
|
||||
pixman_image_unref(buffer->shadow_surface);
|
||||
rdr->destroy_renderbuffer(buffer->rb);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
rdp_renderer_output_destroy(struct weston_output *base)
|
||||
{
|
||||
struct weston_renderer *rdr = base->compositor->renderer;
|
||||
|
||||
switch (rdr->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
rdr->pixman->output_destroy(base);
|
||||
break;
|
||||
case WESTON_RENDERER_GL:
|
||||
rdr->gl->output_destroy(base);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
rdr->vulkan->output_destroy(base);
|
||||
break;
|
||||
default:
|
||||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rdp_output_enable(struct weston_output *base)
|
||||
{
|
||||
const struct weston_renderer *renderer = base->compositor->renderer;
|
||||
const struct pixman_renderer_interface *pixman = renderer->pixman;
|
||||
struct rdp_output *output = to_rdp_output(base);
|
||||
struct rdp_backend *b;
|
||||
struct wl_event_loop *loop;
|
||||
|
|
@ -508,6 +449,12 @@ rdp_output_enable(struct weston_output *base)
|
|||
|
||||
b = output->backend;
|
||||
|
||||
output->shadow_surface = pixman_image_create_bits(b->formats[0]->pixman_format,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
NULL,
|
||||
output->base.current_mode->width * 4);
|
||||
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN: {
|
||||
const struct pixman_renderer_output_options options = {
|
||||
|
|
@ -518,8 +465,23 @@ rdp_output_enable(struct weston_output *base)
|
|||
.format = b->formats[0],
|
||||
};
|
||||
|
||||
if (renderer->pixman->output_create(&output->base, &options) < 0)
|
||||
if (renderer->pixman->output_create(&output->base, &options) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
output->renderbuffer =
|
||||
pixman->create_image_from_ptr(&output->base, options.format,
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
pixman_image_get_data(output->shadow_surface),
|
||||
output->base.current_mode->width * 4);
|
||||
if (output->renderbuffer == NULL) {
|
||||
weston_log("Failed to create surface for frame buffer.\n");
|
||||
renderer->pixman->output_destroy(&output->base);
|
||||
pixman_image_unref(output->shadow_surface);
|
||||
output->shadow_surface = NULL;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_GL: {
|
||||
|
|
@ -534,24 +496,19 @@ rdp_output_enable(struct weston_output *base)
|
|||
},
|
||||
};
|
||||
|
||||
if (renderer->gl->output_fbo_create(&output->base, &options) < 0) {
|
||||
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_surfaceless_options options = {
|
||||
.area = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
},
|
||||
.fb_size = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
},
|
||||
};
|
||||
|
||||
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||
output->renderbuffer =
|
||||
renderer->gl->create_fbo(&output->base, b->formats[0],
|
||||
output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
pixman_image_get_data(output->shadow_surface));
|
||||
if (output->renderbuffer == NULL) {
|
||||
weston_log("Failed to create surface for frame buffer.\n");
|
||||
renderer->pixman->output_destroy(&output->base);
|
||||
pixman_image_unref(output->shadow_surface);
|
||||
output->shadow_surface = NULL;
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
|
@ -560,12 +517,6 @@ rdp_output_enable(struct weston_output *base)
|
|||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
|
||||
output->buffer = rdp_buffer_create(output);
|
||||
if (output->buffer == NULL) {
|
||||
rdp_renderer_output_destroy(base);
|
||||
return -1;
|
||||
}
|
||||
|
||||
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
||||
output->finish_frame_timer = wl_event_loop_add_timer(loop, finish_frame_handler, output);
|
||||
|
||||
|
|
@ -575,6 +526,7 @@ rdp_output_enable(struct weston_output *base)
|
|||
static int
|
||||
rdp_output_disable(struct weston_output *base)
|
||||
{
|
||||
struct weston_renderer *renderer = base->compositor->renderer;
|
||||
struct rdp_output *output = to_rdp_output(base);
|
||||
|
||||
assert(output);
|
||||
|
|
@ -582,9 +534,21 @@ rdp_output_disable(struct weston_output *base)
|
|||
if (!output->base.enabled)
|
||||
return 0;
|
||||
|
||||
rdp_buffer_destroy(output->buffer);
|
||||
output->buffer = NULL;
|
||||
rdp_renderer_output_destroy(base);
|
||||
weston_renderbuffer_unref(output->renderbuffer);
|
||||
output->renderbuffer = NULL;
|
||||
switch (renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
renderer->pixman->output_destroy(&output->base);
|
||||
break;
|
||||
case WESTON_RENDERER_GL:
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
break;
|
||||
default:
|
||||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
pixman_image_unref(output->shadow_surface);
|
||||
output->shadow_surface = NULL;
|
||||
|
||||
wl_event_source_remove(output->finish_frame_timer);
|
||||
|
||||
return 0;
|
||||
|
|
@ -620,7 +584,6 @@ rdp_output_create(struct weston_backend *backend, const char *name)
|
|||
|
||||
output->base.start_repaint_loop = rdp_output_start_repaint_loop;
|
||||
output->base.repaint = rdp_output_repaint;
|
||||
output->base.set_dpms = rdp_output_set_dpms;
|
||||
output->base.switch_mode = rdp_output_switch_mode;
|
||||
|
||||
output->backend = b;
|
||||
|
|
@ -1022,9 +985,6 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
|
|||
{KBD_IRISH, 0, 0},
|
||||
{KBD_BOSNIAN_CYRILLIC, "ba", "us"},
|
||||
{KBD_UNITED_STATES_DVORAK, "us", "dvorak"},
|
||||
{KBD_UNITED_STATES_DVORAK_FOR_LEFT_HAND, "us", "dvorak-l"},
|
||||
{KBD_UNITED_STATES_DVORAK_FOR_RIGHT_HAND, "us", "dvorak-r"},
|
||||
{KBD_UNITED_STATES_DVORAK_PROGRAMMER, "us", "dvp"},
|
||||
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "abnt2"},
|
||||
{KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"},
|
||||
{KBD_GAELIC, "ie", "CloGaelach"},
|
||||
|
|
@ -2029,18 +1989,6 @@ rdp_backend_create(struct weston_compositor *compositor,
|
|||
goto err_compositor;
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_display_options options = {
|
||||
.formats = b->formats,
|
||||
.formats_count = b->formats_count,
|
||||
};
|
||||
|
||||
if (weston_compositor_init_renderer(compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base) < 0)
|
||||
goto err_compositor;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
weston_log("Unsupported renderer requested\n");
|
||||
goto err_free_strings;
|
||||
|
|
@ -2165,7 +2113,6 @@ weston_backend_init(struct weston_compositor *compositor,
|
|||
switch (compositor->renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
case WESTON_RENDERER_GL:
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
break;
|
||||
default:
|
||||
weston_log("Renderer not supported by RDP backend\n");
|
||||
|
|
|
|||
|
|
@ -27,6 +27,14 @@
|
|||
#ifndef RDP_H
|
||||
#define RDP_H
|
||||
|
||||
/* Workaround an issue with clang and freerdp 3 headers. Another
|
||||
* option would be to build with --std=c11 but weston itself isn't
|
||||
* quite ready for that
|
||||
*/
|
||||
#if USE_FREERDP_VERSION >= 3 && defined(__clang__)
|
||||
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
|
||||
#endif
|
||||
|
||||
#include <freerdp/version.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
|
|
@ -47,7 +55,6 @@
|
|||
#include <winpr/string.h>
|
||||
|
||||
#include "backend.h"
|
||||
#include "libweston-internal.h"
|
||||
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/string-helpers.h"
|
||||
|
|
@ -138,17 +145,12 @@ struct rdp_head {
|
|||
rdpMonitor config;
|
||||
};
|
||||
|
||||
struct rdp_buffer {
|
||||
struct rdp_output *output;
|
||||
pixman_image_t *shadow_surface;
|
||||
weston_renderbuffer_t rb;
|
||||
};
|
||||
|
||||
struct rdp_output {
|
||||
struct weston_output base;
|
||||
struct rdp_backend *backend;
|
||||
struct wl_event_source *finish_frame_timer;
|
||||
struct rdp_buffer *buffer;
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
pixman_image_t *shadow_surface;
|
||||
};
|
||||
|
||||
struct rdp_peer_context {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ if not get_option('backend-vnc')
|
|||
endif
|
||||
|
||||
config_h.set('BUILD_VNC_COMPOSITOR', '1')
|
||||
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.10.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
|
||||
dep_neatvnc = dependency('neatvnc', version: ['>= 0.7.0', '< 0.9.0'], required: false, fallback: ['neatvnc', 'neatvnc_dep'])
|
||||
if not dep_neatvnc.found()
|
||||
error('VNC backend requires neatvnc which was not found. Or, you can use \'-Dbackend-vnc=false\'.')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@
|
|||
#include "pixel-formats.h"
|
||||
#include "pixman-renderer.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
|
||||
#define DEFAULT_AXIS_STEP_DISTANCE 10
|
||||
|
|
@ -109,18 +108,9 @@ struct vnc_head {
|
|||
struct weston_head base;
|
||||
};
|
||||
|
||||
struct vnc_buffer {
|
||||
weston_renderbuffer_t rb;
|
||||
struct nvnc_fb *fb;
|
||||
struct vnc_output *output;
|
||||
};
|
||||
|
||||
static void
|
||||
vnc_output_destroy(struct weston_output *base);
|
||||
|
||||
static void
|
||||
vnc_buffer_destroy(struct vnc_buffer *buffer);
|
||||
|
||||
static inline struct vnc_output *
|
||||
to_vnc_output(struct weston_output *base)
|
||||
{
|
||||
|
|
@ -663,7 +653,8 @@ vnc_log_scope_print_region(struct weston_log_scope *log, pixman_region32_t *regi
|
|||
}
|
||||
|
||||
static void
|
||||
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
|
||||
vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *buffer_damage,
|
||||
pixman_region32_t *update_damage)
|
||||
{
|
||||
char timestr[128];
|
||||
|
||||
|
|
@ -672,51 +663,15 @@ vnc_log_damage(struct vnc_backend *backend, pixman_region32_t *damage)
|
|||
|
||||
weston_log_scope_timestamp(backend->debug, timestr, sizeof timestr);
|
||||
|
||||
weston_log_scope_printf(backend->debug, "%s damage:", timestr);
|
||||
vnc_log_scope_print_region(backend->debug, damage);
|
||||
weston_log_scope_printf(backend->debug, "%s buffer damage:", timestr);
|
||||
vnc_log_scope_print_region(backend->debug, buffer_damage);
|
||||
weston_log_scope_printf(backend->debug, "\n");
|
||||
|
||||
weston_log_scope_printf(backend->debug, "%s update damage:", timestr);
|
||||
vnc_log_scope_print_region(backend->debug, update_damage);
|
||||
weston_log_scope_printf(backend->debug, "\n\n");
|
||||
}
|
||||
|
||||
static bool
|
||||
vnc_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||
{
|
||||
struct vnc_buffer *buffer = (struct vnc_buffer *) data;
|
||||
|
||||
assert(nvnc_get_userdata(buffer->fb) == buffer);
|
||||
|
||||
nvnc_set_userdata(buffer->fb, NULL, NULL);
|
||||
vnc_buffer_destroy(buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct vnc_buffer *
|
||||
vnc_buffer_create(struct nvnc_fb* fb, struct vnc_output *output)
|
||||
{
|
||||
const struct pixel_format_info *pfmt =
|
||||
pixel_format_get_info(DRM_FORMAT_XRGB8888);
|
||||
struct weston_renderer *rdr = output->base.compositor->renderer;
|
||||
struct vnc_buffer *buffer = xmalloc(sizeof *buffer);
|
||||
|
||||
buffer->rb = rdr->create_renderbuffer(&output->base, pfmt,
|
||||
nvnc_fb_get_addr(fb),
|
||||
output->base.current_mode->width * 4,
|
||||
vnc_rb_discarded_cb, buffer);
|
||||
buffer->fb = fb;
|
||||
buffer->output = output;
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
vnc_buffer_destroy(struct vnc_buffer *buffer)
|
||||
{
|
||||
struct weston_renderer *rdr = buffer->output->base.compositor->renderer;
|
||||
|
||||
rdr->destroy_renderbuffer(buffer->rb);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
||||
{
|
||||
|
|
@ -724,7 +679,7 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
|||
struct vnc_backend *backend = nvnc_get_userdata(server);
|
||||
struct vnc_output *output = backend->output;
|
||||
struct weston_compositor *ec = output->base.compositor;
|
||||
struct vnc_buffer *buffer;
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
pixman_region32_t local_damage;
|
||||
pixman_region16_t nvnc_damage;
|
||||
struct nvnc_fb *fb;
|
||||
|
|
@ -732,16 +687,49 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
|
|||
fb = nvnc_fb_pool_acquire(output->fb_pool);
|
||||
assert(fb);
|
||||
|
||||
buffer = nvnc_get_userdata(fb);
|
||||
if (!buffer) {
|
||||
buffer = vnc_buffer_create(fb, output);
|
||||
nvnc_set_userdata(fb, buffer,
|
||||
(nvnc_cleanup_fn) vnc_buffer_destroy);
|
||||
renderbuffer = nvnc_get_userdata(fb);
|
||||
if (!renderbuffer) {
|
||||
const struct pixel_format_info *pfmt;
|
||||
|
||||
pfmt = pixel_format_get_info(DRM_FORMAT_XRGB8888);
|
||||
|
||||
switch (ec->renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN: {
|
||||
const struct pixman_renderer_interface *pixman;
|
||||
|
||||
pixman = ec->renderer->pixman;
|
||||
|
||||
renderbuffer =
|
||||
pixman->create_image_from_ptr(&output->base, pfmt,
|
||||
output->base.width,
|
||||
output->base.height,
|
||||
nvnc_fb_get_addr(fb),
|
||||
output->base.width * 4);
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_GL: {
|
||||
renderbuffer =
|
||||
ec->renderer->gl->create_fbo(&output->base, pfmt,
|
||||
output->base.width,
|
||||
output->base.height,
|
||||
nvnc_fb_get_addr(fb));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
|
||||
/* This is a new buffer, so the whole surface is damaged. */
|
||||
pixman_region32_copy(&renderbuffer->damage,
|
||||
&output->base.region);
|
||||
|
||||
nvnc_set_userdata(fb, renderbuffer,
|
||||
(nvnc_cleanup_fn)weston_renderbuffer_unref);
|
||||
}
|
||||
|
||||
vnc_log_damage(backend, damage);
|
||||
vnc_log_damage(backend, &renderbuffer->damage, damage);
|
||||
|
||||
ec->renderer->repaint_output(&output->base, damage, buffer->rb);
|
||||
ec->renderer->repaint_output(&output->base, damage, renderbuffer);
|
||||
|
||||
/* Convert to local coordinates */
|
||||
pixman_region32_init(&local_damage);
|
||||
|
|
@ -821,8 +809,8 @@ vnc_output_enable(struct weston_output *base)
|
|||
case WESTON_RENDERER_PIXMAN: {
|
||||
const struct pixman_renderer_output_options options = {
|
||||
.fb_size = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
.width = output->base.width,
|
||||
.height = output->base.height,
|
||||
},
|
||||
.format = backend->formats[0],
|
||||
};
|
||||
|
|
@ -833,33 +821,18 @@ vnc_output_enable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL: {
|
||||
const struct gl_renderer_fbo_options options = {
|
||||
.area = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
.width = output->base.width,
|
||||
.height = output->base.height,
|
||||
},
|
||||
.fb_size = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
.width = output->base.width,
|
||||
.height = output->base.height,
|
||||
},
|
||||
};
|
||||
if (renderer->gl->output_fbo_create(&output->base, &options) < 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_surfaceless_options options = {
|
||||
.area = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
},
|
||||
.fb_size = {
|
||||
.width = output->base.current_mode->width,
|
||||
.height = output->base.current_mode->height,
|
||||
},
|
||||
};
|
||||
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
|
|
@ -869,10 +842,10 @@ vnc_output_enable(struct weston_output *base)
|
|||
finish_frame_handler,
|
||||
output);
|
||||
|
||||
output->fb_pool = nvnc_fb_pool_new(output->base.current_mode->width,
|
||||
output->base.current_mode->height,
|
||||
output->fb_pool = nvnc_fb_pool_new(output->base.width,
|
||||
output->base.height,
|
||||
backend->formats[0]->format,
|
||||
output->base.current_mode->width);
|
||||
output->base.width);
|
||||
|
||||
output->display = nvnc_display_new(0, 0);
|
||||
|
||||
|
|
@ -906,9 +879,6 @@ vnc_output_disable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL:
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
break;
|
||||
default:
|
||||
unreachable("cannot have auto renderer at runtime");
|
||||
}
|
||||
|
|
@ -1082,9 +1052,6 @@ vnc_output_assign_planes(struct weston_output *base)
|
|||
|
||||
assert(output);
|
||||
|
||||
if (output->base.disable_planes)
|
||||
return;
|
||||
|
||||
if (wl_list_empty(&output->peers))
|
||||
return;
|
||||
|
||||
|
|
@ -1093,19 +1060,6 @@ vnc_output_assign_planes(struct weston_output *base)
|
|||
vnc_output_assign_cursor_plane(output);
|
||||
}
|
||||
|
||||
static void
|
||||
vnc_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||
{
|
||||
struct vnc_output *output = to_vnc_output(base);
|
||||
|
||||
if (level == WESTON_DPMS_ON)
|
||||
weston_output_schedule_repaint(base);
|
||||
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||
weston_output_schedule_repaint_reset(base);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
||||
{
|
||||
|
|
@ -1119,14 +1073,7 @@ vnc_switch_mode(struct weston_output *base, struct weston_mode *target_mode)
|
|||
fb_size.width = target_mode->width;
|
||||
fb_size.height = target_mode->height;
|
||||
|
||||
/* vnc_buffers are stored as user data pointers into the renderbuffers
|
||||
* for the discarded callback. weston_renderer_resize_output(), which
|
||||
* triggers the renderbuffer's discarded callbacks, must be called
|
||||
* before nvnc_fb_pool_resize(), which destroys all the nvnc_fbs and
|
||||
* their associated vnc_buffers, so that the vnc_buffers are valid at
|
||||
* callback. */
|
||||
if (!weston_renderer_resize_output(base, &fb_size, NULL))
|
||||
return -1;
|
||||
weston_renderer_resize_output(base, &fb_size, NULL);
|
||||
|
||||
nvnc_fb_pool_resize(output->fb_pool, target_mode->width,
|
||||
target_mode->height, DRM_FORMAT_XRGB8888,
|
||||
|
|
@ -1158,7 +1105,7 @@ vnc_output_set_size(struct weston_output *base, int width, int height,
|
|||
output->base.repaint = vnc_output_repaint;
|
||||
output->base.assign_planes = vnc_output_assign_planes;
|
||||
output->base.set_backlight = NULL;
|
||||
output->base.set_dpms = vnc_set_dpms;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = vnc_switch_mode;
|
||||
|
||||
output->resizeable = resizeable;
|
||||
|
|
@ -1236,17 +1183,6 @@ vnc_backend_create(struct weston_compositor *compositor,
|
|||
goto err_compositor;
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_display_options options = {
|
||||
.formats = backend->formats,
|
||||
.formats_count = backend->formats_count,
|
||||
};
|
||||
if (weston_compositor_init_renderer(compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base) < 0)
|
||||
goto err_compositor;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
weston_log("Unsupported renderer requested\n");
|
||||
goto err_compositor;
|
||||
|
|
@ -1388,7 +1324,6 @@ weston_backend_init(struct weston_compositor *compositor,
|
|||
switch (compositor->renderer->type) {
|
||||
case WESTON_RENDERER_PIXMAN:
|
||||
case WESTON_RENDERER_GL:
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
break;
|
||||
default:
|
||||
weston_log("Renderer not supported by VNC backend\n");
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ config_h.set('BUILD_WAYLAND_COMPOSITOR', '1')
|
|||
|
||||
srcs_wlwl = [
|
||||
'wayland.c',
|
||||
fullscreen_shell_unstable_v1_client_protocol_h,
|
||||
fullscreen_shell_unstable_v1_protocol_c,
|
||||
presentation_time_protocol_c,
|
||||
presentation_time_server_protocol_h,
|
||||
xdg_shell_client_protocol_h,
|
||||
|
|
@ -19,7 +21,7 @@ deps_wlwl = [
|
|||
dep_libweston_private,
|
||||
dep_libdrm_headers,
|
||||
dep_lib_cairo_shared,
|
||||
dep_lib_renderer_borders,
|
||||
dep_lib_gl_borders,
|
||||
]
|
||||
|
||||
if get_option('renderer-gl')
|
||||
|
|
@ -31,10 +33,6 @@ if get_option('renderer-gl')
|
|||
deps_wlwl += dep_egl # for gl-renderer.h
|
||||
endif
|
||||
|
||||
if get_option('renderer-vulkan')
|
||||
deps_wlwl += dep_vulkan # for vulkan-renderer.h
|
||||
endif
|
||||
|
||||
plugin_wlwl = shared_library(
|
||||
'wayland-backend',
|
||||
srcs_wlwl,
|
||||
|
|
|
|||
|
|
@ -48,8 +48,7 @@
|
|||
#include <libweston/libweston.h>
|
||||
#include <libweston/backend-wayland.h>
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "renderer-borders.h"
|
||||
#include "gl-borders.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "pixman-renderer.h"
|
||||
|
|
@ -59,6 +58,7 @@
|
|||
#include "shared/cairo-util.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "fullscreen-shell-unstable-v1-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#include "presentation-time-server-protocol.h"
|
||||
#include "linux-dmabuf.h"
|
||||
|
|
@ -86,6 +86,7 @@ struct wayland_backend {
|
|||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zwp_fullscreen_shell_v1 *fshell;
|
||||
struct wl_shm *shm;
|
||||
|
||||
struct wl_list output_list;
|
||||
|
|
@ -98,6 +99,7 @@ struct wayland_backend {
|
|||
bool fullscreen;
|
||||
|
||||
struct theme *theme;
|
||||
cairo_device_t *frame_device;
|
||||
struct wl_cursor_theme *cursor_theme;
|
||||
struct wl_cursor *cursor;
|
||||
|
||||
|
|
@ -133,6 +135,7 @@ struct wayland_output {
|
|||
|
||||
struct {
|
||||
struct wl_egl_window *egl_window;
|
||||
struct weston_gl_borders borders;
|
||||
} gl;
|
||||
|
||||
struct {
|
||||
|
|
@ -140,8 +143,6 @@ struct wayland_output {
|
|||
struct wl_list free_buffers;
|
||||
} shm;
|
||||
|
||||
struct weston_renderer_borders borders;
|
||||
|
||||
struct weston_mode mode;
|
||||
struct weston_mode native_mode;
|
||||
|
||||
|
|
@ -191,7 +192,7 @@ struct wayland_shm_buffer {
|
|||
int height;
|
||||
int frame_damaged;
|
||||
|
||||
weston_renderbuffer_t renderbuffer;
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
cairo_surface_t *c_surface;
|
||||
};
|
||||
|
||||
|
|
@ -265,14 +266,9 @@ to_wayland_backend(struct weston_backend *base)
|
|||
static void
|
||||
wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
|
||||
{
|
||||
struct wayland_output *output = buffer->output;
|
||||
const struct weston_renderer *renderer;
|
||||
|
||||
cairo_surface_destroy(buffer->c_surface);
|
||||
if (output) {
|
||||
renderer = output->base.compositor->renderer;
|
||||
renderer->destroy_renderbuffer(buffer->renderbuffer);
|
||||
}
|
||||
if (buffer->output)
|
||||
weston_renderbuffer_unref(buffer->renderbuffer);
|
||||
|
||||
wl_buffer_destroy(buffer->buffer);
|
||||
munmap(buffer->data, buffer->size);
|
||||
|
|
@ -294,22 +290,6 @@ buffer_release(void *data, struct wl_buffer *buffer)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
wayland_rb_discarded_cb(weston_renderbuffer_t renderbuffer, void *data)
|
||||
{
|
||||
struct wayland_shm_buffer *sb = data;
|
||||
const struct weston_renderer *renderer;
|
||||
|
||||
if (sb->renderbuffer) {
|
||||
renderer = sb->output->backend->compositor->renderer;
|
||||
renderer->destroy_renderbuffer(sb->renderbuffer);
|
||||
sb->renderbuffer = NULL;
|
||||
}
|
||||
sb->output = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
|
@ -318,6 +298,7 @@ static struct wayland_shm_buffer *
|
|||
wayland_output_get_shm_buffer(struct wayland_output *output)
|
||||
{
|
||||
const struct weston_renderer *renderer;
|
||||
const struct pixman_renderer_interface *pixman;
|
||||
struct wayland_backend *b = output->backend;
|
||||
const struct pixel_format_info *pfmt = b->formats[0];
|
||||
uint32_t shm_format = pixel_format_get_shm_format(pfmt);
|
||||
|
|
@ -403,23 +384,26 @@ wayland_output_get_shm_buffer(struct wayland_output *output)
|
|||
if (output->frame) {
|
||||
frame_interior(output->frame, &area.x, &area.y,
|
||||
&area.width, &area.height);
|
||||
assert(area.width == output->base.current_mode->width);
|
||||
assert(area.height == output->base.current_mode->height);
|
||||
} else {
|
||||
area.x = 0;
|
||||
area.y = 0;
|
||||
area.width = output->base.current_mode->width;
|
||||
area.height = output->base.current_mode->height;
|
||||
}
|
||||
|
||||
renderer = b->compositor->renderer;
|
||||
pixman = renderer->pixman;
|
||||
|
||||
/* Address only the interior, excluding output decorations */
|
||||
if (renderer->type == WESTON_RENDERER_PIXMAN)
|
||||
if (renderer->type == WESTON_RENDERER_PIXMAN) {
|
||||
sb->renderbuffer =
|
||||
renderer->create_renderbuffer(&output->base, pfmt,
|
||||
pixman->create_image_from_ptr(&output->base, pfmt,
|
||||
area.width, area.height,
|
||||
(uint32_t *)(data + area.y * stride) + area.x,
|
||||
stride,
|
||||
wayland_rb_discarded_cb,
|
||||
sb);
|
||||
stride);
|
||||
pixman_region32_copy(&sb->renderbuffer->damage,
|
||||
&output->base.region);
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
|
@ -451,17 +435,34 @@ static const struct wl_callback_listener frame_listener = {
|
|||
frame_done
|
||||
};
|
||||
|
||||
#if defined(ENABLE_EGL) || defined(ENABLE_VULKAN)
|
||||
static void
|
||||
wayland_output_update_renderer_border(struct wayland_output *output)
|
||||
draw_initial_frame(struct wayland_output *output)
|
||||
{
|
||||
struct wayland_shm_buffer *sb;
|
||||
|
||||
sb = wayland_output_get_shm_buffer(output);
|
||||
|
||||
/* If we are rendering with GL, then orphan it so that it gets
|
||||
* destroyed immediately */
|
||||
if (output->gl.egl_window)
|
||||
sb->output = NULL;
|
||||
|
||||
wl_surface_attach(output->parent.surface, sb->buffer, 0, 0);
|
||||
wl_surface_damage(output->parent.surface, 0, 0,
|
||||
sb->width, sb->height);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EGL
|
||||
static void
|
||||
wayland_output_update_gl_border(struct wayland_output *output)
|
||||
{
|
||||
if (!output->frame)
|
||||
return;
|
||||
if (!(frame_status(output->frame) & FRAME_STATUS_REPAINT))
|
||||
return;
|
||||
|
||||
weston_renderer_borders_update(&output->borders, output->frame,
|
||||
&output->base);
|
||||
weston_gl_borders_update(&output->gl.borders, output->frame,
|
||||
&output->base);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -501,36 +502,7 @@ wayland_output_repaint_gl(struct weston_output *output_base)
|
|||
output->frame_cb = wl_surface_frame(output->parent.surface);
|
||||
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
||||
|
||||
wayland_output_update_renderer_border(output);
|
||||
|
||||
ec->renderer->repaint_output(&output->base, &damage, NULL);
|
||||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VULKAN
|
||||
static int
|
||||
wayland_output_repaint_vulkan(struct weston_output *output_base)
|
||||
{
|
||||
struct wayland_output *output = to_wayland_output(output_base);
|
||||
struct weston_compositor *ec;
|
||||
pixman_region32_t damage;
|
||||
|
||||
assert(output);
|
||||
|
||||
ec = output->base.compositor;
|
||||
|
||||
pixman_region32_init(&damage);
|
||||
|
||||
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||
|
||||
output->frame_cb = wl_surface_frame(output->parent.surface);
|
||||
wl_callback_add_listener(output->frame_cb, &frame_listener, output);
|
||||
|
||||
wayland_output_update_renderer_border(output);
|
||||
wayland_output_update_gl_border(output);
|
||||
|
||||
ec->renderer->repaint_output(&output->base, &damage, NULL);
|
||||
|
||||
|
|
@ -693,6 +665,14 @@ wayland_output_destroy_shm_buffers(struct wayland_output *output)
|
|||
/* Throw away any remaining SHM buffers */
|
||||
wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
|
||||
wayland_shm_buffer_destroy(buffer);
|
||||
/* These will get thrown away when they get released */
|
||||
wl_list_for_each(buffer, &output->shm.buffers, link) {
|
||||
if (buffer->renderbuffer) {
|
||||
weston_renderbuffer_unref(buffer->renderbuffer);
|
||||
buffer->renderbuffer = NULL;
|
||||
}
|
||||
buffer->output = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
@ -714,18 +694,11 @@ wayland_output_disable(struct weston_output *base)
|
|||
break;
|
||||
#ifdef ENABLE_EGL
|
||||
case WESTON_RENDERER_GL:
|
||||
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||
weston_gl_borders_fini(&output->gl.borders, &output->base);
|
||||
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
wl_egl_window_destroy(output->gl.egl_window);
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_VULKAN
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
unreachable("invalid renderer");
|
||||
|
|
@ -807,47 +780,6 @@ cleanup_window:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_VULKAN
|
||||
static int
|
||||
wayland_output_init_vulkan_renderer(struct wayland_output *output)
|
||||
{
|
||||
const struct weston_mode *mode = output->base.current_mode;
|
||||
struct wayland_backend *b = output->backend;
|
||||
const struct weston_renderer *renderer;
|
||||
struct vulkan_renderer_surface_options options = {
|
||||
.formats = b->formats,
|
||||
.formats_count = b->formats_count,
|
||||
};
|
||||
|
||||
if (output->frame) {
|
||||
frame_interior(output->frame, &options.area.x, &options.area.y,
|
||||
&options.area.width, &options.area.height);
|
||||
options.fb_size.width = frame_width(output->frame);
|
||||
options.fb_size.height = frame_height(output->frame);
|
||||
} else {
|
||||
options.area.x = 0;
|
||||
options.area.y = 0;
|
||||
options.area.width = mode->width;
|
||||
options.area.height = mode->height;
|
||||
options.fb_size.width = mode->width;
|
||||
options.fb_size.height = mode->height;
|
||||
}
|
||||
|
||||
options.wayland_display = b->parent.wl_display;
|
||||
options.wayland_surface = output->parent.surface;
|
||||
|
||||
renderer = output->base.compositor->renderer;
|
||||
|
||||
if (renderer->vulkan->output_surface_create(&output->base, &options) < 0)
|
||||
goto cleanup_window;
|
||||
|
||||
return 0;
|
||||
|
||||
cleanup_window:
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
wayland_output_init_pixman_renderer(struct wayland_output *output)
|
||||
{
|
||||
|
|
@ -882,9 +814,6 @@ wayland_output_resize_surface(struct wayland_output *output)
|
|||
struct weston_geometry opa = area;
|
||||
struct wl_region *region;
|
||||
|
||||
assert(b->compositor);
|
||||
assert(b->compositor->renderer);
|
||||
|
||||
if (output->frame) {
|
||||
frame_resize_inside(output->frame, area.width, area.height);
|
||||
frame_interior(output->frame, &area.x, &area.y, NULL, NULL);
|
||||
|
|
@ -920,15 +849,7 @@ wayland_output_resize_surface(struct wayland_output *output)
|
|||
weston_renderer_resize_output(&output->base, &fb_size, &area);
|
||||
|
||||
/* These will need to be re-created due to the resize */
|
||||
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||
} else
|
||||
#endif
|
||||
#ifdef ENABLE_VULKAN
|
||||
if (b->compositor->renderer->type == WESTON_RENDERER_VULKAN) {
|
||||
weston_renderer_resize_output(&output->base, &fb_size, &area);
|
||||
|
||||
/* These will need to be re-created due to the resize */
|
||||
weston_renderer_borders_fini(&output->borders, &output->base);
|
||||
weston_gl_borders_fini(&output->gl.borders, &output->base);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
|
@ -996,6 +917,104 @@ wayland_output_set_fullscreen(struct wayland_output *output,
|
|||
}
|
||||
}
|
||||
|
||||
static struct weston_mode *
|
||||
wayland_output_choose_mode(struct wayland_output *output,
|
||||
struct weston_mode *ref_mode)
|
||||
{
|
||||
struct weston_mode *mode;
|
||||
|
||||
/* First look for an exact match */
|
||||
wl_list_for_each(mode, &output->base.mode_list, link)
|
||||
if (mode->width == ref_mode->width &&
|
||||
mode->height == ref_mode->height &&
|
||||
mode->refresh == ref_mode->refresh)
|
||||
return mode;
|
||||
|
||||
/* If we can't find an exact match, ignore refresh and try again */
|
||||
wl_list_for_each(mode, &output->base.mode_list, link)
|
||||
if (mode->width == ref_mode->width &&
|
||||
mode->height == ref_mode->height)
|
||||
return mode;
|
||||
|
||||
/* Yeah, we failed */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum mode_status {
|
||||
MODE_STATUS_UNKNOWN,
|
||||
MODE_STATUS_SUCCESS,
|
||||
MODE_STATUS_FAIL,
|
||||
MODE_STATUS_CANCEL,
|
||||
};
|
||||
|
||||
static void
|
||||
mode_feedback_successful(void *data,
|
||||
struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
|
||||
{
|
||||
enum mode_status *value = data;
|
||||
|
||||
printf("Mode switch successful\n");
|
||||
|
||||
*value = MODE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
mode_feedback_failed(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
|
||||
{
|
||||
enum mode_status *value = data;
|
||||
|
||||
printf("Mode switch failed\n");
|
||||
|
||||
*value = MODE_STATUS_FAIL;
|
||||
}
|
||||
|
||||
static void
|
||||
mode_feedback_cancelled(void *data, struct zwp_fullscreen_shell_mode_feedback_v1 *fb)
|
||||
{
|
||||
enum mode_status *value = data;
|
||||
|
||||
printf("Mode switch cancelled\n");
|
||||
|
||||
*value = MODE_STATUS_CANCEL;
|
||||
}
|
||||
|
||||
struct zwp_fullscreen_shell_mode_feedback_v1_listener mode_feedback_listener = {
|
||||
mode_feedback_successful,
|
||||
mode_feedback_failed,
|
||||
mode_feedback_cancelled,
|
||||
};
|
||||
|
||||
static enum mode_status
|
||||
wayland_output_fullscreen_shell_mode_feedback(struct wayland_output *output,
|
||||
struct weston_mode *mode)
|
||||
{
|
||||
struct wayland_backend *b = output->backend;
|
||||
struct zwp_fullscreen_shell_mode_feedback_v1 *mode_feedback;
|
||||
enum mode_status mode_status;
|
||||
int ret = 0;
|
||||
|
||||
mode_feedback =
|
||||
zwp_fullscreen_shell_v1_present_surface_for_mode(b->parent.fshell,
|
||||
output->parent.surface,
|
||||
output->parent.output,
|
||||
mode->refresh);
|
||||
|
||||
zwp_fullscreen_shell_mode_feedback_v1_add_listener(mode_feedback,
|
||||
&mode_feedback_listener,
|
||||
&mode_status);
|
||||
|
||||
draw_initial_frame(output);
|
||||
wl_surface_commit(output->parent.surface);
|
||||
|
||||
mode_status = MODE_STATUS_UNKNOWN;
|
||||
while (mode_status == MODE_STATUS_UNKNOWN && ret >= 0)
|
||||
ret = wl_display_dispatch(b->parent.wl_display);
|
||||
|
||||
zwp_fullscreen_shell_mode_feedback_v1_destroy(mode_feedback);
|
||||
|
||||
return mode_status;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_switch_mode_finish(struct wayland_output *output)
|
||||
{
|
||||
|
|
@ -1014,13 +1033,6 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
|
|||
if (wayland_output_init_gl_renderer(output) < 0)
|
||||
return -1;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_VULKAN
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
if (wayland_output_init_vulkan_renderer(output) < 0)
|
||||
return -1;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
unreachable("invalid renderer");
|
||||
|
|
@ -1031,6 +1043,56 @@ wayland_output_switch_mode_finish(struct wayland_output *output)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_switch_mode_fshell(struct wayland_output *output,
|
||||
struct weston_mode *mode)
|
||||
{
|
||||
struct wayland_backend *b;
|
||||
struct wl_surface *old_surface;
|
||||
struct weston_mode *old_mode;
|
||||
enum mode_status mode_status;
|
||||
|
||||
b = output->backend;
|
||||
|
||||
mode = wayland_output_choose_mode(output, mode);
|
||||
if (mode == NULL)
|
||||
return -1;
|
||||
|
||||
if (output->base.current_mode == mode)
|
||||
return 0;
|
||||
|
||||
old_mode = output->base.current_mode;
|
||||
old_surface = output->parent.surface;
|
||||
output->base.current_mode = mode;
|
||||
output->parent.surface =
|
||||
wl_compositor_create_surface(b->parent.compositor);
|
||||
wl_surface_set_user_data(output->parent.surface, output);
|
||||
|
||||
/* Blow the old buffers because we changed size/surfaces */
|
||||
wayland_output_resize_surface(output);
|
||||
|
||||
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, mode);
|
||||
|
||||
/* This should kick-start things again */
|
||||
wayland_output_start_repaint_loop(&output->base);
|
||||
|
||||
if (mode_status == MODE_STATUS_FAIL) {
|
||||
output->base.current_mode = old_mode;
|
||||
wl_surface_destroy(output->parent.surface);
|
||||
output->parent.surface = old_surface;
|
||||
wayland_output_resize_surface(output);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
old_mode->flags &= ~WL_OUTPUT_MODE_CURRENT;
|
||||
output->base.current_mode->flags |= WL_OUTPUT_MODE_CURRENT;
|
||||
|
||||
wl_surface_destroy(old_surface);
|
||||
|
||||
return wayland_output_switch_mode_finish(output);
|
||||
}
|
||||
|
||||
static int
|
||||
wayland_output_switch_mode_xdg(struct wayland_output *output,
|
||||
struct weston_mode *mode)
|
||||
|
|
@ -1074,6 +1136,8 @@ wayland_output_switch_mode(struct weston_output *output_base,
|
|||
|
||||
if (output->parent.xdg_surface)
|
||||
return wayland_output_switch_mode_xdg(output, mode);
|
||||
if (output->backend->parent.fshell)
|
||||
return wayland_output_switch_mode_fshell(output, mode);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1193,6 +1257,7 @@ wayland_output_enable(struct weston_output *base)
|
|||
const struct weston_renderer *renderer = base->compositor->renderer;
|
||||
struct wayland_output *output = to_wayland_output(base);
|
||||
struct wayland_backend *b;
|
||||
enum mode_status mode_status;
|
||||
int ret = 0;
|
||||
|
||||
assert(output);
|
||||
|
|
@ -1228,14 +1293,6 @@ wayland_output_enable(struct weston_output *base)
|
|||
|
||||
output->base.repaint = wayland_output_repaint_gl;
|
||||
break;
|
||||
#endif
|
||||
#ifdef ENABLE_VULKAN
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
if (wayland_output_init_vulkan_renderer(output) < 0)
|
||||
goto err_output;
|
||||
|
||||
output->base.repaint = wayland_output_repaint_vulkan;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
unreachable("invalid renderer");
|
||||
|
|
@ -1247,7 +1304,20 @@ wayland_output_enable(struct weston_output *base)
|
|||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = wayland_output_switch_mode;
|
||||
|
||||
if (b->fullscreen) {
|
||||
if (b->sprawl_across_outputs) {
|
||||
if (b->parent.fshell) {
|
||||
wayland_output_resize_surface(output);
|
||||
|
||||
mode_status = wayland_output_fullscreen_shell_mode_feedback(output, &output->mode);
|
||||
|
||||
if (mode_status == MODE_STATUS_FAIL)
|
||||
zwp_fullscreen_shell_v1_present_surface(b->parent.fshell,
|
||||
output->parent.surface,
|
||||
ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER,
|
||||
output->parent.output);
|
||||
|
||||
}
|
||||
} else if (b->fullscreen) {
|
||||
wayland_output_set_fullscreen(output, 0, NULL);
|
||||
} else {
|
||||
wayland_output_set_windowed(output);
|
||||
|
|
@ -2620,6 +2690,10 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t name,
|
|||
&xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(b->parent.xdg_wm_base,
|
||||
&wm_base_listener, b);
|
||||
} else if (strcmp(interface, "zwp_fullscreen_shell_v1") == 0) {
|
||||
b->parent.fshell =
|
||||
wl_registry_bind(registry, name,
|
||||
&zwp_fullscreen_shell_v1_interface, 1);
|
||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||
display_start_add_seat(b, name, version);
|
||||
} else if (strcmp(interface, "wl_output") == 0) {
|
||||
|
|
@ -2717,12 +2791,18 @@ wayland_destroy(struct weston_backend *backend)
|
|||
if (b->parent.xdg_wm_base)
|
||||
xdg_wm_base_destroy(b->parent.xdg_wm_base);
|
||||
|
||||
if (b->parent.fshell)
|
||||
zwp_fullscreen_shell_v1_release(b->parent.fshell);
|
||||
|
||||
if (b->parent.compositor)
|
||||
wl_compositor_destroy(b->parent.compositor);
|
||||
|
||||
if (b->theme)
|
||||
theme_destroy(b->theme);
|
||||
|
||||
if (b->frame_device)
|
||||
cairo_device_destroy(b->frame_device);
|
||||
|
||||
wl_cursor_theme_destroy(b->cursor_theme);
|
||||
|
||||
free(b->formats);
|
||||
|
|
@ -2871,22 +2951,6 @@ wayland_backend_create(struct weston_compositor *compositor,
|
|||
goto err_display;
|
||||
}
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_display_options options = {
|
||||
.formats = b->formats,
|
||||
.formats_count = b->formats_count,
|
||||
};
|
||||
|
||||
if (weston_compositor_init_renderer(compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base) < 0) {
|
||||
weston_log("Failed to initialize the Vulkan renderer\n");
|
||||
goto err_display;
|
||||
}
|
||||
/* For now Vulkan does not fall back to anything automatically,
|
||||
* like GL renderer does. */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
weston_log("Unsupported renderer requested\n");
|
||||
goto err_display;
|
||||
|
|
@ -2926,6 +2990,8 @@ wayland_backend_destroy(struct wayland_backend *b)
|
|||
|
||||
if (b->theme)
|
||||
theme_destroy(b->theme);
|
||||
if (b->frame_device)
|
||||
cairo_device_destroy(b->frame_device);
|
||||
wl_cursor_theme_destroy(b->cursor_theme);
|
||||
|
||||
wl_list_remove(&b->base.link);
|
||||
|
|
@ -2973,7 +3039,7 @@ weston_backend_init(struct weston_compositor *compositor,
|
|||
if (!b)
|
||||
return -1;
|
||||
|
||||
if (new_config.sprawl) {
|
||||
if (new_config.sprawl || b->parent.fshell) {
|
||||
b->sprawl_across_outputs = true;
|
||||
wl_display_roundtrip(b->parent.wl_display);
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@
|
|||
#include "shared/timespec-util.h"
|
||||
#include "shared/file-util.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "shared/xalloc.h"
|
||||
|
|
@ -141,7 +140,7 @@ struct x11_output {
|
|||
|
||||
xcb_gc_t gc;
|
||||
xcb_shm_seg_t segment;
|
||||
weston_renderbuffer_t renderbuffer;
|
||||
struct weston_renderbuffer *renderbuffer;
|
||||
int shm_id;
|
||||
void *buf;
|
||||
uint8_t depth;
|
||||
|
|
@ -169,10 +168,6 @@ to_x11_head(struct weston_head *base)
|
|||
static void
|
||||
x11_output_destroy(struct weston_output *base);
|
||||
|
||||
static int
|
||||
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||
const struct pixel_format_info *pfmt);
|
||||
|
||||
static inline struct x11_output *
|
||||
to_x11_output(struct weston_output *base)
|
||||
{
|
||||
|
|
@ -456,29 +451,6 @@ x11_output_repaint_gl(struct weston_output *output_base)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
x11_output_repaint_vulkan(struct weston_output *output_base)
|
||||
{
|
||||
struct x11_output *output = to_x11_output(output_base);
|
||||
struct weston_compositor *ec;
|
||||
pixman_region32_t damage;
|
||||
|
||||
assert(output);
|
||||
|
||||
ec = output->base.compositor;
|
||||
|
||||
pixman_region32_init(&damage);
|
||||
|
||||
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||
|
||||
ec->renderer->repaint_output(output_base, &damage, NULL);
|
||||
|
||||
pixman_region32_fini(&damage);
|
||||
|
||||
weston_output_arm_frame_timer(output_base, output->finish_frame_timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region)
|
||||
{
|
||||
|
|
@ -535,6 +507,8 @@ static int
|
|||
x11_output_repaint_shm(struct weston_output *output_base)
|
||||
{
|
||||
struct x11_output *output = to_x11_output(output_base);
|
||||
const struct weston_renderer *renderer;
|
||||
pixman_image_t *image;
|
||||
struct weston_compositor *ec;
|
||||
struct x11_backend *b;
|
||||
xcb_void_cookie_t cookie;
|
||||
|
|
@ -544,8 +518,11 @@ x11_output_repaint_shm(struct weston_output *output_base)
|
|||
assert(output);
|
||||
|
||||
ec = output->base.compositor;
|
||||
renderer = ec->renderer;
|
||||
b = output->backend;
|
||||
|
||||
image = renderer->pixman->renderbuffer_get_image(output->renderbuffer);
|
||||
|
||||
pixman_region32_init(&damage);
|
||||
|
||||
weston_output_flush_damage_for_primary_plane(output_base, &damage);
|
||||
|
|
@ -557,13 +534,13 @@ x11_output_repaint_shm(struct weston_output *output_base)
|
|||
pixman_region32_fini(&damage);
|
||||
|
||||
cookie = xcb_shm_put_image_checked(b->conn, output->window, output->gc,
|
||||
output_base->current_mode->width,
|
||||
output_base->current_mode->height,
|
||||
0, 0,
|
||||
output_base->current_mode->width,
|
||||
output_base->current_mode->height,
|
||||
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
0, output->segment, 0);
|
||||
pixman_image_get_width(image),
|
||||
pixman_image_get_height(image),
|
||||
0, 0,
|
||||
pixman_image_get_width(image),
|
||||
pixman_image_get_height(image),
|
||||
0, 0, output->depth, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
0, output->segment, 0);
|
||||
err = xcb_request_check(b->conn, cookie);
|
||||
if (err != NULL) {
|
||||
weston_log("Failed to put shm image, err: %d\n", err->error_code);
|
||||
|
|
@ -591,7 +568,7 @@ x11_output_deinit_shm(struct x11_backend *b, struct x11_output *output)
|
|||
xcb_generic_error_t *err;
|
||||
xcb_free_gc(b->conn, output->gc);
|
||||
|
||||
b->compositor->renderer->destroy_renderbuffer(output->renderbuffer);
|
||||
weston_renderbuffer_unref(output->renderbuffer);
|
||||
output->renderbuffer = NULL;
|
||||
cookie = xcb_shm_detach_checked(b->conn, output->segment);
|
||||
err = xcb_request_check(b->conn, cookie);
|
||||
|
|
@ -816,40 +793,17 @@ x11_output_get_shm_pixel_format(struct x11_output *output)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
x11_rb_discarded_cb(weston_renderbuffer_t rb, void *data)
|
||||
{
|
||||
struct x11_output *output = (struct x11_output *) data;
|
||||
const struct pixel_format_info *pfmt;
|
||||
|
||||
if (output->base.compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
|
||||
x11_output_deinit_shm(output->backend, output);
|
||||
pfmt = x11_output_get_shm_pixel_format(output);
|
||||
if (!pfmt)
|
||||
return false;
|
||||
if (x11_output_init_shm(output->backend, output, pfmt) < 0) {
|
||||
weston_log("Failed to initialize SHM for the X11 output\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
||||
const struct pixel_format_info *pfmt)
|
||||
const struct pixel_format_info *pfmt, int width, int height)
|
||||
{
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
int bitsperpixel = pfmt->bpp;
|
||||
size_t size = output->base.current_mode->width *
|
||||
output->base.current_mode->height * (bitsperpixel / 8);
|
||||
int stride = output->base.current_mode->width * (bitsperpixel / 8);
|
||||
xcb_void_cookie_t cookie;
|
||||
xcb_generic_error_t *err;
|
||||
|
||||
/* Create SHM segment and attach it */
|
||||
output->shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | S_IRWXU);
|
||||
output->shm_id = shmget(IPC_PRIVATE, width * height * (bitsperpixel / 8), IPC_CREAT | S_IRWXU);
|
||||
if (output->shm_id == -1) {
|
||||
weston_log("x11shm: failed to allocate SHM segment\n");
|
||||
return -1;
|
||||
|
|
@ -873,9 +827,10 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
|||
|
||||
/* Now create pixman image */
|
||||
output->renderbuffer =
|
||||
renderer->create_renderbuffer(&output->base, pfmt, output->buf,
|
||||
stride, x11_rb_discarded_cb,
|
||||
output);
|
||||
renderer->pixman->create_image_from_ptr(&output->base,
|
||||
pfmt, width, height,
|
||||
output->buf,
|
||||
width * (bitsperpixel / 8));
|
||||
|
||||
output->gc = xcb_generate_id(b->conn);
|
||||
xcb_create_gc(b->conn, output->gc, output->window, 0, NULL);
|
||||
|
|
@ -883,19 +838,6 @@ x11_output_init_shm(struct x11_backend *b, struct x11_output *output,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
x11_set_dpms(struct weston_output *base, enum dpms_enum level)
|
||||
{
|
||||
struct x11_output *output = to_x11_output(base);
|
||||
|
||||
if (level == WESTON_DPMS_ON)
|
||||
weston_output_schedule_repaint(base);
|
||||
else if (output->base.repaint_status == REPAINT_AWAITING_COMPLETION) {
|
||||
wl_event_source_timer_update(output->finish_frame_timer, 0);
|
||||
weston_output_schedule_repaint_reset(base);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
||||
{
|
||||
|
|
@ -933,8 +875,20 @@ x11_output_switch_mode(struct weston_output *base, struct weston_mode *mode)
|
|||
fb_size.width = output->mode.width = mode->width;
|
||||
fb_size.height = output->mode.height = mode->height;
|
||||
|
||||
if (!weston_renderer_resize_output(&output->base, &fb_size, NULL))
|
||||
return -1;
|
||||
weston_renderer_resize_output(&output->base, &fb_size, NULL);
|
||||
|
||||
if (base->compositor->renderer->type == WESTON_RENDERER_PIXMAN) {
|
||||
const struct pixel_format_info *pfmt;
|
||||
x11_output_deinit_shm(b, output);
|
||||
pfmt = x11_output_get_shm_pixel_format(output);
|
||||
if (!pfmt)
|
||||
return -1;
|
||||
if (x11_output_init_shm(b, output, pfmt,
|
||||
fb_size.width, fb_size.height) < 0) {
|
||||
weston_log("Failed to initialize SHM for the X11 output\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
output->resize_pending = false;
|
||||
output->window_resized = false;
|
||||
|
|
@ -966,9 +920,6 @@ x11_output_disable(struct weston_output *base)
|
|||
case WESTON_RENDERER_GL:
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
break;
|
||||
case WESTON_RENDERER_VULKAN:
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
break;
|
||||
default:
|
||||
unreachable("invalid renderer");
|
||||
}
|
||||
|
|
@ -1117,7 +1068,8 @@ x11_output_enable(struct weston_output *base)
|
|||
weston_log("Failed to create pixman renderer for output\n");
|
||||
goto err;
|
||||
}
|
||||
if (x11_output_init_shm(b, output, options.format) < 0) {
|
||||
if (x11_output_init_shm(b, output, options.format,
|
||||
mode->width, mode->height) < 0) {
|
||||
weston_log("Failed to initialize SHM for the X11 output\n");
|
||||
renderer->pixman->output_destroy(&output->base);
|
||||
goto err;
|
||||
|
|
@ -1150,29 +1102,6 @@ x11_output_enable(struct weston_output *base)
|
|||
output->base.repaint = x11_output_repaint_gl;
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
struct vulkan_renderer_surface_options options = {
|
||||
.formats = b->formats,
|
||||
.formats_count = b->formats_count,
|
||||
.area.x = 0,
|
||||
.area.y = 0,
|
||||
.area.width = mode->width,
|
||||
.area.height = mode->height,
|
||||
.fb_size.width = mode->width,
|
||||
.fb_size.height = mode->height,
|
||||
};
|
||||
|
||||
options.xcb_connection = b->conn;
|
||||
options.xcb_visualid = screen->root_visual;
|
||||
options.xcb_window = output->window;
|
||||
|
||||
ret = renderer->vulkan->output_surface_create(base, &options);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
output->base.repaint = x11_output_repaint_vulkan;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unreachable("invalid renderer");
|
||||
}
|
||||
|
|
@ -1180,7 +1109,7 @@ x11_output_enable(struct weston_output *base)
|
|||
output->base.start_repaint_loop = x11_output_start_repaint_loop;
|
||||
output->base.assign_planes = NULL;
|
||||
output->base.set_backlight = NULL;
|
||||
output->base.set_dpms = x11_set_dpms;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = x11_output_switch_mode;
|
||||
|
||||
loop = wl_display_get_event_loop(b->compositor->wl_display);
|
||||
|
|
@ -2023,17 +1952,6 @@ x11_backend_create(struct weston_compositor *compositor,
|
|||
goto err_xdisplay;
|
||||
break;
|
||||
}
|
||||
case WESTON_RENDERER_VULKAN: {
|
||||
const struct vulkan_renderer_display_options options = {
|
||||
.formats = b->formats,
|
||||
.formats_count = b->formats_count,
|
||||
};
|
||||
if (weston_compositor_init_renderer(compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base) < 0)
|
||||
goto err_xdisplay;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
weston_log("Unsupported renderer requested\n");
|
||||
goto err_xdisplay;
|
||||
|
|
|
|||
|
|
@ -144,29 +144,29 @@ weston_head_init(struct weston_head *head, const char *name);
|
|||
void
|
||||
weston_head_release(struct weston_head *head);
|
||||
|
||||
bool
|
||||
void
|
||||
weston_head_set_connection_status(struct weston_head *head, bool connected);
|
||||
|
||||
void
|
||||
weston_head_set_internal(struct weston_head *head);
|
||||
|
||||
bool
|
||||
void
|
||||
weston_head_set_monitor_strings(struct weston_head *head,
|
||||
const char *make,
|
||||
const char *model,
|
||||
const char *serialno);
|
||||
bool
|
||||
void
|
||||
weston_head_set_non_desktop(struct weston_head *head, bool non_desktop);
|
||||
|
||||
bool
|
||||
void
|
||||
weston_head_set_physical_size(struct weston_head *head,
|
||||
int32_t mm_width, int32_t mm_height);
|
||||
|
||||
bool
|
||||
void
|
||||
weston_head_set_subpixel(struct weston_head *head,
|
||||
enum wl_output_subpixel sp);
|
||||
|
||||
bool
|
||||
void
|
||||
weston_head_set_transform(struct weston_head *head, uint32_t transform);
|
||||
|
||||
void
|
||||
|
|
@ -177,9 +177,6 @@ void
|
|||
weston_head_set_supported_colorimetry_mask(struct weston_head *head,
|
||||
uint32_t colorimetry_mask);
|
||||
|
||||
void
|
||||
weston_head_set_supported_vrr_modes_mask(struct weston_head *head,
|
||||
uint32_t vrr_modes_mask);
|
||||
/* weston_output */
|
||||
|
||||
void
|
||||
|
|
@ -343,7 +340,7 @@ void
|
|||
notify_tablet_tool_frame(struct weston_tablet_tool *tool,
|
||||
const struct timespec *time);
|
||||
|
||||
void
|
||||
bool
|
||||
weston_output_flush_damage_for_plane(struct weston_output *output,
|
||||
struct weston_plane *plane,
|
||||
pixman_region32_t *damage);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue