mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-09 18:48:08 +02:00
Compare commits
39 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3038814ed | ||
|
|
8f12365f13 | ||
|
|
4c2bbc5180 | ||
|
|
e4323dc7c9 | ||
|
|
641ac3ef82 | ||
|
|
65c7cc45b3 | ||
|
|
60963b795c | ||
|
|
d1f9bd3d09 | ||
|
|
5ea838be63 | ||
|
|
1a9149cc06 | ||
|
|
0b5c47edca | ||
|
|
6445af1ead | ||
|
|
8f1a089917 | ||
|
|
015b3b4d4c | ||
|
|
51dfd1be3a | ||
|
|
ef25333fac | ||
|
|
cb8bb2763a | ||
|
|
3b340a2f9e | ||
|
|
f87d119e56 | ||
|
|
1cb63e1f83 | ||
|
|
23f254c690 | ||
|
|
11f20fa8e4 | ||
|
|
9eb44254a7 | ||
|
|
8eb0ff8a19 | ||
|
|
af871d82ef | ||
|
|
ee92a531da | ||
|
|
353600b6fc | ||
|
|
a712e803d2 | ||
|
|
d70f91d3f1 | ||
|
|
26e03f3891 | ||
|
|
61f2248de2 | ||
|
|
7eaba52a22 | ||
|
|
502e4bd31d | ||
|
|
e056153bf4 | ||
|
|
6d015b4759 | ||
|
|
ca3c5b8015 | ||
|
|
1e667cf0c3 | ||
|
|
efd6789934 | ||
|
|
32f5596178 |
379 changed files with 24914 additions and 57853 deletions
215
.gitlab-ci.yml
215
.gitlab-ci.yml
|
|
@ -1,6 +1,6 @@
|
|||
# vim: set expandtab shiftwidth=2 tabstop=8 textwidth=0:
|
||||
|
||||
.templates_sha: &template_sha 32afe5644697e503af18a736587c8619fa036a72 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||
.templates_sha: &template_sha 184ca628f89f3193c249b4e34e45afee2773a833 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
|
||||
# This file uses the freedesktop ci-templates to build Weston and run our
|
||||
# tests in CI.
|
||||
#
|
||||
|
|
@ -43,7 +43,7 @@
|
|||
variables:
|
||||
FDO_UPSTREAM_REPO: wayland/weston
|
||||
FDO_REPO_SUFFIX: "$BUILD_OS-$FDO_DISTRIBUTION_VERSION/$BUILD_ARCH"
|
||||
FDO_DISTRIBUTION_TAG: '2026-04-01-mesa-26.0.4'
|
||||
FDO_DISTRIBUTION_TAG: '2024-08-14-00-freerdp3.x'
|
||||
|
||||
|
||||
include:
|
||||
|
|
@ -66,11 +66,6 @@ include:
|
|||
# we need a default case though, so all the rest still run
|
||||
- when: on_success
|
||||
|
||||
default:
|
||||
retry:
|
||||
max: 2
|
||||
when: runner_system_failure
|
||||
|
||||
.merge-rules:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||
|
|
@ -84,7 +79,7 @@ stages:
|
|||
- "Pre Base container"
|
||||
- "Base container"
|
||||
- "Full build and test"
|
||||
- "No-GL/Vulkan build and test"
|
||||
- "No-GL build and test"
|
||||
- "Other builds"
|
||||
- pages
|
||||
|
||||
|
|
@ -93,23 +88,20 @@ stages:
|
|||
.os-debian-lts:
|
||||
variables:
|
||||
BUILD_OS: debian
|
||||
LLVM_VERSION: 15
|
||||
USE_DEBIAN_BACKPORTS: y
|
||||
PACKAGES_SPECIFIC: vulkan-validationlayers-dev
|
||||
LLVM_VERSION: 11
|
||||
FREERDP_VERSION: 2
|
||||
FDO_DISTRIBUTION_VERSION: bookworm
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
||||
FDO_DISTRIBUTION_VERSION: bullseye
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
|
||||
|
||||
.os-debian:
|
||||
variables:
|
||||
BUILD_OS: debian
|
||||
LLVM_VERSION: 19
|
||||
LLVM_VERSION: 15
|
||||
FREERDP_VERSION: 3
|
||||
USE_DEBIAN_BACKPORTS: y
|
||||
PACKAGES_SPECIFIC: vulkan-utility-libraries-dev libpolly-19-dev libclang-rt-19-dev python3-standard-imghdr
|
||||
# If you upgrade from trixie, see the use_tls=0 notes in tests/meson.build.
|
||||
FDO_DISTRIBUTION_VERSION: trixie
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} PACKAGES_SPECIFIC="${PACKAGES_SPECIFIC}" bash .gitlab-ci/debian-install.sh'
|
||||
USE_BOOKWORM_BACKPORTS: y
|
||||
# If you upgrade from bookworm, see the use_tls=0 notes in tests/meson.build.
|
||||
FDO_DISTRIBUTION_VERSION: bookworm
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} BUILD_ARCH=${BUILD_ARCH} KERNEL_IMAGE=${KERNEL_IMAGE} KERNEL_DEFCONFIG=${KERNEL_DEFCONFIG} LLVM_VERSION=${LLVM_VERSION} FDO_DISTRIBUTION_VERSION=${FDO_DISTRIBUTION_VERSION} bash .gitlab-ci/debian-install.sh'
|
||||
|
||||
# Does not inherit .default-rules as we only want it to run in MR context.
|
||||
check-commit:
|
||||
|
|
@ -119,6 +111,7 @@ check-commit:
|
|||
stage: "Merge request checks"
|
||||
script:
|
||||
- ci-fairy check-commits --signed-off-by --junit-xml=results.xml
|
||||
- ci-fairy check-merge-request --require-allow-collaboration --junit-xml=results.xml
|
||||
variables:
|
||||
GIT_DEPTH: 100
|
||||
artifacts:
|
||||
|
|
@ -146,14 +139,12 @@ check-commit:
|
|||
- .os-debian-lts
|
||||
variables:
|
||||
BUILD_ARCH: "armv7"
|
||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||
|
||||
.debian-armv7:
|
||||
extends:
|
||||
- .os-debian
|
||||
variables:
|
||||
BUILD_ARCH: "armv7"
|
||||
FDO_DISTRIBUTION_PLATFORM: "linux/arm/v7"
|
||||
# Armv7 doesn't have freerdp3 in bookworm-backports so we don't build FreeRDP
|
||||
MESON_DIST_OPTIONS: "-Dbackend-rdp=false"
|
||||
# Inhibit installation of freerdp-dev
|
||||
|
|
@ -220,6 +211,8 @@ armv7-debian-lts-container_prep:
|
|||
- .fdo.container-build@debian
|
||||
tags:
|
||||
- aarch64
|
||||
variables:
|
||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
||||
needs:
|
||||
- job: base-container-pre
|
||||
timeout: 30m
|
||||
|
|
@ -232,6 +225,8 @@ armv7-debian-container_prep:
|
|||
- .fdo.container-build@debian
|
||||
tags:
|
||||
- aarch64
|
||||
variables:
|
||||
FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
|
||||
needs:
|
||||
- job: base-container-pre
|
||||
timeout: 30m
|
||||
|
|
@ -267,23 +262,17 @@ aarch64-debian-container_prep:
|
|||
timeout: 15m
|
||||
variables:
|
||||
BUILDDIR: $CI_PROJECT_DIR/build-weston-$CI_JOB_NAME
|
||||
BUILDDIR_WESTINY: $CI_PROJECT_DIR/build-westiny-$CI_JOB_NAME
|
||||
PREFIX: $CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
||||
PREFIX_WESTINY: $CI_PROJECT_DIR/prefix-westiny-$CI_JOB_NAME
|
||||
before_script:
|
||||
- export PATH=~/.local/bin:$PATH
|
||||
- export XDG_RUNTIME_DIR="$(mktemp -p $(pwd) -d xdg-runtime-XXXXXX)"
|
||||
- export TESTS_RES_PATH="$BUILDDIR/tests-res.txt"
|
||||
- export VK_INSTANCE_LAYERS=VK_LAYER_KHRONOS_validation
|
||||
- mkdir "$BUILDDIR" "$PREFIX"
|
||||
- mkdir "$BUILDDIR_WESTINY" "$PREFIX_WESTINY"
|
||||
|
||||
.build-with-clang:
|
||||
variables:
|
||||
CC: clang-$LLVM_VERSION
|
||||
CC_LD: lld-$LLVM_VERSION
|
||||
CXX: clang++-$LLVM_VERSION
|
||||
CXX_LD: lld-$LLVM_VERSION
|
||||
MESON_TOOLCHAIN_OPTIONS: "$MESON_OPTIONS -Db_lundef=false" # clang+ASan+undef=boom
|
||||
|
||||
# Extends the core build templates to also provide for running our testing. We
|
||||
|
|
@ -292,12 +281,18 @@ aarch64-debian-container_prep:
|
|||
.build-and-test:
|
||||
extends:
|
||||
- .default-rules
|
||||
variables:
|
||||
SANITIZE: "-Db_sanitize=address"
|
||||
script:
|
||||
- "${CI_PROJECT_DIR}/.gitlab-ci/build.sh"
|
||||
- "${CI_PROJECT_DIR}/.gitlab-ci/test.sh"
|
||||
|
||||
- cd "$BUILDDIR"
|
||||
- meson --prefix="$PREFIX" --wrap-mode=nofallback -Db_sanitize=address ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
- ninja install
|
||||
- test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
||||
- virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
||||
- TEST_RES=$(cat $TESTS_RES_PATH)
|
||||
- rm $TESTS_RES_PATH
|
||||
- cp -R /weston-virtme ./
|
||||
- rm weston-virtme/${KERNEL_IMAGE}
|
||||
- exit $TEST_RES
|
||||
artifacts:
|
||||
name: weston-$CI_COMMIT_SHA
|
||||
when: always
|
||||
|
|
@ -308,14 +303,18 @@ aarch64-debian-container_prep:
|
|||
- $BUILDDIR/weston-virtme
|
||||
- $PREFIX
|
||||
reports:
|
||||
junit: $BUILDDIR/meson-logs/testlog.junit.xml
|
||||
junit: $BUILDDIR/meson-logs/testlog-junit.xml
|
||||
|
||||
# Same as above, but without running any tests.
|
||||
.build-no-test:
|
||||
extends:
|
||||
- .default-rules
|
||||
script:
|
||||
- "${CI_PROJECT_DIR}/.gitlab-ci/build.sh"
|
||||
- cd "$BUILDDIR"
|
||||
- meson --prefix="$PREFIX" --wrap-mode=nofallback ${MESON_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||
- ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
- ninja install
|
||||
- ninja clean
|
||||
artifacts:
|
||||
name: weston-$CI_COMMIT_SHA
|
||||
when: always
|
||||
|
|
@ -426,81 +425,67 @@ aarch64-debian-container_prep:
|
|||
- job: aarch64-debian-container_prep
|
||||
artifacts: false
|
||||
|
||||
# Full build (gcov + perfetto) used for testing under KVM.
|
||||
# Full build, used for testing under KVM.
|
||||
.build-options-full:
|
||||
stage: "Full build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Doptimization=0
|
||||
-Db_coverage=true
|
||||
--force-fallback-for=perfetto
|
||||
-Dperfetto=true
|
||||
-Dperfetto:werror=false
|
||||
-Dwerror=true
|
||||
-Dtest-skip-is-failure=true
|
||||
-Ddeprecated-remoting=true
|
||||
-Ddeprecated-pipewire=true
|
||||
after_script:
|
||||
- ninja -C "$BUILDDIR" coverage-html > "$BUILDDIR/meson-logs/ninja-coverage-html.txt"
|
||||
- ninja -C "$BUILDDIR" coverage-xml
|
||||
|
||||
# Full build, (without gcov and perfetto)
|
||||
.build-options-full-v2:
|
||||
stage: "Full build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Doptimization=0
|
||||
-Dwerror=true
|
||||
-Dtest-skip-is-failure=true
|
||||
|
||||
x86_64-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-x86_64
|
||||
- .build-options-full
|
||||
|
||||
x86_64-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-full
|
||||
artifacts:
|
||||
reports:
|
||||
coverage_report:
|
||||
coverage_format: cobertura
|
||||
path: $BUILDDIR/meson-logs/coverage.xml
|
||||
|
||||
x86_64-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-full-v2
|
||||
|
||||
aarch64-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
aarch64-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
x86_64-clang-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-x86_64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
x86_64-clang-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
aarch64-clang-debian-lts-full-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
aarch64-clang-debian-full-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-with-clang
|
||||
- .build-options-full-v2
|
||||
- .build-options-full
|
||||
|
||||
# Docs should be invariant on all architectures, so we only do it on Debian
|
||||
# x86-64.
|
||||
|
|
@ -514,88 +499,62 @@ docs-build:
|
|||
- .build-env-debian-x86_64
|
||||
- .build-no-test
|
||||
|
||||
# Building without gl-renderer and/or vulkan-renderer, to make sure this keeps working.
|
||||
.build-options-no-gl-no-vulkan:
|
||||
stage: "No-GL/Vulkan build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||
-Drenderer-gl=false
|
||||
-Drenderer-vulkan=false
|
||||
-Dwerror=true
|
||||
|
||||
# Building without gl-renderer, to make sure this keeps working.
|
||||
.build-options-no-gl:
|
||||
stage: "No-GL/Vulkan build and test"
|
||||
stage: "No-GL build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||
-Drenderer-gl=false
|
||||
-Dremoting=false
|
||||
-Dpipewire=false
|
||||
-Dwerror=true
|
||||
|
||||
.build-options-no-vulkan:
|
||||
stage: "No-GL/Vulkan build and test"
|
||||
variables:
|
||||
MESON_OPTIONS: >
|
||||
-Dsimple-clients=damage,im,shm,touch,dmabuf-v4l
|
||||
-Drenderer-vulkan=false
|
||||
-Dwerror=true
|
||||
|
||||
x86_64-debian-lts-no-gl-no-vulkan-build:
|
||||
x86_64-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-x86_64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
x86_64-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-debian-lts-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-clang-debian-lts-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
armv7-clang-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
aarch64-debian-lts-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
|
||||
aarch64-debian-no-gl-no-vulkan-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-options-no-gl-no-vulkan
|
||||
- .build-options-no-gl
|
||||
|
||||
x86_64-debian-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-no-gl
|
||||
|
||||
x86_64-debian-no-vulkan-build:
|
||||
armv7-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-x86_64
|
||||
- .build-options-no-vulkan
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
armv7-debian-no-gl-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
armv7-clang-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .build-env-debian-lts-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
armv7-clang-debian-no-gl-build:
|
||||
extends:
|
||||
- .build-env-debian-armv7
|
||||
- .build-with-clang
|
||||
- .build-no-test
|
||||
- .build-options-no-gl
|
||||
|
||||
aarch64-debian-lts-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-lts-aarch64
|
||||
- .build-options-no-gl
|
||||
|
||||
aarch64-debian-no-gl-build:
|
||||
extends:
|
||||
- .test-env-debian-aarch64
|
||||
- .build-options-no-gl
|
||||
|
||||
# Expose docs and coverage reports, so we can show users any changes to these
|
||||
# inside their merge requests, letting us check them before merge.
|
||||
|
|
@ -607,18 +566,18 @@ x86_64-debian-no-vulkan-build:
|
|||
docs-and-coverage:
|
||||
extends:
|
||||
- .default-rules
|
||||
- .debian-lts-x86_64
|
||||
- .debian-x86_64
|
||||
- .fdo.suffixed-image@debian
|
||||
stage: pages
|
||||
needs:
|
||||
- job: docs-build
|
||||
artifacts: true
|
||||
- job: x86_64-debian-lts-full-build
|
||||
- job: x86_64-debian-full-build
|
||||
artifacts: true
|
||||
timeout: 5m
|
||||
script:
|
||||
- mv prefix-weston-docs-build/share/doc/weston Documentation
|
||||
- mv build-weston-x86_64-debian-lts-full-build/meson-logs/coveragereport Test_Coverage
|
||||
- mv build-weston-x86_64-debian-full-build/meson-logs/coveragereport Test_Coverage
|
||||
- rm Test_Coverage/gcov.css
|
||||
- cp doc/style/lcov-style.css Test_Coverage/gcov.css
|
||||
- cp doc/style/*.png Test_Coverage/
|
||||
|
|
|
|||
|
|
@ -4,8 +4,6 @@
|
|||
# .gitlab-ci.yml for more information. This script is called from an
|
||||
# OS-specific build scripts like debian-install.sh.
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
set -o xtrace -o errexit
|
||||
|
||||
# Set concurrency to an appropriate level for our shared runners, falling back
|
||||
|
|
@ -27,8 +25,7 @@ esac
|
|||
|
||||
# Build and install Meson. Generally we want to keep this in sync with what
|
||||
# we require inside meson.build.
|
||||
fdo_log_section_start_collapsed install_meson "install_meson"
|
||||
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.4.2
|
||||
pip3 install $PIP_ARGS git+https://github.com/mesonbuild/meson.git@1.0.0
|
||||
export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
# Our docs are built using Sphinx (top-level organisation and final HTML/CSS
|
||||
|
|
@ -44,22 +41,31 @@ pip3 install $PIP_ARGS sphinxcontrib-qthelp==1.0.3
|
|||
pip3 install $PIP_ARGS sphinxcontrib-serializinghtml==1.1.5
|
||||
pip3 install $PIP_ARGS breathe==4.31.0
|
||||
pip3 install $PIP_ARGS sphinx_rtd_theme==1.0.0
|
||||
fdo_log_section_end install_meson
|
||||
|
||||
|
||||
# Build a Linux kernel for use in testing. We enable the VKMS module so we can
|
||||
# predictably test the DRM backend in the absence of real hardware. We lock the
|
||||
# version here so we see predictable results.
|
||||
#
|
||||
# To run this we use virtme-ng, a QEMU wrapper. It is a fork from virtme, whose
|
||||
# development stalled.
|
||||
# To run this we use virtme, a QEMU wrapper: https://github.com/amluto/virtme
|
||||
#
|
||||
# virtme-ng makes our lives easier by abstracting handling of the console,
|
||||
# virtme makes our lives easier by abstracting handling of the console,
|
||||
# filesystem, etc, so we can pretend that the VM we execute in is actually
|
||||
# just a regular container.
|
||||
fdo_log_section_start_collapsed install_kernel "install_kernel"
|
||||
#
|
||||
# The reason why we are using a fork here is that it adds a patch to have the
|
||||
# --script-dir command line option. With that we can run scripts that are in a
|
||||
# certain folder when virtme starts, which is necessary in our use case.
|
||||
#
|
||||
# The upstream also has some commands that could help us to reach the same
|
||||
# results: --script-sh and --script-exec. Unfornutately they are not completely
|
||||
# implemented yet, so we had some trouble to use them and it was becoming
|
||||
# hackery.
|
||||
#
|
||||
# The fork pulls in this support from the original GitHub PR, rebased on top of
|
||||
# a newer upstream version which fixes AArch64 support.
|
||||
if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
||||
git clone --depth=1 --branch drm-misc-next-2026-03-20 https://gitlab.freedesktop.org/drm/misc/kernel.git linux
|
||||
# 6.3 is (still) used as >= 6.5 drm-writeback test will timeout
|
||||
git clone --depth=1 --branch=v6.3 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
|
||||
cd linux
|
||||
|
||||
if [[ "${BUILD_ARCH}" = "x86-64" ]]; then
|
||||
|
|
@ -85,8 +91,9 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
|||
./scripts/config \
|
||||
--enable CONFIG_DRM \
|
||||
--enable CONFIG_DRM_KMS_HELPER \
|
||||
--enable CONFIG_DRM_KMS_FB_HELPER \
|
||||
--enable CONFIG_DRM_VKMS \
|
||||
--enable CONFIG_UDMABUF
|
||||
--enable CONFIG_DRM_VGEM
|
||||
make ARCH=${LINUX_ARCH} oldconfig
|
||||
make ARCH=${LINUX_ARCH}
|
||||
|
||||
|
|
@ -101,15 +108,14 @@ if [[ -n "$KERNEL_DEFCONFIG" ]]; then
|
|||
./setup.py install
|
||||
cd ..
|
||||
fi
|
||||
fdo_log_section_end install_kernel
|
||||
|
||||
# Build and install Wayland; keep this version in sync with our dependency
|
||||
# in meson.build.
|
||||
fdo_log_section_start_collapsed install_wayland "install_wayland"
|
||||
git clone --branch 1.22.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
|
||||
cd wayland
|
||||
git show -s HEAD
|
||||
meson setup build --wrap-mode=nofallback -Ddocumentation=false
|
||||
mkdir build
|
||||
meson build --wrap-mode=nofallback -Ddocumentation=false
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf wayland
|
||||
|
|
@ -117,39 +123,24 @@ rm -rf wayland
|
|||
# Keep this version in sync with our dependency in meson.build. If you wish to
|
||||
# raise a MR against custom protocol, please change this reference to clone
|
||||
# your relevant tree, and make sure you bump $FDO_DISTRIBUTION_TAG.
|
||||
git clone --branch 1.46 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||
git clone --branch 1.33 --depth=1 https://gitlab.freedesktop.org/wayland/wayland-protocols
|
||||
cd wayland-protocols
|
||||
git show -s HEAD
|
||||
meson setup build --wrap-mode=nofallback -Dtests=false
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf wayland-protocols
|
||||
fdo_log_section_end install_wayland
|
||||
|
||||
# Build and install our own version of libdrm. Debian 11 (bullseye) provides
|
||||
# libdrm 2.4.104 which doesn't have the IN_FORMATS iterator api, and Mesa
|
||||
# depends on 2.4.109 as well.
|
||||
# Bump to 2.4.118 to include DRM_FORMAT_NV{15,20,30}
|
||||
fdo_log_section_start_collapsed install_libdrm "install_libdrm"
|
||||
git clone --branch libdrm-2.4.118 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
||||
git clone --branch libdrm-2.4.109 --depth=1 https://gitlab.freedesktop.org/mesa/drm.git
|
||||
cd drm
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dvc4=disabled -Dfreedreno=disabled -Detnaviv=disabled
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dvc4=false -Dfreedreno=false -Detnaviv=false
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf drm
|
||||
fdo_log_section_end install_libdrm
|
||||
|
||||
# Build and install Vulkan-Headers with a defined version, mostly because
|
||||
# the version in Debian 11 (bullseye) is too old to build vulkan-renderer.
|
||||
fdo_log_section_start_collapsed install_vulkan_headers "install_vulkan_headers"
|
||||
git clone --branch sdk-1.3.239.0 --depth=1 https://github.com/KhronosGroup/Vulkan-Headers
|
||||
cd Vulkan-Headers
|
||||
cmake -G Ninja -B build
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf Vulkan-Headers
|
||||
fdo_log_section_end install_vulkan_headers
|
||||
|
||||
# Build and install our own version of Mesa. Debian provides a perfectly usable
|
||||
# Mesa, however llvmpipe's rendering behaviour can change subtly over time.
|
||||
|
|
@ -158,87 +149,64 @@ fdo_log_section_end install_vulkan_headers
|
|||
# features from Mesa then bump this version and $FDO_DISTRIBUTION_TAG, however
|
||||
# please be prepared for some of the tests to change output, which will need to
|
||||
# be manually inspected for correctness.
|
||||
fdo_log_section_start_collapsed install_mesa "install_mesa"
|
||||
|
||||
# Needed for Mesa >= 25.3
|
||||
git clone --branch 12.2.0 --depth=1 https://github.com/KhronosGroup/glslang
|
||||
cd glslang
|
||||
cmake -G Ninja -B build
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf glslang
|
||||
|
||||
git clone --branch mesa-26.0.4 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
||||
git clone --branch 23.0 --depth=1 https://gitlab.freedesktop.org/mesa/mesa.git
|
||||
cd mesa
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dgallium-drivers=llvmpipe -Dvulkan-drivers=swrast -Dvideo-codecs= \
|
||||
-Degl=enabled -Dgbm=enabled -Dgles2=enabled -Dllvm=enabled \
|
||||
-Dshared-glapi=enabled -Dglx=disabled
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dgallium-drivers=swrast -Dvulkan-drivers= -Ddri-drivers=
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf mesa
|
||||
fdo_log_section_end install_mesa
|
||||
|
||||
# PipeWire is used for remoting support. Unlike our other dependencies its
|
||||
# behaviour will be stable, however as a pre-1.0 project its API is not yet
|
||||
# stable, so again we lock it to a fixed version.
|
||||
#
|
||||
# ... the version chosen is 0.3.32 with a small Clang-specific build fix.
|
||||
fdo_log_section_start_collapsed install_pipewire "install_pipewire"
|
||||
git clone --single-branch --branch master https://gitlab.freedesktop.org/pipewire/pipewire.git pipewire-src
|
||||
cd pipewire-src
|
||||
git checkout -b snapshot bf112940d0bf8f526dd6229a619c1283835b49c2
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf pipewire-src
|
||||
fdo_log_section_end install_pipewire
|
||||
|
||||
# seatd lets us avoid the pain of open-coding TTY assignment within Weston.
|
||||
# We use this for our tests using the DRM backend.
|
||||
fdo_log_section_start_collapsed install_seatd "install_seatd"
|
||||
git clone --depth=1 --branch 0.6.1 https://git.sr.ht/~kennylevinsen/seatd
|
||||
cd seatd
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled \
|
||||
-Dlibseat-seatd=enabled -Dlibseat-logind=systemd -Dserver=enabled
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf seatd
|
||||
fdo_log_section_end install_seatd
|
||||
|
||||
# Build and install aml and neatvnc, which are required for the VNC backend
|
||||
fdo_log_section_start_collapsed install_aml_neatvnc "install_aml_neatvnc"
|
||||
git clone --branch v0.3.0 --depth=1 https://github.com/any1/aml.git
|
||||
cd aml
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf aml
|
||||
git clone --branch v0.7.0 --depth=1 https://github.com/any1/neatvnc.git
|
||||
cd neatvnc
|
||||
meson setup build --wrap-mode=nofallback -Dauto_features=disabled
|
||||
meson build --wrap-mode=nofallback -Dauto_features=disabled
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf neatvnc
|
||||
fdo_log_section_end install_aml_neatvnc
|
||||
|
||||
# Build and install libdisplay-info, used by drm-backend
|
||||
fdo_log_section_start_collapsed install_libdisplay-info "install_libdisplay-info"
|
||||
git clone --branch 0.2.0 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
||||
git clone --branch 0.1.1 --depth=1 https://gitlab.freedesktop.org/emersion/libdisplay-info.git
|
||||
cd libdisplay-info
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf libdisplay-info
|
||||
fdo_log_section_end install_libdisplay-info
|
||||
|
||||
# Build and install lcms2, which we use to support color-management.
|
||||
fdo_log_section_start_collapsed install_lcms2 "install_lcms2"
|
||||
git clone --branch master https://github.com/mm2/Little-CMS.git lcms2
|
||||
cd lcms2
|
||||
git checkout -b snapshot lcms2.16
|
||||
meson setup build --wrap-mode=nofallback
|
||||
meson build --wrap-mode=nofallback
|
||||
ninja ${NINJAFLAGS} -C build install
|
||||
cd ..
|
||||
rm -rf lcms2
|
||||
fdo_log_section_end install_lcms2
|
||||
|
|
|
|||
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -xe
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
fdo_log_section_start_collapsed build_weston "build_weston"
|
||||
cd "$BUILDDIR"
|
||||
meson --prefix="$PREFIX" --wrap-mode=nofallback $SANITIZE ${MESON_OPTIONS} ${MESON_TOOLCHAIN_OPTIONS} ${MESON_DIST_OPTIONS} ..
|
||||
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
ninja install
|
||||
|
||||
if [ "$CI_JOB_NAME" == "x86_64-debian-full-build" ]; then
|
||||
cd "$BUILDDIR_WESTINY"
|
||||
export NPREFIX=$CI_PROJECT_DIR/prefix-weston-$CI_JOB_NAME
|
||||
export PKG_CONFIG_PATH=$NPREFIX/lib/pkgconfig/:$NPREFIX/share/pkgconfig/:$NPREFIX/lib/x86_64-linux-gnu/pkgconfig:$PKG_CONFIG_PATH
|
||||
meson setup --prefix="$PREFIX_WESTINY" --wrap-mode=nofallback ../westinyplus/
|
||||
ninja -k0 -j${FDO_CI_CONCURRENT:-4}
|
||||
ninja install
|
||||
ninja clean
|
||||
cd -
|
||||
fi
|
||||
fdo_log_section_end build_weston
|
||||
|
|
@ -26,22 +26,14 @@ MESA_DEV_PKGS="
|
|||
python3-mako
|
||||
"
|
||||
|
||||
# These get temporarily installed for other build dependencies and then
|
||||
# force-removed.
|
||||
# cmake is used by Vulkan-Headers
|
||||
BUILD_DEV_PKGS="
|
||||
cmake
|
||||
"
|
||||
|
||||
# Needed for running the custom-built mesa
|
||||
MESA_RUNTIME_PKGS="
|
||||
libllvm${LLVM_VERSION}
|
||||
"
|
||||
|
||||
if [ x"$USE_DEBIAN_BACKPORTS" = "xy" ] ; then
|
||||
echo 'deb http://deb.debian.org/debian '${FDO_DISTRIBUTION_VERSION}'-backports main' >> /etc/apt/sources.list
|
||||
if [ x"$USE_BOOKWORM_BACKPORTS" = "xy" ] ; then
|
||||
echo 'deb http://deb.debian.org/debian bookworm-backports main' >> /etc/apt/sources.list
|
||||
fi
|
||||
|
||||
apt-get update
|
||||
apt-get -y --no-install-recommends install \
|
||||
autoconf \
|
||||
|
|
@ -53,7 +45,6 @@ apt-get -y --no-install-recommends install \
|
|||
graphviz \
|
||||
gcovr \
|
||||
git \
|
||||
glslang-tools \
|
||||
hwdata \
|
||||
lcov \
|
||||
libasound2-dev \
|
||||
|
|
@ -68,7 +59,7 @@ apt-get -y --no-install-recommends install \
|
|||
libexpat1-dev \
|
||||
libffi-dev \
|
||||
libgbm-dev \
|
||||
libgdk-pixbuf-xlib-2.0-dev \
|
||||
libgdk-pixbuf2.0-dev \
|
||||
libgles2-mesa-dev \
|
||||
libglu1-mesa-dev \
|
||||
libgstreamer1.0-dev \
|
||||
|
|
@ -77,7 +68,6 @@ apt-get -y --no-install-recommends install \
|
|||
libjack-jackd2-dev \
|
||||
libjpeg-dev \
|
||||
libjpeg-dev \
|
||||
liblua5.4-dev \
|
||||
libmtdev-dev \
|
||||
libpam0g-dev \
|
||||
libpango1.0-dev \
|
||||
|
|
@ -132,9 +122,7 @@ apt-get -y --no-install-recommends install \
|
|||
cargo rustc \
|
||||
iproute2 udev \
|
||||
$MESA_DEV_PKGS \
|
||||
$BUILD_DEV_PKGS \
|
||||
$MESA_RUNTIME_PKGS \
|
||||
$PACKAGES_SPECIFIC \
|
||||
$LINUX_DEV_PKGS \
|
||||
|
||||
if [ "$FREERDP_VERSION" -ne 0 ] ; then
|
||||
|
|
@ -147,4 +135,4 @@ fi
|
|||
|
||||
# And remove packages which are only required for our build dependencies,
|
||||
# which we don't need bloating the image whilst we build and run Weston.
|
||||
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS $BUILD_DEV_PKGS
|
||||
apt-get -y --autoremove purge $LINUX_DEV_PKGS $MESA_DEV_PKGS
|
||||
|
|
|
|||
|
|
@ -11,16 +11,3 @@ leak:wl_shm_buffer_begin_access
|
|||
leak:g_malloc0
|
||||
leak:sysprof_collector_get
|
||||
leak:/ld-*.so*
|
||||
|
||||
# Add all of perfetto, since it's not easy to clean up after it
|
||||
leak:perfetto
|
||||
|
||||
# lavapipe inexplicably leaks when Vulkan physical devices are enumerated,
|
||||
# despite us a) not using that device and b) freeing the instance. This is
|
||||
# apparently a known issue. (Also when ASan creates threads ...)
|
||||
leak:vkEnumeratePhysicalDevices
|
||||
leak:asan_thread_start
|
||||
|
||||
# glib/pangoft for Trixie update
|
||||
leak:libpangoft2
|
||||
leak:libglib
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -xe
|
||||
|
||||
source "${FDO_CI_BASH_HELPERS}"
|
||||
|
||||
cd "$BUILDDIR"
|
||||
test -n "${QEMU_SMP}" || QEMU_SMP=${FDO_CI_CONCURRENT:-4}
|
||||
virtme-run --rw --pwd --kimg /weston-virtme/${KERNEL_IMAGE} --kopt quiet --kopt log_buf_len=2M --script-sh ../.gitlab-ci/virtme-scripts/run-weston-tests.sh --qemu-opts -m 4096 -smp ${QEMU_SMP}
|
||||
TEST_RES=$(cat $TESTS_RES_PATH)
|
||||
rm $TESTS_RES_PATH
|
||||
cp -R /weston-virtme ./
|
||||
rm weston-virtme/${KERNEL_IMAGE}
|
||||
exit $TEST_RES
|
||||
|
|
@ -12,7 +12,10 @@ export LIBSEAT_BACKEND=seatd
|
|||
# devices are loaded is not predictable, so the DRM node that VKMS takes can
|
||||
# change across each boot. That's why we have this one-liner shell script to get
|
||||
# the appropriate node for VKMS.
|
||||
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/bus/faux/devices/vkms/drm/card*)
|
||||
export WESTON_TEST_SUITE_DRM_DEVICE=$(basename /sys/devices/platform/vkms/drm/card*)
|
||||
# To run tests in the CI that exercise the zwp_linux_dmabuf_v1 implementation in
|
||||
# Weston, we use VGEM to allocate buffers.
|
||||
export WESTON_TEST_SUITE_ALLOC_DEVICE=$(basename /sys/devices/platform/vgem/drm/card*)
|
||||
|
||||
# ninja test depends on meson, and meson itself looks for its modules on folder
|
||||
# $HOME/.local/lib/pythonX.Y/site-packages (the Python version may differ).
|
||||
|
|
@ -23,11 +26,11 @@ export HOME=/root
|
|||
export PATH=$HOME/.local/bin:$PATH
|
||||
export PATH=/usr/local/bin:$PATH
|
||||
|
||||
export SEATD_LOGLEVEL=debug
|
||||
|
||||
# Terrible hack, per comment in weston-test-runner.c's main(): find Mesa's
|
||||
# llvmpipe/lavapipe driver module location
|
||||
export WESTON_CI_LEAK_DL_HANDLES=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true):
|
||||
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libvulkan_lvp.so -print 2>/dev/null || true)
|
||||
export WESTON_CI_LEAK_DL_HANDLES=$WESTON_CI_LEAK_DL_HANDLES:$(find /usr/local -name libgallium\*.so -print 2>/dev/null || true)
|
||||
# llvmpipe driver module location
|
||||
export WESTON_CI_LEAK_DL_HANDLE=$(find /usr/local -name swrast_dri.so -print 2>/dev/null || true)
|
||||
|
||||
# run the tests and save the exit status
|
||||
# we give ourselves a very generous timeout multiplier due to ASan overhead
|
||||
|
|
|
|||
|
|
@ -117,11 +117,11 @@ finish_calibration (struct calibrator *calibrator)
|
|||
*/
|
||||
memset(&m, 0, sizeof(m));
|
||||
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
||||
m.M.col[0].el[i] = calibrator->tests[i].clicked_x;
|
||||
m.M.col[1].el[i] = calibrator->tests[i].clicked_y;
|
||||
m.M.col[2].el[i] = 1;
|
||||
m.d[i] = calibrator->tests[i].clicked_x;
|
||||
m.d[i + 4] = calibrator->tests[i].clicked_y;
|
||||
m.d[i + 8] = 1;
|
||||
}
|
||||
m.M.col[3].el[3] = 1;
|
||||
m.d[15] = 1;
|
||||
|
||||
weston_matrix_invert(&inverse, &m);
|
||||
|
||||
|
|
@ -129,8 +129,8 @@ finish_calibration (struct calibrator *calibrator)
|
|||
memset(&y_calib, 0, sizeof(y_calib));
|
||||
|
||||
for (i = 0; i < (int)ARRAY_LENGTH(test_ratios); i++) {
|
||||
x_calib.v.el[i] = calibrator->tests[i].drawn_x;
|
||||
y_calib.v.el[i] = calibrator->tests[i].drawn_y;
|
||||
x_calib.f[i] = calibrator->tests[i].drawn_x;
|
||||
y_calib.f[i] = calibrator->tests[i].drawn_y;
|
||||
}
|
||||
|
||||
/* Multiples into the vector */
|
||||
|
|
@ -138,8 +138,8 @@ finish_calibration (struct calibrator *calibrator)
|
|||
weston_matrix_transform(&inverse, &y_calib);
|
||||
|
||||
printf ("Calibration values: %f %f %f %f %f %f\n",
|
||||
x_calib.v.el[0], x_calib.v.el[1], x_calib.v.el[2],
|
||||
y_calib.v.el[0], y_calib.v.el[1], y_calib.v.el[2]);
|
||||
x_calib.f[0], x_calib.f[1], x_calib.f[2],
|
||||
y_calib.f[0], y_calib.f[1], y_calib.f[2]);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
|||
610
clients/color.c
610
clients/color.c
|
|
@ -1,610 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2024 SUSE Software Solutions Germany GmbH
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "color-management-v1-client-protocol.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "single-pixel-buffer-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "window.h"
|
||||
|
||||
enum image_description_status {
|
||||
IMAGE_DESCRIPTION_NOT_CREATED = 0,
|
||||
IMAGE_DESCRIPTION_READY,
|
||||
IMAGE_DESCRIPTION_FAILED,
|
||||
};
|
||||
|
||||
struct pixel_color {
|
||||
uint32_t r;
|
||||
uint32_t g;
|
||||
uint32_t b;
|
||||
uint32_t a;
|
||||
};
|
||||
|
||||
struct color {
|
||||
struct display *display;
|
||||
struct window *window;
|
||||
struct widget *parent_widget;
|
||||
struct widget *widget;
|
||||
|
||||
struct wp_color_manager_v1 *color_manager;
|
||||
struct wp_color_management_surface_v1 *color_surface;
|
||||
struct wp_single_pixel_buffer_manager_v1 *single_pixel_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
struct wp_viewport *viewport;
|
||||
|
||||
struct pixel_color pixel_color;
|
||||
|
||||
bool unmanaged;
|
||||
|
||||
enum wp_color_manager_v1_primaries primaries;
|
||||
enum wp_color_manager_v1_transfer_function transfer_function;
|
||||
float min_lum;
|
||||
float max_lum;
|
||||
float ref_lum;
|
||||
|
||||
uint32_t supported_color_features;
|
||||
uint32_t supported_rendering_intents;
|
||||
uint32_t supported_primaries_named;
|
||||
uint32_t supported_tf_named;
|
||||
};
|
||||
|
||||
struct valid_enum {
|
||||
const char *name;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
static bool opt_help = false;
|
||||
static uint32_t opt_width = 250;
|
||||
static uint32_t opt_height = 250;
|
||||
static const char *opt_r = NULL;
|
||||
static const char *opt_g = NULL;
|
||||
static const char *opt_b = NULL;
|
||||
static const char *opt_a = NULL;
|
||||
static bool opt_unmanaged = false;
|
||||
static const char *opt_primaries = NULL;
|
||||
static const char *opt_transfer_function = NULL;
|
||||
static const char *opt_min_lum = NULL;
|
||||
static const char *opt_max_lum = NULL;
|
||||
static const char *opt_ref_lum = NULL;
|
||||
static const struct weston_option cli_options[] = {
|
||||
{ WESTON_OPTION_BOOLEAN, "help", 0, &opt_help },
|
||||
{ WESTON_OPTION_UNSIGNED_INTEGER, "width", 'w', &opt_width },
|
||||
{ WESTON_OPTION_UNSIGNED_INTEGER, "height", 'h', &opt_height },
|
||||
{ WESTON_OPTION_STRING, 0, 'R', &opt_r },
|
||||
{ WESTON_OPTION_STRING, 0, 'G', &opt_g },
|
||||
{ WESTON_OPTION_STRING, 0, 'B', &opt_b },
|
||||
{ WESTON_OPTION_STRING, 0, 'A', &opt_a },
|
||||
{ WESTON_OPTION_BOOLEAN, "unmanaged", 'u', &opt_unmanaged },
|
||||
{ WESTON_OPTION_STRING, "primaries", 'p', &opt_primaries },
|
||||
{ WESTON_OPTION_STRING, "transfer-function", 't', &opt_transfer_function },
|
||||
{ WESTON_OPTION_STRING, "min-lum", 'm', &opt_min_lum },
|
||||
{ WESTON_OPTION_STRING, "max-lum", 'M', &opt_max_lum },
|
||||
{ WESTON_OPTION_STRING, "ref-lum", 'r', &opt_ref_lum },
|
||||
};
|
||||
|
||||
static const struct valid_enum valid_primaries[] = {
|
||||
{ "srgb", WP_COLOR_MANAGER_V1_PRIMARIES_SRGB },
|
||||
{ "bt2020", WP_COLOR_MANAGER_V1_PRIMARIES_BT2020 },
|
||||
};
|
||||
|
||||
static const struct valid_enum valid_transfer_functions[] = {
|
||||
{ "srgb", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB },
|
||||
{ "pq", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ },
|
||||
{ "linear", WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR },
|
||||
};
|
||||
|
||||
static bool
|
||||
validate_color(const char *c, uint32_t *dest, uint32_t fallback)
|
||||
{
|
||||
char *end;
|
||||
double value;
|
||||
|
||||
if (!c) {
|
||||
*dest = fallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = strtod(c, &end);
|
||||
if (value < 0.0 || value > 1.0 || *end != '\0') {
|
||||
fprintf(stderr, "Validating color failed, it should be between 0.0 and 1.0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = value * UINT32_MAX;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_option(const struct color *color,
|
||||
const char *option, uint32_t *dest,
|
||||
const struct valid_enum *valid_options,
|
||||
int count, uint32_t fallback)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (color->unmanaged && option) {
|
||||
fprintf(stderr, "Option '%s' not valid in unmanaged mode\n", option);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!option) {
|
||||
*dest = fallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (strcmp(valid_options[i].name, option) == 0) {
|
||||
*dest = valid_options[i].value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "Validating option '%s' failed, valid options:\n", option);
|
||||
for (i = 0; i < count; i++)
|
||||
fprintf(stderr, "'%s' ", valid_options[i].name);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_luminance(const struct color *color,
|
||||
const char *c, float *dest, float fallback)
|
||||
{
|
||||
char *end;
|
||||
float value;
|
||||
|
||||
if (color->unmanaged && c) {
|
||||
fprintf(stderr, "Luminance not valid in unmanaged mode.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!c) {
|
||||
*dest = fallback;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = strtof(c, &end);
|
||||
if (value < 0.f || value > 10000.f || *end != '\0') {
|
||||
fprintf(stderr, "Validating luminance failed, it should be between 0 and 10,000\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
*dest = value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_options(struct color *color)
|
||||
{
|
||||
color->unmanaged = opt_unmanaged;
|
||||
|
||||
return validate_color(opt_r, &color->pixel_color.r, 0) &&
|
||||
validate_color(opt_g, &color->pixel_color.g, 0) &&
|
||||
validate_color(opt_b, &color->pixel_color.b, 0) &&
|
||||
validate_color(opt_a, &color->pixel_color.a, UINT32_MAX) &&
|
||||
validate_option(color, opt_primaries, &color->primaries,
|
||||
valid_primaries,
|
||||
ARRAY_LENGTH(valid_primaries),
|
||||
WP_COLOR_MANAGER_V1_PRIMARIES_SRGB) &&
|
||||
validate_option(color, opt_transfer_function, &color->transfer_function,
|
||||
valid_transfer_functions,
|
||||
ARRAY_LENGTH(valid_transfer_functions),
|
||||
WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) &&
|
||||
validate_luminance(color, opt_min_lum, &color->min_lum, -1.f) &&
|
||||
validate_luminance(color, opt_max_lum, &color->max_lum, -1.f) &&
|
||||
validate_luminance(color, opt_ref_lum, &color->ref_lum, -1.f);
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *program_name, int exit_code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
fprintf(stderr, "Usage: %s [OPTIONS]\n", program_name);
|
||||
fprintf(stderr, " --help\n");
|
||||
fprintf(stderr, " --width or -w\n");
|
||||
fprintf(stderr, " --height or -h\n");
|
||||
fprintf(stderr, " -R (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " -G (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " -B (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " -A (0.0 to 1.0)\n");
|
||||
fprintf(stderr, " Mode of operation may be:\n");
|
||||
fprintf(stderr, " --unmanaged or -u: do not use color-management\n");
|
||||
fprintf(stderr, " Or use the following:\n");
|
||||
fprintf(stderr, " --primaries or -p:");
|
||||
fprintf(stderr, "\n ");
|
||||
for (i = 0; i < ARRAY_LENGTH(valid_primaries); i++)
|
||||
fprintf(stderr, " '%s'", valid_primaries[i].name);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " --transfer-function or -t:");
|
||||
fprintf(stderr, "\n ");
|
||||
for (i = 0; i < ARRAY_LENGTH(valid_transfer_functions); i++)
|
||||
fprintf(stderr, " '%s'", valid_transfer_functions[i].name);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " --min-lum or -m (0.0 to 10000.0)\n");
|
||||
fprintf(stderr, " --max-lum or -M (0.0 to 10000.0)\n");
|
||||
fprintf(stderr, " --ref-lum or -r (0.0 to 10000.0)\n");
|
||||
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
static void
|
||||
supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t render_intent)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_rendering_intents |= 1 << render_intent;
|
||||
}
|
||||
|
||||
static void
|
||||
supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t feature)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_color_features |= 1 << feature;
|
||||
}
|
||||
|
||||
static void
|
||||
supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t tf)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_tf_named |= 1 << tf;
|
||||
}
|
||||
|
||||
static void
|
||||
supported_primaries_named(void *data,
|
||||
struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
uint32_t primaries)
|
||||
{
|
||||
struct color *color = data;
|
||||
|
||||
color->supported_primaries_named |= 1 << primaries;
|
||||
}
|
||||
|
||||
static void
|
||||
done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wp_color_manager_v1_listener color_manager_listener = {
|
||||
supported_intent,
|
||||
supported_feature,
|
||||
supported_tf_named,
|
||||
supported_primaries_named,
|
||||
done,
|
||||
};
|
||||
|
||||
static void
|
||||
global_handler(struct display *display, uint32_t name,
|
||||
const char *interface, uint32_t version, void *data)
|
||||
{
|
||||
struct color *color = data;
|
||||
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
||||
|
||||
if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
||||
color->single_pixel_manager =
|
||||
display_bind(display, name,
|
||||
&wp_single_pixel_buffer_manager_v1_interface, 1);
|
||||
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
||||
color->viewporter = display_bind(display, name,
|
||||
&wp_viewporter_interface, 1);
|
||||
color->viewport = wp_viewporter_get_viewport(color->viewporter, surface);
|
||||
}
|
||||
|
||||
if (color->unmanaged)
|
||||
return;
|
||||
|
||||
if (strcmp(interface, wp_color_manager_v1_interface.name) == 0) {
|
||||
color->color_manager = display_bind(display, name,
|
||||
&wp_color_manager_v1_interface, 1);
|
||||
color->color_surface = wp_color_manager_v1_get_surface(color->color_manager,
|
||||
surface);
|
||||
wp_color_manager_v1_add_listener(color->color_manager,
|
||||
&color_manager_listener, color);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
check_color_requirements(struct color *color)
|
||||
{
|
||||
|
||||
if (!color->color_manager) {
|
||||
fprintf(stderr, "The compositor doesn't expose %s\n",
|
||||
wp_color_manager_v1_interface.name);
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_PARAMETRIC))) {
|
||||
fprintf(stderr, "The color manager doesn't support the parametric creator\n");
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_primaries_named & (1 << color->primaries))) {
|
||||
fprintf(stderr, "The color manager doesn't support the primaries name\n");
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_tf_named & (1 << color->transfer_function))) {
|
||||
fprintf(stderr, "The color manager doesn't support the transfer function\n");
|
||||
return false;
|
||||
}
|
||||
if (!(color->supported_rendering_intents & (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL))) {
|
||||
fprintf(stderr, "The color manager doesn't support perceptual render intent\n");
|
||||
return false;
|
||||
}
|
||||
if (color->min_lum != -1.f || color->max_lum != -1.f || color->ref_lum != -1.f) {
|
||||
if (!(color->supported_color_features & (1 << WP_COLOR_MANAGER_V1_FEATURE_SET_LUMINANCES))) {
|
||||
fprintf(stderr, "The color manager doesn't support setting luminances\n");
|
||||
return false;
|
||||
}
|
||||
if (color->min_lum == -1.f || color->max_lum == -1.f || color->ref_lum == -1.f) {
|
||||
fprintf(stderr, "To set the luminances it is required min-lum, max-lum and ref-lum\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
color_destroy(struct color *color)
|
||||
{
|
||||
if (color->color_surface)
|
||||
wp_color_management_surface_v1_destroy(color->color_surface);
|
||||
|
||||
if (color->color_manager)
|
||||
wp_color_manager_v1_destroy(color->color_manager);
|
||||
|
||||
if (color->single_pixel_manager)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(color->single_pixel_manager);
|
||||
|
||||
if (color->viewport)
|
||||
wp_viewport_destroy(color->viewport);
|
||||
|
||||
if (color->viewporter)
|
||||
wp_viewporter_destroy(color->viewporter);
|
||||
|
||||
if (color->widget)
|
||||
widget_destroy(color->widget);
|
||||
|
||||
if (color->parent_widget)
|
||||
widget_destroy(color->parent_widget);
|
||||
|
||||
if (color->window)
|
||||
window_destroy(color->window);
|
||||
|
||||
if (color->display)
|
||||
display_destroy(color->display);
|
||||
|
||||
free(color);
|
||||
}
|
||||
|
||||
static void
|
||||
resize_handler(struct widget *parent_widget, int32_t width, int32_t height, void *data)
|
||||
{
|
||||
struct color *color = data;
|
||||
struct rectangle allocation;
|
||||
struct wl_surface *surface = widget_get_wl_surface(color->widget);
|
||||
struct wl_subsurface *subsurface = widget_get_wl_subsurface(color->widget);
|
||||
|
||||
widget_get_allocation(parent_widget, &allocation);
|
||||
wl_subsurface_set_position(subsurface, allocation.x, allocation.y);
|
||||
|
||||
wp_viewport_set_destination(color->viewport, width, height);
|
||||
|
||||
wl_surface_commit(surface);
|
||||
}
|
||||
|
||||
static void
|
||||
set_empty_input_region(struct color *color, struct widget *widget)
|
||||
{
|
||||
struct wl_region *region;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_surface *surface = widget_get_wl_surface(widget);
|
||||
|
||||
compositor = display_get_compositor(color->display);
|
||||
region = wl_compositor_create_region(compositor);
|
||||
wl_surface_set_input_region(surface, region);
|
||||
wl_region_destroy(region);
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
wl_buffer_destroy(buffer);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
||||
static void
|
||||
set_single_pixel(struct color *color, struct widget *widget)
|
||||
{
|
||||
struct wl_surface *surface = widget_get_wl_surface(widget);
|
||||
struct wl_buffer *buffer =
|
||||
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(color->single_pixel_manager,
|
||||
color->pixel_color.r,
|
||||
color->pixel_color.g,
|
||||
color->pixel_color.b,
|
||||
color->pixel_color.a);
|
||||
wl_buffer_add_listener(buffer, &buffer_listener, NULL);
|
||||
wl_surface_attach(surface, buffer, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
image_description_failed(void *data,
|
||||
struct wp_image_description_v1 *wp_image_description_v1,
|
||||
uint32_t cause, const char *msg)
|
||||
{
|
||||
enum image_description_status *image_desc_status = data;
|
||||
|
||||
fprintf(stderr, "Failed to create image description: %u - %s\n",
|
||||
cause, msg);
|
||||
|
||||
*image_desc_status = IMAGE_DESCRIPTION_FAILED;
|
||||
}
|
||||
|
||||
static void
|
||||
image_description_ready(void *data, struct wp_image_description_v1 *wp_image_description_v1,
|
||||
uint32_t identity)
|
||||
{
|
||||
enum image_description_status *image_desc_status = data;
|
||||
|
||||
*image_desc_status = IMAGE_DESCRIPTION_READY;
|
||||
}
|
||||
|
||||
static const struct wp_image_description_v1_listener image_description_listener = {
|
||||
image_description_failed,
|
||||
image_description_ready,
|
||||
};
|
||||
|
||||
static struct wp_image_description_v1 *
|
||||
create_image_description(struct color *color, uint32_t primaries_named, uint32_t tf_named)
|
||||
{
|
||||
struct wp_image_description_creator_params_v1 *params_creator;
|
||||
struct wp_image_description_v1 *image_description;
|
||||
enum image_description_status image_desc_status = IMAGE_DESCRIPTION_NOT_CREATED;
|
||||
int ret = 0;
|
||||
|
||||
params_creator = wp_color_manager_v1_create_parametric_creator(color->color_manager);
|
||||
wp_image_description_creator_params_v1_set_primaries_named(params_creator, primaries_named);
|
||||
wp_image_description_creator_params_v1_set_tf_named(params_creator, tf_named);
|
||||
if (color->min_lum != -1 && color->max_lum != -1 && color->ref_lum != -1)
|
||||
wp_image_description_creator_params_v1_set_luminances(params_creator,
|
||||
color->min_lum * 10000,
|
||||
color->max_lum,
|
||||
color->ref_lum);
|
||||
|
||||
image_description = wp_image_description_creator_params_v1_create(params_creator);
|
||||
wp_image_description_v1_add_listener(image_description,
|
||||
&image_description_listener,
|
||||
&image_desc_status);
|
||||
|
||||
while (ret != -1 && image_desc_status == IMAGE_DESCRIPTION_NOT_CREATED)
|
||||
ret = wl_display_dispatch(display_get_display(color->display));
|
||||
if (ret == -1) {
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
fprintf(stderr, "Error when creating the image description: %s\n", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (image_desc_status == IMAGE_DESCRIPTION_FAILED) {
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert(image_desc_status == IMAGE_DESCRIPTION_READY);
|
||||
|
||||
return image_description;
|
||||
}
|
||||
|
||||
static bool
|
||||
set_image_description(struct color *color, struct widget *widget)
|
||||
{
|
||||
struct wp_image_description_v1 *image_description;
|
||||
|
||||
image_description =
|
||||
create_image_description(color,
|
||||
color->primaries,
|
||||
color->transfer_function);
|
||||
if (!image_description)
|
||||
return false;
|
||||
|
||||
wp_color_management_surface_v1_set_image_description(
|
||||
color->color_surface,
|
||||
image_description,
|
||||
WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL);
|
||||
|
||||
wp_image_description_v1_destroy(image_description);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct color *color;
|
||||
|
||||
if (parse_options(cli_options, ARRAY_LENGTH(cli_options), &argc, argv) > 1)
|
||||
usage(argv[0], EXIT_FAILURE);
|
||||
|
||||
if (opt_help)
|
||||
usage(argv[0], EXIT_SUCCESS);
|
||||
|
||||
color = xzalloc(sizeof *color);
|
||||
if (!validate_options(color)) {
|
||||
color_destroy(color);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
color->display = display_create(&argc, argv);
|
||||
if (!color->display) {
|
||||
color_destroy(color);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
color->window = window_create(color->display);
|
||||
color->parent_widget = window_frame_create(color->window, color);
|
||||
color->widget = window_add_subsurface(color->window, color, SUBSURFACE_SYNCHRONIZED);
|
||||
|
||||
display_set_user_data(color->display, color);
|
||||
display_set_global_handler(color->display, global_handler);
|
||||
wl_display_roundtrip(display_get_display(color->display));
|
||||
|
||||
if (!color->unmanaged && !check_color_requirements(color)) {
|
||||
color_destroy(color);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
window_unset_shadow(color->window);
|
||||
window_set_title(color->window, "Color");
|
||||
window_set_appid(color->window, "org.freedesktop.weston.color");
|
||||
/* The first resize call sets the min size,
|
||||
* setting 0, 0 sets a default size */
|
||||
window_schedule_resize(color->window, 0, 0);
|
||||
window_schedule_resize(color->window, opt_width, opt_height);
|
||||
|
||||
widget_set_resize_handler(color->parent_widget, resize_handler);
|
||||
widget_set_use_cairo(color->widget, 0);
|
||||
|
||||
set_empty_input_region(color, color->widget);
|
||||
set_single_pixel(color, color->widget);
|
||||
|
||||
if (color->unmanaged || set_image_description(color, color->widget))
|
||||
display_run(color->display);
|
||||
|
||||
color_destroy(color);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -53,7 +53,6 @@
|
|||
|
||||
#include "window.h"
|
||||
|
||||
#include "single-pixel-buffer-v1-client-protocol.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include "weston-desktop-shell-client-protocol.h"
|
||||
|
||||
|
|
@ -778,148 +777,95 @@ panel_add_launcher(struct panel *panel, const char *icon, const char *path, cons
|
|||
enum {
|
||||
BACKGROUND_SCALE,
|
||||
BACKGROUND_SCALE_CROP,
|
||||
BACKGROUND_SCALE_FIT,
|
||||
BACKGROUND_TILE,
|
||||
BACKGROUND_CENTERED
|
||||
};
|
||||
|
||||
static void
|
||||
buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
wl_buffer_destroy(buffer);
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
||||
static void
|
||||
background_draw(struct widget *widget, void *data)
|
||||
{
|
||||
struct background *background = data;
|
||||
cairo_surface_t *surface, *image;
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_t *cr;
|
||||
double im_w, im_h;
|
||||
double sx, sy, s;
|
||||
double tx, ty;
|
||||
struct rectangle allocation;
|
||||
|
||||
if (!background->image && background->color) {
|
||||
struct display *display = window_get_display(background->window);
|
||||
struct wp_single_pixel_buffer_manager_v1 *sp_manager;
|
||||
struct wl_surface *wl_surface;
|
||||
struct wl_buffer *wl_buffer;
|
||||
uint32_t r8, g8, b8;
|
||||
uint32_t r32, g32, b32;
|
||||
surface = window_get_surface(background->window);
|
||||
|
||||
/* Single pixel buffer must use scale 1 */
|
||||
window_set_buffer_scale(background->window, 1);
|
||||
cr = widget_cairo_create(background->widget);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
if (background->color == 0)
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
|
||||
else
|
||||
set_hex_color(cr, background->color);
|
||||
cairo_paint(cr);
|
||||
|
||||
sp_manager = display_get_single_pixel_buffer_manager(display);
|
||||
assert(sp_manager);
|
||||
wl_surface = widget_get_wl_surface(background->widget);
|
||||
assert(wl_surface);
|
||||
widget_get_allocation(widget, &allocation);
|
||||
image = NULL;
|
||||
if (background->image)
|
||||
image = load_cairo_surface(background->image);
|
||||
else if (background->color == 0) {
|
||||
char *name = file_name_with_datadir("pattern.png");
|
||||
|
||||
r8 = (background->color >> 16) & 0xff;
|
||||
g8 = (background->color >> 8) & 0xff;
|
||||
b8 = (background->color >> 0) & 0xff;
|
||||
|
||||
r32 = r8 << 24 | r8 << 16 | r8 << 8 | r8;
|
||||
g32 = g8 << 24 | g8 << 16 | g8 << 8 | g8;
|
||||
b32 = b8 << 24 | b8 << 16 | b8 << 8 | b8;
|
||||
|
||||
wl_buffer =
|
||||
wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(sp_manager,
|
||||
r32,
|
||||
g32,
|
||||
b32,
|
||||
0xffffffff);
|
||||
assert(wl_buffer);
|
||||
|
||||
wl_surface_attach(wl_surface, wl_buffer, 0, 0);
|
||||
wl_buffer_add_listener(wl_buffer, &buffer_listener, NULL);
|
||||
widget_surface_flush(widget);
|
||||
} else {
|
||||
cairo_surface_t *surface, *image;
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_t *cr;
|
||||
double im_w, im_h;
|
||||
double sx, sy, s;
|
||||
double tx, ty;
|
||||
struct rectangle allocation;
|
||||
|
||||
surface = window_get_surface(background->window);
|
||||
|
||||
cr = widget_cairo_create(background->widget);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
|
||||
if (background->color == 0)
|
||||
cairo_set_source_rgba(cr, 0.0, 0.0, 0.2, 1.0);
|
||||
else
|
||||
set_hex_color(cr, background->color);
|
||||
cairo_paint(cr);
|
||||
|
||||
widget_get_allocation(widget, &allocation);
|
||||
image = NULL;
|
||||
if (background->image)
|
||||
image = load_cairo_surface(background->image);
|
||||
else if (background->color == 0) {
|
||||
char *name = file_name_with_datadir("pattern.png");
|
||||
|
||||
image = load_cairo_surface(name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (image && background->type != -1) {
|
||||
im_w = cairo_image_surface_get_width(image);
|
||||
im_h = cairo_image_surface_get_height(image);
|
||||
sx = im_w / allocation.width;
|
||||
sy = im_h / allocation.height;
|
||||
|
||||
pattern = cairo_pattern_create_for_surface(image);
|
||||
|
||||
switch (background->type) {
|
||||
case BACKGROUND_SCALE:
|
||||
cairo_matrix_init_scale(&matrix, sx, sy);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||
break;
|
||||
case BACKGROUND_SCALE_CROP:
|
||||
case BACKGROUND_SCALE_FIT:
|
||||
if (background->type == BACKGROUND_SCALE_CROP)
|
||||
s = (sx < sy) ? sx : sy;
|
||||
else
|
||||
s = (sx > sy) ? sx : sy;
|
||||
/* align center */
|
||||
tx = (im_w - s * allocation.width) * 0.5;
|
||||
ty = (im_h - s * allocation.height) * 0.5;
|
||||
cairo_matrix_init_translate(&matrix, tx, ty);
|
||||
cairo_matrix_scale(&matrix, s, s);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||
break;
|
||||
case BACKGROUND_TILE:
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
||||
break;
|
||||
case BACKGROUND_CENTERED:
|
||||
s = (sx < sy) ? sx : sy;
|
||||
if (s < 1.0)
|
||||
s = 1.0;
|
||||
|
||||
/* align center */
|
||||
tx = (im_w - s * allocation.width) * 0.5;
|
||||
ty = (im_h - s * allocation.height) * 0.5;
|
||||
|
||||
cairo_matrix_init_translate(&matrix, tx, ty);
|
||||
cairo_matrix_scale(&matrix, s, s);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
break;
|
||||
}
|
||||
|
||||
cairo_set_source(cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
cairo_surface_destroy(image);
|
||||
cairo_mask(cr, pattern);
|
||||
}
|
||||
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_destroy(surface);
|
||||
image = load_cairo_surface(name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (image && background->type != -1) {
|
||||
im_w = cairo_image_surface_get_width(image);
|
||||
im_h = cairo_image_surface_get_height(image);
|
||||
sx = im_w / allocation.width;
|
||||
sy = im_h / allocation.height;
|
||||
|
||||
pattern = cairo_pattern_create_for_surface(image);
|
||||
|
||||
switch (background->type) {
|
||||
case BACKGROUND_SCALE:
|
||||
cairo_matrix_init_scale(&matrix, sx, sy);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||
break;
|
||||
case BACKGROUND_SCALE_CROP:
|
||||
s = (sx < sy) ? sx : sy;
|
||||
/* align center */
|
||||
tx = (im_w - s * allocation.width) * 0.5;
|
||||
ty = (im_h - s * allocation.height) * 0.5;
|
||||
cairo_matrix_init_translate(&matrix, tx, ty);
|
||||
cairo_matrix_scale(&matrix, s, s);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_PAD);
|
||||
break;
|
||||
case BACKGROUND_TILE:
|
||||
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT);
|
||||
break;
|
||||
case BACKGROUND_CENTERED:
|
||||
s = (sx < sy) ? sx : sy;
|
||||
if (s < 1.0)
|
||||
s = 1.0;
|
||||
|
||||
/* align center */
|
||||
tx = (im_w - s * allocation.width) * 0.5;
|
||||
ty = (im_h - s * allocation.height) * 0.5;
|
||||
|
||||
cairo_matrix_init_translate(&matrix, tx, ty);
|
||||
cairo_matrix_scale(&matrix, s, s);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
break;
|
||||
}
|
||||
|
||||
cairo_set_source(cr, pattern);
|
||||
cairo_pattern_destroy (pattern);
|
||||
cairo_surface_destroy(image);
|
||||
cairo_mask(cr, pattern);
|
||||
}
|
||||
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
background->painted = 1;
|
||||
check_desktop_ready(background->window);
|
||||
}
|
||||
|
|
@ -946,7 +892,6 @@ background_configure(void *data,
|
|||
}
|
||||
|
||||
if (!background->image && background->color) {
|
||||
widget_set_use_cairo(background->widget, 0);
|
||||
widget_set_viewport_destination(background->widget, width, height);
|
||||
width = 1;
|
||||
height = 1;
|
||||
|
|
@ -1246,10 +1191,6 @@ background_create(struct desktop *desktop, struct output *output)
|
|||
weston_config_section_get_color(s, "background-color",
|
||||
&background->color, 0x00000000);
|
||||
|
||||
/* Backgrounds must be fully opaque. */
|
||||
if (background->color != 0)
|
||||
background->color |= 0xFF000000;
|
||||
|
||||
weston_config_section_get_string(s, "background-type",
|
||||
&type, "tile");
|
||||
if (type == NULL) {
|
||||
|
|
@ -1261,8 +1202,6 @@ background_create(struct desktop *desktop, struct output *output)
|
|||
background->type = BACKGROUND_SCALE;
|
||||
} else if (strcmp(type, "scale-crop") == 0) {
|
||||
background->type = BACKGROUND_SCALE_CROP;
|
||||
} else if (strcmp(type, "scale-fit") == 0) {
|
||||
background->type = BACKGROUND_SCALE_FIT;
|
||||
} else if (strcmp(type, "tile") == 0) {
|
||||
background->type = BACKGROUND_TILE;
|
||||
} else if (strcmp(type, "centered") == 0) {
|
||||
|
|
@ -1382,11 +1321,10 @@ output_handle_scale(void *data,
|
|||
int32_t scale)
|
||||
{
|
||||
struct output *output = data;
|
||||
struct background *background = output->background;
|
||||
|
||||
if (output->panel)
|
||||
window_set_buffer_scale(output->panel->window, scale);
|
||||
if (background && !background->color)
|
||||
if (output->background)
|
||||
window_set_buffer_scale(output->background->window, scale);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -515,7 +515,7 @@ create_drag_source(struct dnd *dnd,
|
|||
dnd_drag->drag_surface =
|
||||
wl_compositor_create_surface(compositor);
|
||||
|
||||
if (dnd->self_only || display_get_data_device_manager_version(display) <
|
||||
if (display_get_data_device_manager_version(display) <
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
||||
/* Data sources version < 3 will not get action
|
||||
* nor dnd_finished events, as we can't honor
|
||||
|
|
@ -546,11 +546,11 @@ create_drag_source(struct dnd *dnd,
|
|||
flower_mime_type);
|
||||
wl_data_source_offer(dnd_drag->data_source,
|
||||
text_mime_type);
|
||||
}
|
||||
|
||||
if (display_get_data_device_manager_version(display) >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
||||
wl_data_source_set_actions(dnd_drag->data_source, actions);
|
||||
}
|
||||
if (display_get_data_device_manager_version(display) >=
|
||||
WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
|
||||
wl_data_source_set_actions(dnd_drag->data_source, actions);
|
||||
}
|
||||
|
||||
wl_data_device_start_drag(input_get_data_device(input),
|
||||
|
|
|
|||
|
|
@ -346,7 +346,6 @@ usage(int error_code)
|
|||
fprintf(stderr, "Usage: fullscreen [OPTIONS]\n\n"
|
||||
" -w <width>\tSet window width to <width>\n"
|
||||
" -h <height>\tSet window height to <height>\n"
|
||||
" -f\t\tMap window as fullscreen\n"
|
||||
" --help\tShow this help text\n\n");
|
||||
|
||||
exit(error_code);
|
||||
|
|
@ -395,8 +394,6 @@ int main(int argc, char *argv[])
|
|||
usage(EXIT_FAILURE);
|
||||
|
||||
fullscreen.height = atol(argv[i]);
|
||||
} else if (strcmp(argv[i], "-f") == 0) {
|
||||
fullscreen.fullscreen = 1;
|
||||
} else if (strcmp(argv[i], "--help") == 0)
|
||||
usage(EXIT_SUCCESS);
|
||||
else
|
||||
|
|
@ -437,8 +434,6 @@ int main(int argc, char *argv[])
|
|||
window_set_fullscreen_handler(fullscreen.window, fullscreen_handler);
|
||||
|
||||
window_set_user_data(fullscreen.window, &fullscreen);
|
||||
if (fullscreen.fullscreen)
|
||||
window_set_fullscreen(fullscreen.window, fullscreen.fullscreen);
|
||||
/* Hack to set minimum allocation so we can shrink later */
|
||||
window_schedule_resize(fullscreen.window,
|
||||
1, 1);
|
||||
|
|
|
|||
|
|
@ -143,8 +143,6 @@ hmi_homescreen_launcher {
|
|||
uint32_t workspace_id;
|
||||
char *icon;
|
||||
char *path;
|
||||
char **argv;
|
||||
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
|
|
@ -310,10 +308,12 @@ launcher_button(uint32_t surfaceId, struct wl_list *launcher_list)
|
|||
struct hmi_homescreen_launcher *launcher = NULL;
|
||||
|
||||
wl_list_for_each(launcher, launcher_list, link) {
|
||||
char *argv[] = { NULL };
|
||||
|
||||
if (surfaceId != launcher->icon_surface_id)
|
||||
continue;
|
||||
|
||||
execute_process(launcher->path, launcher->argv);
|
||||
execute_process(launcher->path, argv);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1065,32 +1065,6 @@ create_launchers(struct wlContextCommon *cmm, struct wl_list *launcher_list)
|
|||
free(launchers);
|
||||
}
|
||||
|
||||
static char **
|
||||
parse_command(char *str)
|
||||
{
|
||||
char **argv;
|
||||
char *saveptr;
|
||||
char *token;
|
||||
int i;
|
||||
int count = 1;
|
||||
|
||||
for (i = 1; str[i]; i++)
|
||||
if (str[i] == ' ' && str[i-1] != ' ')
|
||||
count++;
|
||||
|
||||
argv = xcalloc(count + 1, sizeof(char*));
|
||||
|
||||
i = 0;
|
||||
token = strtok_r(str, " ", &saveptr);
|
||||
while (token != NULL) {
|
||||
argv[i++] = token;
|
||||
|
||||
token = strtok_r(NULL, " ", &saveptr);
|
||||
}
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method to read out weston.ini to get configuration
|
||||
*/
|
||||
|
|
@ -1203,7 +1177,6 @@ hmi_homescreen_setting_create(void)
|
|||
|
||||
while (weston_config_next_section(config, §ion, &name)) {
|
||||
struct hmi_homescreen_launcher *launcher;
|
||||
char *command;
|
||||
|
||||
if (strcmp(name, "ivi-launcher") != 0)
|
||||
continue;
|
||||
|
|
@ -1213,18 +1186,8 @@ hmi_homescreen_setting_create(void)
|
|||
|
||||
weston_config_section_get_string(section, "icon",
|
||||
&launcher->icon, NULL);
|
||||
|
||||
weston_config_section_get_string(section, "command",
|
||||
&command, NULL);
|
||||
if (command == NULL) {
|
||||
weston_config_section_get_string(section, "path",
|
||||
&launcher->path, NULL);
|
||||
launcher->argv = NULL;
|
||||
} else {
|
||||
launcher->argv = parse_command(command);
|
||||
launcher->path = launcher->argv[0];
|
||||
}
|
||||
|
||||
weston_config_section_get_string(section, "path",
|
||||
&launcher->path, NULL);
|
||||
weston_config_section_get_uint(section, "workspace-id",
|
||||
&launcher->workspace_id, 0);
|
||||
weston_config_section_get_uint(section, "icon-id",
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ srcs_toytoolkit = [
|
|||
relative_pointer_unstable_v1_protocol_c,
|
||||
pointer_constraints_unstable_v1_client_protocol_h,
|
||||
pointer_constraints_unstable_v1_protocol_c,
|
||||
single_pixel_buffer_v1_client_protocol_h,
|
||||
single_pixel_buffer_v1_protocol_c,
|
||||
tablet_unstable_v2_client_protocol_h,
|
||||
tablet_unstable_v2_protocol_c,
|
||||
ivi_application_client_protocol_h,
|
||||
|
|
@ -42,7 +40,10 @@ dep_toytoolkit = declare_dependency(
|
|||
link_with: lib_toytoolkit,
|
||||
dependencies: deps_toytoolkit,
|
||||
)
|
||||
dep_gbm = dependency('gbm', required: false, version: '>= 21.3')
|
||||
dep_gbm = dependency('gbm', required: false, version: '>= 21.1.1')
|
||||
if dep_gbm.found() and dep_gbm.version().version_compare('>= 21.3')
|
||||
config_h.set('HAVE_GBM_BO_CREATE_WITH_MODIFIERS2', '1')
|
||||
endif
|
||||
|
||||
simple_clients_enabled = get_option('simple-clients')
|
||||
simple_build_all = simple_clients_enabled.contains('all')
|
||||
|
|
@ -160,21 +161,6 @@ simple_clients = [
|
|||
],
|
||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
||||
},
|
||||
{
|
||||
'name': 'timing',
|
||||
'sources': [
|
||||
'simple-timing.c',
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
commit_timing_v1_client_protocol_h,
|
||||
commit_timing_v1_protocol_c,
|
||||
fifo_v1_client_protocol_h,
|
||||
fifo_v1_protocol_c,
|
||||
presentation_time_client_protocol_h,
|
||||
presentation_time_protocol_c,
|
||||
],
|
||||
'dep_objs': [ dep_wayland_client, dep_libshared ]
|
||||
},
|
||||
{
|
||||
'name': 'touch',
|
||||
'sources': [
|
||||
|
|
@ -186,89 +172,6 @@ simple_clients = [
|
|||
},
|
||||
]
|
||||
|
||||
if dep_vulkan.found() and prog_glslang.found()
|
||||
srcs_simple_vulkan_shaders = [
|
||||
'simple_vulkan_vertex_shader.vert',
|
||||
'simple_vulkan_fragment_shader.frag',
|
||||
]
|
||||
|
||||
simple_vulkan_shaders = []
|
||||
foreach s : srcs_simple_vulkan_shaders
|
||||
simple_vulkan_shaders += custom_target(s + '.spv.h',
|
||||
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
||||
input: s,
|
||||
output: '@BASENAME@.spv.h',
|
||||
)
|
||||
endforeach
|
||||
|
||||
simple_clients += {
|
||||
'name': 'vulkan',
|
||||
'sources': [
|
||||
'simple-vulkan.c',
|
||||
simple_vulkan_shaders,
|
||||
fractional_scale_v1_client_protocol_h,
|
||||
fractional_scale_v1_protocol_c,
|
||||
tearing_control_v1_client_protocol_h,
|
||||
tearing_control_v1_protocol_c,
|
||||
viewporter_client_protocol_h,
|
||||
viewporter_protocol_c,
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
],
|
||||
'dep_objs': [
|
||||
dep_vulkan,
|
||||
dep_libm,
|
||||
dep_libshared,
|
||||
dep_matrix_c,
|
||||
dep_wayland_client,
|
||||
],
|
||||
'deps': [ 'vulkan', 'wayland-cursor' ],
|
||||
'options': [ 'renderer-gl' ]
|
||||
}
|
||||
|
||||
srcs_simple_dmabuf_vulkan_shaders = [
|
||||
'simple_dmabuf_vulkan_vertex_shader.vert',
|
||||
'simple_dmabuf_vulkan_fragment_shader.frag',
|
||||
]
|
||||
|
||||
simple_dmabuf_vulkan_shaders = []
|
||||
foreach s : srcs_simple_dmabuf_vulkan_shaders
|
||||
simple_dmabuf_vulkan_shaders += custom_target(s + '.spv.h',
|
||||
command: [ prog_glslang, '@INPUT@', '--quiet', '--variable-name', '@BASENAME@', '-V', '-x', '-o', '@OUTPUT@' ],
|
||||
input: s,
|
||||
output: '@BASENAME@.spv.h',
|
||||
)
|
||||
endforeach
|
||||
|
||||
simple_clients += {
|
||||
'name': 'dmabuf-vulkan',
|
||||
'sources': [
|
||||
'simple-dmabuf-vulkan.c',
|
||||
simple_dmabuf_vulkan_shaders,
|
||||
linux_dmabuf_unstable_v1_client_protocol_h,
|
||||
linux_dmabuf_unstable_v1_protocol_c,
|
||||
linux_explicit_synchronization_unstable_v1_client_protocol_h,
|
||||
linux_explicit_synchronization_unstable_v1_protocol_c,
|
||||
xdg_shell_client_protocol_h,
|
||||
xdg_shell_protocol_c,
|
||||
weston_direct_display_client_protocol_h,
|
||||
weston_direct_display_protocol_c,
|
||||
],
|
||||
'dep_objs': [
|
||||
dep_vulkan,
|
||||
dep_libdrm_headers,
|
||||
dep_libm,
|
||||
dep_libdrm,
|
||||
dep_libshared,
|
||||
dep_matrix_c,
|
||||
dep_wayland_client,
|
||||
dep_libweston_private, # for pixel-formats.h
|
||||
],
|
||||
'deps': [ 'vulkan', 'wayland-cursor', 'gbm' ],
|
||||
'options': [ 'renderer-gl' ]
|
||||
}
|
||||
endif
|
||||
|
||||
foreach t : simple_clients
|
||||
if simple_build_all or simple_clients_enabled.contains(t.get('name'))
|
||||
t_name = 'weston-simple-' + t.get('name')
|
||||
|
|
@ -366,15 +269,6 @@ demo_clients = [
|
|||
'basename': 'cliptest',
|
||||
'dep_objs': [ dep_vertex_clipping, dep_matrix_c ]
|
||||
},
|
||||
{
|
||||
'basename': 'color',
|
||||
'add_sources': [
|
||||
color_management_v1_client_protocol_h,
|
||||
color_management_v1_protocol_c,
|
||||
single_pixel_buffer_v1_client_protocol_h,
|
||||
single_pixel_buffer_v1_protocol_c,
|
||||
],
|
||||
},
|
||||
{
|
||||
'basename': 'constraints',
|
||||
'add_sources': [
|
||||
|
|
@ -497,7 +391,7 @@ if get_option('shell-desktop')
|
|||
env_modmap += 'weston-desktop-shell=@0@;'.format(exe_shell_desktop.full_path())
|
||||
endif
|
||||
|
||||
if get_option('shell-desktop') or get_option('shell-kiosk') or get_option('shell-ivi')
|
||||
if get_option('shell-desktop') or get_option('shell-fullscreen') or get_option('shell-kiosk') or get_option('shell-ivi')
|
||||
exe_shooter = executable(
|
||||
'weston-screenshooter',
|
||||
'screenshot.c',
|
||||
|
|
@ -505,7 +399,6 @@ if get_option('shell-desktop') or get_option('shell-kiosk') or get_option('shell
|
|||
weston_output_capture_protocol_c,
|
||||
include_directories: common_inc,
|
||||
dependencies: [
|
||||
dep_client_buffer,
|
||||
dep_toytoolkit,
|
||||
dep_libweston_private, # for pixel-formats.h
|
||||
dep_pixman,
|
||||
|
|
|
|||
|
|
@ -775,7 +775,7 @@ registry_handle_global(void *data, struct wl_registry *registry,
|
|||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
||||
d->presentation =
|
||||
wl_registry_bind(registry,
|
||||
name, &wp_presentation_interface, 2);
|
||||
name, &wp_presentation_interface, 1);
|
||||
wp_presentation_add_listener(d->presentation,
|
||||
&presentation_listener, d);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,44 +24,33 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cairo.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <pixman.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-client.h>
|
||||
#include <limits.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <pixman.h>
|
||||
#include <cairo.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "shared/client-buffer-util.h"
|
||||
#include "shared/file-util.h"
|
||||
#include "shared/os-compatibility.h"
|
||||
#include "shared/string-helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <wayland-client.h>
|
||||
#include "weston-output-capture-client-protocol.h"
|
||||
#include "shared/os-compatibility.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "shared/file-util.h"
|
||||
#include "pixel-formats.h"
|
||||
|
||||
struct screenshooter_app {
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_shm *shm;
|
||||
struct zwp_linux_dmabuf_v1 *dmabuf;
|
||||
struct weston_capture_v1 *capture_factory;
|
||||
|
||||
bool verbose;
|
||||
const struct pixel_format_info *requested_format;
|
||||
enum weston_capture_v1_source src_type;
|
||||
enum client_buffer_type buffer_type;
|
||||
|
||||
struct wl_list output_list; /* struct screenshooter_output::link */
|
||||
|
||||
bool retry;
|
||||
|
|
@ -70,14 +59,14 @@ struct screenshooter_app {
|
|||
};
|
||||
|
||||
struct screenshooter_buffer {
|
||||
struct client_buffer *buf;
|
||||
size_t len;
|
||||
void *data;
|
||||
struct wl_buffer *wl_buffer;
|
||||
pixman_image_t *image;
|
||||
enum weston_capture_v1_source src_type;
|
||||
};
|
||||
|
||||
struct screenshooter_output {
|
||||
struct screenshooter_app *app;
|
||||
uint32_t name;
|
||||
struct wl_list link; /* struct screenshooter_app::output_list */
|
||||
|
||||
struct wl_output *wl_output;
|
||||
|
|
@ -87,8 +76,7 @@ struct screenshooter_output {
|
|||
|
||||
int buffer_width;
|
||||
int buffer_height;
|
||||
struct wl_array formats;
|
||||
bool formats_done;
|
||||
const struct pixel_format_info *fmt;
|
||||
struct screenshooter_buffer *buffer;
|
||||
};
|
||||
|
||||
|
|
@ -105,6 +93,10 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
|
|||
const struct pixel_format_info *fmt)
|
||||
{
|
||||
struct screenshooter_buffer *buffer;
|
||||
struct wl_shm_pool *pool;
|
||||
int fd;
|
||||
size_t bytes_pp;
|
||||
size_t stride;
|
||||
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
|
|
@ -113,60 +105,54 @@ screenshot_create_shm_buffer(struct screenshooter_app *app,
|
|||
|
||||
buffer = xzalloc(sizeof *buffer);
|
||||
|
||||
buffer->buf = client_buffer_util_create_shm_buffer(app->shm,
|
||||
fmt,
|
||||
width,
|
||||
height);
|
||||
bytes_pp = fmt->bpp / 8;
|
||||
stride = width * bytes_pp;
|
||||
buffer->len = stride * height;
|
||||
|
||||
assert(width == stride / bytes_pp);
|
||||
assert(height == buffer->len / stride);
|
||||
|
||||
fd = os_create_anonymous_file(buffer->len);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "creating a buffer file for %zd B failed: %s\n",
|
||||
buffer->len, strerror(errno));
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer->data = mmap(NULL, buffer->len, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
if (buffer->data == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pool = wl_shm_create_pool(app->shm, fd, buffer->len);
|
||||
close(fd);
|
||||
buffer->wl_buffer =
|
||||
wl_shm_pool_create_buffer(pool, 0, width, height, stride,
|
||||
pixel_format_get_shm_format(fmt));
|
||||
wl_shm_pool_destroy(pool);
|
||||
|
||||
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
||||
width, height,
|
||||
buffer->buf->data,
|
||||
buffer->buf->strides[0]);
|
||||
buffer->data, stride);
|
||||
abort_oom_if_null(buffer->image);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static struct screenshooter_buffer *
|
||||
screenshot_create_udmabuf(struct screenshooter_app *app,
|
||||
int width, int height,
|
||||
const struct pixel_format_info *fmt)
|
||||
{
|
||||
struct screenshooter_buffer* buffer = NULL;
|
||||
|
||||
assert(width > 0);
|
||||
assert(height > 0);
|
||||
assert(fmt);
|
||||
|
||||
buffer = xzalloc(sizeof *buffer);
|
||||
|
||||
buffer->buf = client_buffer_util_create_dmabuf_buffer(app->display,
|
||||
app->dmabuf,
|
||||
fmt,
|
||||
width,
|
||||
height);
|
||||
|
||||
if (fmt->pixman_format) {
|
||||
buffer->image = pixman_image_create_bits(fmt->pixman_format,
|
||||
width, height,
|
||||
buffer->buf->data,
|
||||
buffer->buf->strides[0]);
|
||||
abort_oom_if_null(buffer->image);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
screenshooter_buffer_destroy(struct screenshooter_buffer *buffer)
|
||||
{
|
||||
if (!buffer)
|
||||
return;
|
||||
|
||||
if (buffer->image)
|
||||
pixman_image_unref(buffer->image);
|
||||
|
||||
client_buffer_util_destroy_buffer(buffer->buf);
|
||||
pixman_image_unref(buffer->image);
|
||||
munmap(buffer->data, buffer->len);
|
||||
wl_buffer_destroy(buffer->wl_buffer);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
|
@ -176,37 +162,10 @@ capture_source_handle_format(void *data,
|
|||
uint32_t drm_format)
|
||||
{
|
||||
struct screenshooter_output *output = data;
|
||||
uint32_t *fmt;
|
||||
|
||||
assert(output->source == proxy);
|
||||
|
||||
if (output->formats_done) {
|
||||
wl_array_release(&output->formats);
|
||||
wl_array_init(&output->formats);
|
||||
output->formats_done = false;
|
||||
}
|
||||
|
||||
fmt = wl_array_add(&output->formats, sizeof(uint32_t));
|
||||
assert(fmt);
|
||||
*fmt = drm_format;
|
||||
|
||||
if (output->app->verbose) {
|
||||
const struct pixel_format_info *fmt_info;
|
||||
|
||||
fmt_info = pixel_format_get_info(drm_format);
|
||||
assert(fmt_info);
|
||||
printf("Got format %s / 0x%x\n", fmt_info->drm_format_name,
|
||||
drm_format);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
capture_source_handle_formats_done(void *data,
|
||||
struct weston_capture_source_v1 *proxy)
|
||||
{
|
||||
struct screenshooter_output *output = data;
|
||||
|
||||
output->formats_done = true;
|
||||
output->fmt = pixel_format_get_info(drm_format);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -221,9 +180,6 @@ capture_source_handle_size(void *data,
|
|||
|
||||
output->buffer_width = width;
|
||||
output->buffer_height = height;
|
||||
|
||||
if (output->app->verbose)
|
||||
printf("Got size %dx%d\n", width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -253,9 +209,7 @@ capture_source_handle_failed(void *data,
|
|||
struct screenshooter_output *output = data;
|
||||
|
||||
output->app->waitcount--;
|
||||
/* We don't set app.failed here because there could be other
|
||||
* outputs we still want to capture!
|
||||
*/
|
||||
output->app->failed = true;
|
||||
|
||||
if (msg)
|
||||
fprintf(stderr, "Output capture error: %s\n", msg);
|
||||
|
|
@ -263,7 +217,6 @@ capture_source_handle_failed(void *data,
|
|||
|
||||
static const struct weston_capture_source_v1_listener capture_source_handlers = {
|
||||
.format = capture_source_handle_format,
|
||||
.formats_done = capture_source_handle_formats_done,
|
||||
.size = capture_source_handle_size,
|
||||
.complete = capture_source_handle_complete,
|
||||
.retry = capture_source_handle_retry,
|
||||
|
|
@ -278,20 +231,17 @@ create_output(struct screenshooter_app *app, uint32_t output_name, uint32_t vers
|
|||
version = MIN(version, 4);
|
||||
output = xzalloc(sizeof *output);
|
||||
output->app = app;
|
||||
output->name = output_name;
|
||||
output->wl_output = wl_registry_bind(app->registry, output_name,
|
||||
&wl_output_interface, version);
|
||||
abort_oom_if_null(output->wl_output);
|
||||
|
||||
output->source = weston_capture_v1_create(app->capture_factory,
|
||||
output->wl_output,
|
||||
app->src_type);
|
||||
WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER);
|
||||
abort_oom_if_null(output->source);
|
||||
weston_capture_source_v1_add_listener(output->source,
|
||||
&capture_source_handlers, output);
|
||||
|
||||
wl_array_init(&output->formats);
|
||||
|
||||
wl_list_insert(&app->output_list, &output->link);
|
||||
}
|
||||
|
||||
|
|
@ -300,8 +250,6 @@ destroy_output(struct screenshooter_output *output)
|
|||
{
|
||||
weston_capture_source_v1_destroy(output->source);
|
||||
|
||||
wl_array_release(&output->formats);
|
||||
|
||||
if (wl_output_get_version(output->wl_output) >= WL_OUTPUT_RELEASE_SINCE_VERSION)
|
||||
wl_output_release(output->wl_output);
|
||||
else
|
||||
|
|
@ -329,13 +277,7 @@ handle_global(void *data, struct wl_registry *registry,
|
|||
} else if (strcmp(interface, weston_capture_v1_interface.name) == 0) {
|
||||
app->capture_factory = wl_registry_bind(registry, name,
|
||||
&weston_capture_v1_interface,
|
||||
2);
|
||||
} else if (strcmp(interface, zwp_linux_dmabuf_v1_interface.name) == 0) {
|
||||
if (version < 3)
|
||||
return;
|
||||
app->dmabuf = wl_registry_bind(registry, name,
|
||||
&zwp_linux_dmabuf_v1_interface,
|
||||
3);
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -353,46 +295,15 @@ static const struct wl_registry_listener registry_listener = {
|
|||
static void
|
||||
screenshooter_output_capture(struct screenshooter_output *output)
|
||||
{
|
||||
const struct pixel_format_info *fmt_info = NULL;
|
||||
uint32_t *fmt;
|
||||
|
||||
screenshooter_buffer_destroy(output->buffer);
|
||||
|
||||
wl_array_for_each(fmt, &output->formats) {
|
||||
fmt_info = pixel_format_get_info(*fmt);
|
||||
assert(fmt_info);
|
||||
|
||||
if (fmt_info == output->app->requested_format ||
|
||||
output->app->requested_format == NULL)
|
||||
break;
|
||||
|
||||
fmt_info = NULL;
|
||||
}
|
||||
if (!fmt_info) {
|
||||
fprintf(stderr, "No supported format found\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (output->app->verbose)
|
||||
printf("Creating buffer with format %s / 0x%x and size %ux%u\n",
|
||||
fmt_info->drm_format_name, fmt_info->format,
|
||||
output->buffer_width, output->buffer_height);
|
||||
|
||||
if (output->app->buffer_type == CLIENT_BUFFER_TYPE_SHM) {
|
||||
output->buffer = screenshot_create_shm_buffer(output->app,
|
||||
output->buffer_width,
|
||||
output->buffer_height,
|
||||
fmt_info);
|
||||
} else if (output->app->buffer_type == CLIENT_BUFFER_TYPE_DMABUF) {
|
||||
output->buffer = screenshot_create_udmabuf(output->app,
|
||||
output->buffer_width,
|
||||
output->buffer_height,
|
||||
fmt_info);
|
||||
}
|
||||
output->buffer = screenshot_create_shm_buffer(output->app,
|
||||
output->buffer_width,
|
||||
output->buffer_height,
|
||||
output->fmt);
|
||||
abort_oom_if_null(output->buffer);
|
||||
|
||||
weston_capture_source_v1_capture(output->source,
|
||||
output->buffer->buf->wl_buffer);
|
||||
output->buffer->wl_buffer);
|
||||
output->app->waitcount++;
|
||||
}
|
||||
|
||||
|
|
@ -412,8 +323,6 @@ screenshot_write_png(const struct buffer_size *buff_size,
|
|||
abort_oom_if_null(shot);
|
||||
|
||||
wl_list_for_each(output, output_list, link) {
|
||||
client_buffer_util_maybe_sync_dmabuf_start(output->buffer->buf);
|
||||
|
||||
pixman_image_composite32(PIXMAN_OP_SRC,
|
||||
output->buffer->image, /* src */
|
||||
NULL, /* mask */
|
||||
|
|
@ -422,8 +331,6 @@ screenshot_write_png(const struct buffer_size *buff_size,
|
|||
0, 0, /* mask x,y */
|
||||
output->offset_x, output->offset_y, /* dst x,y */
|
||||
output->buffer_width, output->buffer_height);
|
||||
|
||||
client_buffer_util_maybe_sync_dmabuf_end(output->buffer->buf);
|
||||
}
|
||||
|
||||
surface = cairo_image_surface_create_for_data((void *)pixman_image_get_data(shot),
|
||||
|
|
@ -442,59 +349,6 @@ screenshot_write_png(const struct buffer_size *buff_size,
|
|||
pixman_image_unref(shot);
|
||||
}
|
||||
|
||||
static void
|
||||
screenshot_write_yuv(const struct buffer_size *buff_size,
|
||||
struct wl_list *output_list)
|
||||
{
|
||||
struct screenshooter_output *output;
|
||||
int i = 0;
|
||||
|
||||
wl_list_for_each(output, output_list, link) {
|
||||
struct screenshooter_buffer *buffer = output->buffer;
|
||||
char filepath[PATH_MAX];
|
||||
char filepath_prefix[100];
|
||||
int write_offset = 0;
|
||||
FILE *fp;
|
||||
|
||||
sprintf(filepath_prefix, "wayland-screenshot-output-%d-", i++);
|
||||
fp = file_create_dated(getenv("XDG_PICTURES_DIR"),
|
||||
filepath_prefix, ".yuv", filepath,
|
||||
sizeof(filepath));
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Writing yuv file for output %d failed\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
client_buffer_util_maybe_sync_dmabuf_start(buffer->buf);
|
||||
|
||||
for (unsigned int j = 0; j < pixel_format_get_plane_count(buffer->buf->fmt); j++) {
|
||||
int plane_height =
|
||||
buffer->buf->height / pixel_format_hsub(buffer->buf->fmt, j);
|
||||
|
||||
for (int k = 0; k < plane_height; k++) {
|
||||
size_t lines_written;
|
||||
|
||||
lines_written = fwrite(buffer->buf->data + write_offset,
|
||||
buffer->buf->bytes_per_line[j],
|
||||
1, fp);
|
||||
if (lines_written != 1) {
|
||||
fprintf(stderr,
|
||||
"Writing yuv file for output %d " \
|
||||
"failed during write(): %s\n",
|
||||
i, strerror(errno));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
write_offset += buffer->buf->strides[j];
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
|
||||
client_buffer_util_maybe_sync_dmabuf_end(buffer->buf);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
screenshot_set_buffer_size(struct buffer_size *buff_size,
|
||||
struct wl_list *output_list)
|
||||
|
|
@ -528,177 +382,41 @@ screenshot_set_buffer_size(struct buffer_size *buff_size,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
received_formats_for_all_outputs(struct screenshooter_app *app)
|
||||
{
|
||||
struct screenshooter_output *output;
|
||||
|
||||
wl_list_for_each(output, &app->output_list, link) {
|
||||
if (!output->formats_done)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
all_output_formats_are_yuv(struct wl_list *output_list)
|
||||
{
|
||||
struct screenshooter_output *output;
|
||||
int color_model = -1;
|
||||
|
||||
wl_list_for_each(output, output_list, link) {
|
||||
if (color_model == -1) {
|
||||
color_model = output->buffer->buf->fmt->color_model;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((int)output->buffer->buf->fmt->color_model != color_model) {
|
||||
fprintf(stderr, "Mixing of RGB and YUV output formats not supported\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
assert(color_model == (int)COLOR_MODEL_RGB ||
|
||||
color_model == (int)COLOR_MODEL_YUV);
|
||||
return color_model == COLOR_MODEL_YUV;
|
||||
}
|
||||
|
||||
static void
|
||||
print_usage_and_exit(void)
|
||||
{
|
||||
printf("usage flags:\n"
|
||||
"\t'-h,--help'"
|
||||
"\n\t\tprint this help output\n"
|
||||
"\t'-v,--verbose'"
|
||||
"\n\t\tprint additional output\n"
|
||||
"\t'-f,--format=<>'"
|
||||
"\n\t\tthe DRM format name to use without the DRM_FORMAT_ prefix, e.g. RGBA8888 or NV12\n"
|
||||
"\n\t\tIn case of YCbCr formats like NV12, instead of a single .png, the output will consist of raw .yuv files for each output."
|
||||
"\n\t\tThese files do not contain any metadata, however that can be added by converting to .y4m with a command like:"
|
||||
"\n\t\tffmpeg -s 1024x768 -r 1 -pix_fmt yuv420p -i ~/wayland-screenshot-output-0-2025-08-01_15-58-24.yuv -c:v copy screenshot.y4m\n"
|
||||
"\n\t\tNote that this may not work for all YCbCr pixel formats.\n"
|
||||
"\t'-s,--source-type=<>'"
|
||||
"\n\t\tframebuffer to use framebuffer source (default), "
|
||||
"\n\t\twriteback to use writeback source\n"
|
||||
"\t'-b,--buffer-type=<>'"
|
||||
"\n\t\tshm to use a SHM buffer (default), "
|
||||
"\n\t\tdmabuf to use a DMA buffer\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static const struct weston_enum_map source_types [] = {
|
||||
{ "framebuffer", WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER },
|
||||
{ "writeback", WESTON_CAPTURE_V1_SOURCE_WRITEBACK },
|
||||
};
|
||||
|
||||
static const struct weston_enum_map buffer_types [] = {
|
||||
{ "shm", CLIENT_BUFFER_TYPE_SHM },
|
||||
{ "dmabuf", CLIENT_BUFFER_TYPE_DMABUF },
|
||||
};
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct wl_display *display;
|
||||
struct screenshooter_output *output;
|
||||
struct screenshooter_output *tmp_output;
|
||||
struct buffer_size buff_size = {};
|
||||
struct screenshooter_app app = {};
|
||||
int c, option_index;
|
||||
|
||||
app.src_type = WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER;
|
||||
app.buffer_type = CLIENT_BUFFER_TYPE_SHM;
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
{"format", required_argument, NULL, 'f'},
|
||||
{"source-type", required_argument, NULL, 's'},
|
||||
{"buffer-type", required_argument, NULL, 'b'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hvf:s:b:",
|
||||
long_options, &option_index)) != -1) {
|
||||
const struct weston_enum_map *entry;
|
||||
|
||||
switch(c) {
|
||||
case 'v':
|
||||
app.verbose = true;
|
||||
break;
|
||||
case 'f':
|
||||
app.requested_format = pixel_format_get_info_by_drm_name(optarg);
|
||||
if (!app.requested_format) {
|
||||
fprintf(stderr, "Unknown format %s\n", optarg);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
entry = weston_enum_map_find_name(source_types,
|
||||
optarg);
|
||||
if (!entry)
|
||||
print_usage_and_exit();
|
||||
|
||||
app.src_type = entry->value;
|
||||
break;
|
||||
case 'b':
|
||||
entry = weston_enum_map_find_name(buffer_types,
|
||||
optarg);
|
||||
if (!entry)
|
||||
print_usage_and_exit();
|
||||
|
||||
app.buffer_type = entry->value;
|
||||
break;
|
||||
default:
|
||||
print_usage_and_exit();
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_init(&app.output_list);
|
||||
|
||||
app.display = wl_display_connect(NULL);
|
||||
if (app.display == NULL) {
|
||||
display = wl_display_connect(NULL);
|
||||
if (display == NULL) {
|
||||
fprintf(stderr, "failed to create display: %s\n",
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
app.registry = wl_display_get_registry(app.display);
|
||||
app.registry = wl_display_get_registry(display);
|
||||
wl_registry_add_listener(app.registry, ®istry_listener, &app);
|
||||
|
||||
/* Process wl_registry advertisements */
|
||||
wl_display_roundtrip(app.display);
|
||||
wl_display_roundtrip(display);
|
||||
|
||||
if (!app.shm) {
|
||||
fprintf(stderr, "Error: display does not support wl_shm\n");
|
||||
return -1;
|
||||
}
|
||||
if (!app.capture_factory) {
|
||||
fprintf(stderr, "Error: display does not support weston_capture_v1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(app.buffer_type == CLIENT_BUFFER_TYPE_SHM && !app.shm) {
|
||||
fprintf(stderr, "Error: display does not support wl_shm\n");
|
||||
return -1;
|
||||
}
|
||||
if (app.buffer_type == CLIENT_BUFFER_TYPE_DMABUF && !app.dmabuf) {
|
||||
fprintf(stderr, "Error: Compositor does not support zwp_linux_dmabuf_v1\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (app.verbose) {
|
||||
printf("Taking screenshot with %s source %s buffer\n",
|
||||
(app.src_type == WESTON_CAPTURE_V1_SOURCE_FRAMEBUFFER) ? "framebuffer" : "writeback",
|
||||
(app.buffer_type == CLIENT_BUFFER_TYPE_SHM) ? "shm" : "dma");
|
||||
}
|
||||
|
||||
/* Process initial events for wl_output and weston_capture_source_v1 */
|
||||
wl_display_roundtrip(app.display);
|
||||
|
||||
while (!received_formats_for_all_outputs(&app)) {
|
||||
if (app.verbose)
|
||||
printf("Waiting for compositor to send capture source data\n");
|
||||
|
||||
if (wl_display_dispatch(app.display) < 0) {
|
||||
fprintf(stderr, "Error: connection terminated\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wl_display_roundtrip(display);
|
||||
|
||||
do {
|
||||
app.retry = false;
|
||||
|
|
@ -707,7 +425,7 @@ main(int argc, char *argv[])
|
|||
screenshooter_output_capture(output);
|
||||
|
||||
while (app.waitcount > 0 && !app.failed) {
|
||||
if (wl_display_dispatch(app.display) < 0)
|
||||
if (wl_display_dispatch(display) < 0)
|
||||
app.failed = true;
|
||||
assert(app.waitcount >= 0);
|
||||
}
|
||||
|
|
@ -716,11 +434,7 @@ main(int argc, char *argv[])
|
|||
if (!app.failed) {
|
||||
if (screenshot_set_buffer_size(&buff_size, &app.output_list) < 0)
|
||||
return -1;
|
||||
|
||||
if (all_output_formats_are_yuv(&app.output_list))
|
||||
screenshot_write_yuv(&buff_size, &app.output_list);
|
||||
else
|
||||
screenshot_write_png(&buff_size, &app.output_list);
|
||||
screenshot_write_png(&buff_size, &app.output_list);
|
||||
} else {
|
||||
fprintf(stderr, "Error: screenshot or protocol failure\n");
|
||||
}
|
||||
|
|
@ -730,10 +444,8 @@ main(int argc, char *argv[])
|
|||
|
||||
weston_capture_v1_destroy(app.capture_factory);
|
||||
wl_shm_destroy(app.shm);
|
||||
if (app.dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(app.dmabuf);
|
||||
wl_registry_destroy(app.registry);
|
||||
wl_display_disconnect(app.display);
|
||||
wl_display_disconnect(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,6 +340,7 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer,
|
|||
buffer->release_fence_fd = -1;
|
||||
|
||||
if (display->modifiers_count > 0) {
|
||||
#ifdef HAVE_GBM_BO_CREATE_WITH_MODIFIERS2
|
||||
buffer->bo = gbm_bo_create_with_modifiers2(display->gbm.device,
|
||||
buffer->width,
|
||||
buffer->height,
|
||||
|
|
@ -347,6 +348,14 @@ create_dmabuf_buffer(struct display *display, struct buffer *buffer,
|
|||
display->modifiers,
|
||||
display->modifiers_count,
|
||||
GBM_BO_USE_RENDERING);
|
||||
#else
|
||||
buffer->bo = gbm_bo_create_with_modifiers(display->gbm.device,
|
||||
buffer->width,
|
||||
buffer->height,
|
||||
buffer->format,
|
||||
display->modifiers,
|
||||
display->modifiers_count);
|
||||
#endif
|
||||
if (buffer->bo)
|
||||
buffer->modifier = gbm_bo_get_modifier(buffer->bo);
|
||||
}
|
||||
|
|
@ -806,7 +815,7 @@ render(struct window *window, struct buffer *buffer)
|
|||
|
||||
glUniform1f(window->gl.offset_uniform, offset);
|
||||
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
||||
(GLfloat *) reflection.M.colmaj);
|
||||
(GLfloat *) reflection.d);
|
||||
|
||||
glClearColor(0.0,0.0, 0.0, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
@ -855,7 +864,7 @@ render_mandelbrot(struct window *window, struct buffer *buffer)
|
|||
|
||||
glUniform1f(window->gl.offset_uniform, offset);
|
||||
glUniformMatrix4fv(window->gl.reflection_uniform, 1, GL_FALSE,
|
||||
(GLfloat *) reflection.M.colmaj);
|
||||
(GLfloat *) reflection.d);
|
||||
|
||||
glClearColor(0.6, 0.6, 0.6, 1.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
|
@ -1101,12 +1110,6 @@ destroy_display(struct display *display)
|
|||
|
||||
free(display->modifiers);
|
||||
|
||||
if (display->direct_display)
|
||||
weston_direct_display_v1_destroy(display->direct_display);
|
||||
|
||||
if (display->explicit_sync)
|
||||
zwp_linux_explicit_synchronization_v1_destroy(display->explicit_sync);
|
||||
|
||||
if (display->dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy(display->dmabuf);
|
||||
|
||||
|
|
|
|||
|
|
@ -547,11 +547,18 @@ create_dmabuf_buffer(struct window *window, struct buffer *buf, uint32_t width,
|
|||
buf->format = format;
|
||||
|
||||
if (count_modifiers > 0) {
|
||||
#ifdef HAVE_GBM_BO_CREATE_WITH_MODIFIERS2
|
||||
buf->bo = gbm_bo_create_with_modifiers2(display->gbm_device,
|
||||
buf->width, buf->height,
|
||||
format, modifiers,
|
||||
count_modifiers,
|
||||
bo_flags);
|
||||
#else
|
||||
buf->bo = gbm_bo_create_with_modifiers(display->gbm_device,
|
||||
buf->width, buf->height,
|
||||
format, modifiers,
|
||||
count_modifiers);
|
||||
#endif
|
||||
if (buf->bo)
|
||||
buf->modifier = gbm_bo_get_modifier(buf->bo);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -564,6 +564,7 @@ init_gl(struct window *window)
|
|||
|
||||
glBindAttribLocation(program, window->gl.pos, "pos");
|
||||
glBindAttribLocation(program, window->gl.col, "color");
|
||||
glLinkProgram(program);
|
||||
|
||||
window->gl.rotation_uniform =
|
||||
glGetUniformLocation(program, "rotation");
|
||||
|
|
@ -939,10 +940,10 @@ redraw(struct window *window)
|
|||
angle = ((time - window->initial_frame_time) / speed_div)
|
||||
% 360 * M_PI / 180.0;
|
||||
}
|
||||
rotation.M.col[0].el[0] = cos(angle);
|
||||
rotation.M.col[0].el[2] = sin(angle);
|
||||
rotation.M.col[2].el[0] = -sin(angle);
|
||||
rotation.M.col[2].el[2] = cos(angle);
|
||||
rotation.d[0] = cos(angle);
|
||||
rotation.d[2] = sin(angle);
|
||||
rotation.d[8] = -sin(angle);
|
||||
rotation.d[10] = cos(angle);
|
||||
|
||||
switch (window->buffer_transform) {
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
|
|
@ -981,7 +982,7 @@ redraw(struct window *window)
|
|||
glViewport(0, 0, window->buffer_size.width, window->buffer_size.height);
|
||||
|
||||
glUniformMatrix4fv(window->gl.rotation_uniform, 1, GL_FALSE,
|
||||
(GLfloat *) rotation.M.colmaj);
|
||||
(GLfloat *) rotation.d);
|
||||
|
||||
if (window->opaque || window->fullscreen)
|
||||
glClearColor(0.0, 0.0, 0.0, 1);
|
||||
|
|
@ -1473,10 +1474,15 @@ main(int argc, char **argv)
|
|||
create_surface(&window);
|
||||
|
||||
/* we already have wait_for_configure set after create_surface() */
|
||||
while (running && ret != -1 && window.wait_for_configure)
|
||||
while (running && ret != -1 && window.wait_for_configure) {
|
||||
ret = wl_display_dispatch(display.display);
|
||||
|
||||
init_gl(&window);
|
||||
/* wait until xdg_surface::configure acks the new dimensions */
|
||||
if (window.wait_for_configure)
|
||||
continue;
|
||||
|
||||
init_gl(&window);
|
||||
}
|
||||
|
||||
display.cursor_surface =
|
||||
wl_compositor_create_surface(display.compositor);
|
||||
|
|
@ -1524,9 +1530,6 @@ out_no_xdg_shell:
|
|||
if (display.compositor)
|
||||
wl_compositor_destroy(display.compositor);
|
||||
|
||||
if (display.tearing_manager)
|
||||
wp_tearing_control_manager_v1_destroy(display.tearing_manager);
|
||||
|
||||
if (display.viewporter)
|
||||
wp_viewporter_destroy(display.viewporter);
|
||||
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ simple_im_key_handler(struct simple_im *keyboard,
|
|||
|
||||
if (keyboard->compose_state == state_compose) {
|
||||
uint32_t i = 0;
|
||||
const struct compose_seq *cs;
|
||||
struct compose_seq *cs;
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <sys/mman.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
|
|
@ -43,20 +42,8 @@
|
|||
#include <libweston/zalloc.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
#define FMT(fmt, bpp, r, g, b, a) { WL_SHM_FORMAT_ ## fmt, #fmt, bpp, { r, g, b, a } }
|
||||
|
||||
#define MAX_BUFFER_ALLOC 2
|
||||
|
||||
struct window;
|
||||
|
||||
struct format {
|
||||
uint32_t code;
|
||||
const char *string;
|
||||
int bpp;
|
||||
uint64_t color[4];
|
||||
};
|
||||
|
||||
struct display {
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
|
|
@ -65,10 +52,7 @@ struct display {
|
|||
struct wl_seat *seat;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct wl_shm *shm;
|
||||
const struct format *format;
|
||||
bool paint_format;
|
||||
bool has_format;
|
||||
struct window *window;
|
||||
bool has_xrgb;
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
|
|
@ -97,68 +81,6 @@ struct window {
|
|||
bool needs_update_buffer;
|
||||
};
|
||||
|
||||
static const struct format shm_formats[] = {
|
||||
/* 8 bpp formats */
|
||||
FMT(R8, 8, 0x00, 0x55, 0xaa, 0xff ),
|
||||
|
||||
/* 16 bpp formats */
|
||||
FMT(R16, 16, 0x0000, 0x5555, 0xaaaa, 0xffff ),
|
||||
FMT(GR88, 16, 0x00ff, 0xff00, 0x0000, 0xffff ),
|
||||
FMT(RG88, 16, 0xff00, 0x00ff, 0x0000, 0xffff ),
|
||||
FMT(RGB565, 16, 0xf800, 0x07e0, 0x001f, 0xffff ),
|
||||
FMT(BGR565, 16, 0x001f, 0x07e0, 0xf800, 0xffff ),
|
||||
FMT(XRGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
|
||||
FMT(ARGB4444, 16, 0xff00, 0xf0f0, 0xf00f, 0x7777 ),
|
||||
FMT(XBGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
|
||||
FMT(ABGR4444, 16, 0xf00f, 0xf0f0, 0xff00, 0x7777 ),
|
||||
FMT(RGBX4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
|
||||
FMT(RGBA4444, 16, 0xf00f, 0x0f0f, 0x00ff, 0x7777 ),
|
||||
FMT(BGRX4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
|
||||
FMT(BGRA4444, 16, 0x00ff, 0x0f0f, 0xf00f, 0x7777 ),
|
||||
FMT(XRGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
|
||||
FMT(ARGB1555, 16, 0xfc00, 0x83e1, 0x801f, 0x0000 ),
|
||||
FMT(XBGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
|
||||
FMT(ABGR1555, 16, 0x801f, 0x83e1, 0xfc00, 0x0000 ),
|
||||
FMT(RGBX5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
|
||||
FMT(RGBA5551, 16, 0xf801, 0x07c1, 0x003f, 0x0000 ),
|
||||
FMT(BGRX5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
|
||||
FMT(BGRA5551, 16, 0x003f, 0x07c1, 0xf801, 0x0000 ),
|
||||
|
||||
/* 24 bpp formats */
|
||||
FMT(RGB888, 24, 0xff0000, 0x00ff00, 0x0000ff, 0xffffff ),
|
||||
FMT(BGR888, 24, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff ),
|
||||
|
||||
/* 32 bpp formats */
|
||||
FMT(GR1616, 32, 0x0000ffff, 0xffff0000, 0x00000000, 0xffffffff ),
|
||||
FMT(RG1616, 32, 0xffff0000, 0x0000ffff, 0x00000000, 0xffffffff ),
|
||||
FMT(XRGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
|
||||
FMT(ARGB8888, 32, 0xffff0000, 0xff00ff00, 0xff0000ff, 0x7f7f7f7f ),
|
||||
FMT(XBGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
|
||||
FMT(ABGR8888, 32, 0xff0000ff, 0xff00ff00, 0xffff0000, 0x7f7f7f7f ),
|
||||
FMT(RGBX8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
|
||||
FMT(RGBA8888, 32, 0xff0000ff, 0x00ff00ff, 0x0000ffff, 0x7f7f7f7f ),
|
||||
FMT(BGRX8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
|
||||
FMT(BGRA8888, 32, 0x0000ffff, 0x00ff00ff, 0xff0000ff, 0x7f7f7f7f ),
|
||||
FMT(XRGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
|
||||
FMT(ARGB2101010, 32, 0xfff00000, 0xc00ffc00, 0xc00003ff, 0x5ff7fdff ),
|
||||
FMT(XBGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
|
||||
FMT(ABGR2101010, 32, 0xc00003ff, 0xc00ffc00, 0xfff00000, 0x5ff7fdff ),
|
||||
FMT(RGBX1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
|
||||
FMT(RGBA1010102, 32, 0xffc00003, 0x003ff003, 0x00000fff, 0x7fdff7fd ),
|
||||
FMT(BGRX1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
|
||||
FMT(BGRA1010102, 32, 0x00000fff, 0x003ff003, 0xffc00003, 0x7fdff7fd ),
|
||||
|
||||
/* 64 bpp formats */
|
||||
FMT(XRGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
|
||||
FMT(ARGB16161616, 64, 0xffffffff00000000, 0xffff0000ffff0000, 0xffff00000000ffff, 0x7fff7fff7fff7fff ),
|
||||
FMT(XBGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
|
||||
FMT(ABGR16161616, 64, 0xffff00000000ffff, 0xffff0000ffff0000, 0xffffffff00000000, 0x7fff7fff7fff7fff ),
|
||||
FMT(XRGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
|
||||
FMT(ARGB16161616F, 64, 0x3c003c0000000000, 0x3c0000003c000000, 0x3c00000000003c00, 0x3800380038003800 ),
|
||||
FMT(XBGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
|
||||
FMT(ABGR16161616F, 64, 0x3c00000000003c00, 0x3c0000003c000000, 0x3c003c0000000000, 0x3800380038003800 ),
|
||||
};
|
||||
|
||||
static int running = 1;
|
||||
|
||||
static void
|
||||
|
|
@ -229,8 +151,7 @@ static const struct wl_buffer_listener buffer_listener = {
|
|||
};
|
||||
|
||||
static int
|
||||
create_shm_buffer(struct window *window, struct buffer *buffer,
|
||||
const struct format *format)
|
||||
create_shm_buffer(struct window *window, struct buffer *buffer, uint32_t format)
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
int fd, size, stride;
|
||||
|
|
@ -240,7 +161,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer,
|
|||
|
||||
width = window->width;
|
||||
height = window->height;
|
||||
stride = width * (format->bpp / 8);
|
||||
stride = width * 4;
|
||||
size = stride * height;
|
||||
display = window->display;
|
||||
|
||||
|
|
@ -261,7 +182,7 @@ create_shm_buffer(struct window *window, struct buffer *buffer,
|
|||
pool = wl_shm_create_pool(display->shm, fd, size);
|
||||
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
||||
width, height,
|
||||
stride, format->code);
|
||||
stride, format);
|
||||
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
||||
wl_shm_pool_destroy(pool);
|
||||
close(fd);
|
||||
|
|
@ -298,16 +219,8 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
|||
uint32_t serial, uint32_t time, uint32_t key,
|
||||
uint32_t state)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
if (key == KEY_F11 && state) {
|
||||
if (d->window->fullscreen)
|
||||
xdg_toplevel_unset_fullscreen(d->window->xdg_toplevel);
|
||||
else
|
||||
xdg_toplevel_set_fullscreen(d->window->xdg_toplevel, NULL);
|
||||
} else if (key == KEY_ESC && state) {
|
||||
if (key == KEY_ESC && state)
|
||||
running = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -503,16 +416,14 @@ window_next_buffer(struct window *window)
|
|||
return NULL;
|
||||
|
||||
if (!buffer->buffer) {
|
||||
ret = create_shm_buffer(window, buffer,
|
||||
window->display->format);
|
||||
ret = create_shm_buffer(window, buffer, WL_SHM_FORMAT_XRGB8888);
|
||||
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
/* paint the padding */
|
||||
memset(buffer->shm_data, 0xff,
|
||||
window->width * window->height *
|
||||
(window->display->format->bpp / 8));
|
||||
window->width * window->height * 4);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
|
@ -564,122 +475,6 @@ paint_pixels(void *image, int padding, int width, int height, uint32_t time)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
paint_format(void *image, const struct format *format, int width, int height)
|
||||
{
|
||||
uint64_t *img64 = (uint64_t*) image;
|
||||
uint32_t *img32 = (uint32_t*) image;
|
||||
uint16_t *img16 = (uint16_t*) image;
|
||||
uint8_t *img8 = (uint8_t*) image;
|
||||
uint64_t color;
|
||||
int i, j;
|
||||
|
||||
#define GET_COLOR(y) \
|
||||
(y < (1 * (height / 4))) ? format->color[0] : \
|
||||
(y < (2 * (height / 4))) ? format->color[1] : \
|
||||
(y < (3 * (height / 4))) ? format->color[2] : \
|
||||
format->color[3]
|
||||
|
||||
switch (format->code) {
|
||||
case WL_SHM_FORMAT_R8:
|
||||
for (i = 0; i < height; i++) {
|
||||
color = GET_COLOR(i);
|
||||
for (j = 0; j < width; j++)
|
||||
img8[i * width + j] = color;
|
||||
}
|
||||
break;
|
||||
|
||||
case WL_SHM_FORMAT_R16:
|
||||
case WL_SHM_FORMAT_GR88:
|
||||
case WL_SHM_FORMAT_RG88:
|
||||
case WL_SHM_FORMAT_RGB565:
|
||||
case WL_SHM_FORMAT_BGR565:
|
||||
case WL_SHM_FORMAT_XRGB4444:
|
||||
case WL_SHM_FORMAT_ARGB4444:
|
||||
case WL_SHM_FORMAT_XBGR4444:
|
||||
case WL_SHM_FORMAT_ABGR4444:
|
||||
case WL_SHM_FORMAT_RGBX4444:
|
||||
case WL_SHM_FORMAT_RGBA4444:
|
||||
case WL_SHM_FORMAT_BGRX4444:
|
||||
case WL_SHM_FORMAT_BGRA4444:
|
||||
case WL_SHM_FORMAT_XRGB1555:
|
||||
case WL_SHM_FORMAT_ARGB1555:
|
||||
case WL_SHM_FORMAT_XBGR1555:
|
||||
case WL_SHM_FORMAT_ABGR1555:
|
||||
case WL_SHM_FORMAT_RGBX5551:
|
||||
case WL_SHM_FORMAT_RGBA5551:
|
||||
case WL_SHM_FORMAT_BGRX5551:
|
||||
case WL_SHM_FORMAT_BGRA5551:
|
||||
for (i = 0; i < height; i++) {
|
||||
color = GET_COLOR(i);
|
||||
for (j = 0; j < width; j++)
|
||||
img16[i * width + j] = color;
|
||||
}
|
||||
break;
|
||||
|
||||
case WL_SHM_FORMAT_RGB888:
|
||||
case WL_SHM_FORMAT_BGR888:
|
||||
for (i = 0; i < height; i++) {
|
||||
color = GET_COLOR(i);
|
||||
for (j = 0; j < width; j++) {
|
||||
img8[(i * width + j) * 3 + 0] =
|
||||
(color >> 0) & 0xff;
|
||||
img8[(i * width + j) * 3 + 1] =
|
||||
(color >> 8) & 0xff;
|
||||
img8[(i * width + j) * 3 + 2] =
|
||||
(color >> 16) & 0xff;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WL_SHM_FORMAT_GR1616:
|
||||
case WL_SHM_FORMAT_RG1616:
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
case WL_SHM_FORMAT_XBGR8888:
|
||||
case WL_SHM_FORMAT_ABGR8888:
|
||||
case WL_SHM_FORMAT_RGBX8888:
|
||||
case WL_SHM_FORMAT_RGBA8888:
|
||||
case WL_SHM_FORMAT_BGRX8888:
|
||||
case WL_SHM_FORMAT_BGRA8888:
|
||||
case WL_SHM_FORMAT_XRGB2101010:
|
||||
case WL_SHM_FORMAT_ARGB2101010:
|
||||
case WL_SHM_FORMAT_XBGR2101010:
|
||||
case WL_SHM_FORMAT_ABGR2101010:
|
||||
case WL_SHM_FORMAT_RGBX1010102:
|
||||
case WL_SHM_FORMAT_RGBA1010102:
|
||||
case WL_SHM_FORMAT_BGRX1010102:
|
||||
case WL_SHM_FORMAT_BGRA1010102:
|
||||
for (i = 0; i < height; i++) {
|
||||
color = GET_COLOR(i);
|
||||
for (j = 0; j < width; j++)
|
||||
img32[i * width + j] = color;
|
||||
}
|
||||
break;
|
||||
|
||||
case WL_SHM_FORMAT_XRGB16161616:
|
||||
case WL_SHM_FORMAT_ARGB16161616:
|
||||
case WL_SHM_FORMAT_XBGR16161616:
|
||||
case WL_SHM_FORMAT_ABGR16161616:
|
||||
case WL_SHM_FORMAT_XRGB16161616F:
|
||||
case WL_SHM_FORMAT_ARGB16161616F:
|
||||
case WL_SHM_FORMAT_XBGR16161616F:
|
||||
case WL_SHM_FORMAT_ABGR16161616F:
|
||||
for (i = 0; i < height; i++) {
|
||||
color = GET_COLOR(i);
|
||||
for (j = 0; j < width; j++)
|
||||
img64[i * width + j] = color;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
};
|
||||
|
||||
#undef GET_COLOR
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener frame_listener;
|
||||
|
||||
static void
|
||||
|
|
@ -698,12 +493,7 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
|
|||
abort();
|
||||
}
|
||||
|
||||
if (window->display->paint_format)
|
||||
paint_format(buffer->shm_data, window->display->format,
|
||||
window->width, window->height);
|
||||
else
|
||||
paint_pixels(buffer->shm_data, 20, window->width,
|
||||
window->height, time);
|
||||
paint_pixels(buffer->shm_data, 20, window->width, window->height, time);
|
||||
|
||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||
wl_surface_damage(window->surface,
|
||||
|
|
@ -727,8 +517,8 @@ shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
|||
{
|
||||
struct display *d = data;
|
||||
|
||||
if (format == d->format->code)
|
||||
d->has_format = true;
|
||||
if (format == WL_SHM_FORMAT_XRGB8888)
|
||||
d->has_xrgb = true;
|
||||
}
|
||||
|
||||
struct wl_shm_listener shm_listener = {
|
||||
|
|
@ -782,7 +572,7 @@ static const struct wl_registry_listener registry_listener = {
|
|||
};
|
||||
|
||||
static struct display *
|
||||
create_display(const struct format *format, bool paint_format)
|
||||
create_display(void)
|
||||
{
|
||||
struct display *display;
|
||||
|
||||
|
|
@ -794,9 +584,7 @@ create_display(const struct format *format, bool paint_format)
|
|||
display->display = wl_display_connect(NULL);
|
||||
assert(display->display);
|
||||
|
||||
display->format = format;
|
||||
display->paint_format = paint_format;
|
||||
display->has_format= false;
|
||||
display->has_xrgb = false;
|
||||
display->registry = wl_display_get_registry(display->display);
|
||||
wl_registry_add_listener(display->registry,
|
||||
®istry_listener, display);
|
||||
|
|
@ -848,9 +636,8 @@ create_display(const struct format *format, bool paint_format)
|
|||
* technique.
|
||||
*/
|
||||
|
||||
if (!display->has_format) {
|
||||
fprintf(stderr, "Format '%s' not supported by compositor.\n",
|
||||
format->string);
|
||||
if (!display->has_xrgb) {
|
||||
fprintf(stderr, "WL_SHM_FORMAT_XRGB32 not available\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -881,86 +668,19 @@ signal_int(int signum)
|
|||
running = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *program)
|
||||
{
|
||||
fprintf(stdout,
|
||||
"Usage: %s [OPTIONS]\n"
|
||||
"\n"
|
||||
"Draw pixels into shared memory buffers using wl_shm\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help Show this help\n"
|
||||
" -F, --format <format> Test format (see list below)\n"
|
||||
"\n"
|
||||
"RGB formats:\n"
|
||||
" - 8 bpp: r8.\n"
|
||||
"\n"
|
||||
" - 16 bpp: r16, gr88, rg88, rgb565, bgr565, xrgb4444, argb4444, xbgr4444,\n"
|
||||
" abgr4444, rgbx4444, rgba4444, bgrx4444, bgra4444, xrgb1555,\n"
|
||||
" argb1555, xbgr1555, abgr1555, rgbx5551, rgba5551, bgrx5551,\n"
|
||||
" bgra5551.\n"
|
||||
"\n"
|
||||
" - 24 bpp: rgb888, bgr888.\n"
|
||||
"\n"
|
||||
" - 32 bpp: gr1616, rg1616, xrgb8888, argb8888, xbgr8888, abgr8888, rgbx8888,\n"
|
||||
" rgba8888, bgrx8888, bgra8888, xrgb2101010, argb2101010, xbgr2101010,\n"
|
||||
" abgr2101010, rgbx1010102, rgba1010102, bgrx1010102, bgra1010102.\n"
|
||||
"\n"
|
||||
" - 64 bpp: xrgb16161616, argb16161616, xbgr16161616, abgr16161616,\n"
|
||||
" xrgb16161616f, argb16161616f, xbgr16161616f, abgr16161616f.\n",
|
||||
program);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sigaction sigint;
|
||||
struct display *display;
|
||||
struct window *window;
|
||||
const struct format *format = NULL;
|
||||
bool paint_format = false;
|
||||
const char *value;
|
||||
int ret = 0, i, j;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-h") ||
|
||||
!strcmp(argv[i], "--help")) {
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
} else if (!strcmp(argv[i], "-F") ||
|
||||
!strcmp(argv[i], "--format")) {
|
||||
value = ++i == argc ? "" : argv[i];
|
||||
for (j = 0; j < (int) ARRAY_SIZE(shm_formats); j++) {
|
||||
if (!strcasecmp(shm_formats[j].string, value)) {
|
||||
format = &shm_formats[j];
|
||||
paint_format = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!format) {
|
||||
fprintf(stderr, "Format '%s' not supported by "
|
||||
"client.\n", value);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!format)
|
||||
for (i = 0; i < (int) ARRAY_SIZE(shm_formats); i++)
|
||||
if (shm_formats[i].code == WL_SHM_FORMAT_XRGB8888)
|
||||
format = &shm_formats[i];
|
||||
assert(format);
|
||||
|
||||
display = create_display(format, paint_format);
|
||||
window = create_window(display, 256, 256);
|
||||
display = create_display();
|
||||
window = create_window(display, 250, 250);
|
||||
if (!window)
|
||||
return 1;
|
||||
|
||||
display->window = window;
|
||||
sigint.sa_handler = signal_int;
|
||||
sigemptyset(&sigint.sa_mask);
|
||||
sigint.sa_flags = SA_RESETHAND;
|
||||
|
|
|
|||
|
|
@ -1,880 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2011 Benjamin Franzke
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include "shared/os-compatibility.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/zalloc.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#include "commit-timing-v1-client-protocol.h"
|
||||
#include "fifo-v1-client-protocol.h"
|
||||
#include "presentation-time-client-protocol.h"
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define MAX_BUFFER_ALLOC 1000
|
||||
|
||||
struct display {
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct xdg_wm_base *wm_base;
|
||||
struct wl_seat *seat;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct wl_shm *shm;
|
||||
struct wp_commit_timing_manager_v1 *commit_timing_manager;
|
||||
struct wp_fifo_manager_v1 *fifo_manager;
|
||||
struct wp_presentation *presentation;
|
||||
bool have_clock_id;
|
||||
clockid_t presentation_clock_id;
|
||||
int64_t first_frame_time;
|
||||
int64_t refresh_nsec;
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
struct window *window;
|
||||
struct wl_buffer *buffer;
|
||||
void *shm_data;
|
||||
int busy;
|
||||
int width, height;
|
||||
size_t size; /* width * 4 * height */
|
||||
struct wl_list buffer_link; /** window::buffer_list */
|
||||
};
|
||||
|
||||
struct window {
|
||||
struct display *display;
|
||||
int width, height;
|
||||
int init_width, init_height;
|
||||
struct wl_surface *surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct wl_list buffer_list;
|
||||
struct wp_fifo_v1 *fifo;
|
||||
struct wp_commit_timer_v1 *commit_timer;
|
||||
bool wait_for_configure;
|
||||
bool maximized;
|
||||
bool fullscreen;
|
||||
bool needs_update_buffer;
|
||||
};
|
||||
|
||||
struct feedback {
|
||||
struct wp_presentation_feedback *fb;
|
||||
struct window *window;
|
||||
int64_t target_time;
|
||||
bool final;
|
||||
};
|
||||
|
||||
static int running = 1;
|
||||
|
||||
static void
|
||||
draw_for_time(void *data, int64_t time, bool wait_fifo);
|
||||
|
||||
static void
|
||||
finish_run(struct window *window);
|
||||
|
||||
static struct buffer *
|
||||
alloc_buffer(struct window *window, int width, int height)
|
||||
{
|
||||
struct buffer *buffer = calloc(1, sizeof(*buffer));
|
||||
|
||||
buffer->width = width;
|
||||
buffer->height = height;
|
||||
wl_list_insert(&window->buffer_list, &buffer->buffer_link);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_buffer(struct buffer *buffer)
|
||||
{
|
||||
if (buffer->buffer)
|
||||
wl_buffer_destroy(buffer->buffer);
|
||||
|
||||
munmap(buffer->shm_data, buffer->size);
|
||||
wl_list_remove(&buffer->buffer_link);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static struct buffer *
|
||||
pick_free_buffer(struct window *window)
|
||||
{
|
||||
struct buffer *b;
|
||||
struct buffer *buffer = NULL;
|
||||
|
||||
wl_list_for_each(b, &window->buffer_list, buffer_link) {
|
||||
if (!b->busy) {
|
||||
buffer = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
prune_old_released_buffers(struct window *window)
|
||||
{
|
||||
struct buffer *b, *b_next;
|
||||
|
||||
wl_list_for_each_safe(b, b_next,
|
||||
&window->buffer_list, buffer_link) {
|
||||
if (!b->busy && (b->width != window->width ||
|
||||
b->height != window->height))
|
||||
destroy_buffer(b);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
buffer_release(void *data, struct wl_buffer *buffer)
|
||||
{
|
||||
struct buffer *mybuf = data;
|
||||
|
||||
mybuf->busy = 0;
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
||||
static int
|
||||
create_shm_buffer(struct window *window, struct buffer *buffer)
|
||||
{
|
||||
struct wl_shm_pool *pool;
|
||||
int fd, size, stride;
|
||||
void *data;
|
||||
int width, height;
|
||||
struct display *display;
|
||||
|
||||
width = window->width;
|
||||
height = window->height;
|
||||
stride = width * 4;
|
||||
size = stride * height;
|
||||
display = window->display;
|
||||
|
||||
fd = os_create_anonymous_file(size);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
|
||||
size, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
fprintf(stderr, "mmap failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pool = wl_shm_create_pool(display->shm, fd, size);
|
||||
buffer->buffer = wl_shm_pool_create_buffer(pool, 0,
|
||||
width, height,
|
||||
stride,
|
||||
WL_SHM_FORMAT_XRGB8888);
|
||||
wl_buffer_add_listener(buffer->buffer, &buffer_listener, buffer);
|
||||
wl_shm_pool_destroy(pool);
|
||||
close(fd);
|
||||
|
||||
buffer->size = size;
|
||||
buffer->shm_data = data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t format, int fd, uint32_t size)
|
||||
{
|
||||
/* Just so we don’t leak the keymap fd */
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t serial, struct wl_surface *surface,
|
||||
struct wl_array *keys)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t serial, struct wl_surface *surface)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t serial, uint32_t time, uint32_t key,
|
||||
uint32_t state)
|
||||
{
|
||||
if (key == KEY_ESC && state)
|
||||
running = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t serial, uint32_t mods_depressed,
|
||||
uint32_t mods_latched, uint32_t mods_locked,
|
||||
uint32_t group)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_keyboard_listener keyboard_listener = {
|
||||
keyboard_handle_keymap,
|
||||
keyboard_handle_enter,
|
||||
keyboard_handle_leave,
|
||||
keyboard_handle_key,
|
||||
keyboard_handle_modifiers,
|
||||
};
|
||||
|
||||
static void
|
||||
seat_handle_capabilities(void *data, struct wl_seat *seat,
|
||||
enum wl_seat_capability caps)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !d->keyboard) {
|
||||
d->keyboard = wl_seat_get_keyboard(seat);
|
||||
wl_keyboard_add_listener(d->keyboard, &keyboard_listener, d);
|
||||
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && d->keyboard) {
|
||||
wl_keyboard_destroy(d->keyboard);
|
||||
d->keyboard = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_seat_listener seat_listener = {
|
||||
seat_handle_capabilities,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_xdg_surface_configure(void *data, struct xdg_surface *surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
struct window *window = data;
|
||||
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
|
||||
if (window->wait_for_configure) {
|
||||
draw_for_time(window, 0, false);
|
||||
window->wait_for_configure = false;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
handle_xdg_surface_configure,
|
||||
};
|
||||
|
||||
static void
|
||||
handle_xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
|
||||
int32_t width, int32_t height,
|
||||
struct wl_array *states)
|
||||
{
|
||||
struct window *window = data;
|
||||
uint32_t *p;
|
||||
|
||||
window->fullscreen = false;
|
||||
window->maximized = false;
|
||||
|
||||
wl_array_for_each(p, states) {
|
||||
uint32_t state = *p;
|
||||
switch (state) {
|
||||
case XDG_TOPLEVEL_STATE_FULLSCREEN:
|
||||
window->fullscreen = true;
|
||||
break;
|
||||
case XDG_TOPLEVEL_STATE_MAXIMIZED:
|
||||
window->maximized = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0) {
|
||||
if (!window->fullscreen && !window->maximized) {
|
||||
window->init_width = width;
|
||||
window->init_height = height;
|
||||
}
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
} else if (!window->fullscreen && !window->maximized) {
|
||||
window->width = window->init_width;
|
||||
window->height = window->init_height;
|
||||
}
|
||||
|
||||
window->needs_update_buffer = true;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel)
|
||||
{
|
||||
running = 0;
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
|
||||
handle_xdg_toplevel_configure,
|
||||
handle_xdg_toplevel_close,
|
||||
};
|
||||
|
||||
static struct window *
|
||||
create_window(struct display *display, int width, int height)
|
||||
{
|
||||
struct window *window;
|
||||
int i;
|
||||
|
||||
window = zalloc(sizeof *window);
|
||||
if (!window)
|
||||
return NULL;
|
||||
|
||||
window->display = display;
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
window->init_width = width;
|
||||
window->init_height = height;
|
||||
window->surface = wl_compositor_create_surface(display->compositor);
|
||||
window->fifo = wp_fifo_manager_v1_get_fifo(display->fifo_manager,
|
||||
window->surface);
|
||||
window->commit_timer = wp_commit_timing_manager_v1_get_timer(display->commit_timing_manager,
|
||||
window->surface);
|
||||
window->needs_update_buffer = false;
|
||||
wl_list_init(&window->buffer_list);
|
||||
|
||||
assert(display->wm_base);
|
||||
|
||||
window->xdg_surface =
|
||||
xdg_wm_base_get_xdg_surface(display->wm_base,
|
||||
window->surface);
|
||||
assert(window->xdg_surface);
|
||||
xdg_surface_add_listener(window->xdg_surface,
|
||||
&xdg_surface_listener, window);
|
||||
|
||||
window->xdg_toplevel =
|
||||
xdg_surface_get_toplevel(window->xdg_surface);
|
||||
assert(window->xdg_toplevel);
|
||||
xdg_toplevel_add_listener(window->xdg_toplevel,
|
||||
&xdg_toplevel_listener, window);
|
||||
|
||||
xdg_toplevel_set_title(window->xdg_toplevel, "simple-timing");
|
||||
xdg_toplevel_set_app_id(window->xdg_toplevel,
|
||||
"org.freedesktop.weston.simple-timing");
|
||||
|
||||
wl_surface_commit(window->surface);
|
||||
window->wait_for_configure = true;
|
||||
|
||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
||||
alloc_buffer(window, window->width, window->height);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_window(struct window *window)
|
||||
{
|
||||
struct buffer *buffer, *buffer_next;
|
||||
|
||||
wl_list_for_each_safe(buffer, buffer_next,
|
||||
&window->buffer_list, buffer_link)
|
||||
destroy_buffer(buffer);
|
||||
|
||||
if (window->xdg_toplevel)
|
||||
xdg_toplevel_destroy(window->xdg_toplevel);
|
||||
if (window->xdg_surface)
|
||||
xdg_surface_destroy(window->xdg_surface);
|
||||
wl_surface_destroy(window->surface);
|
||||
|
||||
if (window->fifo)
|
||||
wp_fifo_v1_destroy(window->fifo);
|
||||
|
||||
if (window->commit_timer)
|
||||
wp_commit_timer_v1_destroy(window->commit_timer);
|
||||
|
||||
free(window);
|
||||
}
|
||||
|
||||
static struct buffer *
|
||||
window_next_buffer(struct window *window)
|
||||
{
|
||||
struct buffer *buffer = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (window->needs_update_buffer) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_BUFFER_ALLOC; i++)
|
||||
alloc_buffer(window, window->width, window->height);
|
||||
|
||||
window->needs_update_buffer = false;
|
||||
}
|
||||
|
||||
buffer = pick_free_buffer(window);
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
if (!buffer->buffer) {
|
||||
ret = create_shm_buffer(window, buffer);
|
||||
|
||||
if (ret < 0)
|
||||
return NULL;
|
||||
|
||||
/* paint the padding */
|
||||
memset(buffer->shm_data, 0xff,
|
||||
window->width * window->height * 4);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
paint_pixels(void *image, int width, int height, uint32_t time)
|
||||
{
|
||||
const int halfh = height / 2;
|
||||
const int halfw = width / 2;
|
||||
int ir, or;
|
||||
uint32_t *pixel = image;
|
||||
int y;
|
||||
|
||||
/* squared radii thresholds */
|
||||
or = (halfw < halfh ? halfw : halfh) - 8;
|
||||
ir = or - 32;
|
||||
or *= or;
|
||||
ir *= ir;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
int x;
|
||||
int y2 = (y - halfh) * (y - halfh);
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
uint32_t v;
|
||||
|
||||
/* squared distance from center */
|
||||
int r2 = (x - halfw) * (x - halfw) + y2;
|
||||
|
||||
if (r2 < ir)
|
||||
v = (r2 / 32 + time / 64) * 0x0080401;
|
||||
else if (r2 < or)
|
||||
v = (y + time / 32) * 0x0080401;
|
||||
else
|
||||
v = (x + time / 16) * 0x0080401;
|
||||
v &= 0x00ffffff;
|
||||
|
||||
/* cross if compositor uses X from XRGB as alpha */
|
||||
if (abs(x - y) > 6 && abs(x + y - height) > 6)
|
||||
v |= 0xff000000;
|
||||
|
||||
*pixel++ = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
queue_some_frames(struct window *window)
|
||||
{
|
||||
struct display *display = window->display;
|
||||
int64_t target_nsec;
|
||||
int i;
|
||||
|
||||
assert(display->first_frame_time);
|
||||
|
||||
/* Round off error will cause us problems if we don't
|
||||
* reduce this a bit, because we could end up rounding
|
||||
* to either side of a refresh.
|
||||
*/
|
||||
target_nsec = display->first_frame_time - 100000;
|
||||
|
||||
for (i = 0; i < 60; i++) {
|
||||
target_nsec += display->refresh_nsec * 2;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < 30; i++) {
|
||||
target_nsec += display->refresh_nsec * 4;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
target_nsec += display->refresh_nsec * 10;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
target_nsec += display->refresh_nsec * 100;
|
||||
draw_for_time(window, target_nsec, false);
|
||||
}
|
||||
|
||||
finish_run(window);
|
||||
}
|
||||
|
||||
static void
|
||||
feedback_sync_output(void *data,
|
||||
struct wp_presentation_feedback *presentation_feedback,
|
||||
struct wl_output *output)
|
||||
{
|
||||
/* Just don't care */
|
||||
}
|
||||
|
||||
static void
|
||||
feedback_presented(void *data,
|
||||
struct wp_presentation_feedback *presentation_feedback,
|
||||
uint32_t tv_sec_hi,
|
||||
uint32_t tv_sec_lo,
|
||||
uint32_t tv_nsec,
|
||||
uint32_t refresh_nsec,
|
||||
uint32_t seq_hi,
|
||||
uint32_t seq_lo,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct feedback *feedback = data;
|
||||
struct window *window = feedback->window;
|
||||
struct display *display = window->display;
|
||||
struct timespec pres_ts = {
|
||||
.tv_sec = ((int64_t)tv_sec_hi << 32) + tv_sec_lo,
|
||||
.tv_nsec = tv_nsec,
|
||||
};
|
||||
int64_t ntime = timespec_to_nsec(&pres_ts);
|
||||
double delay;
|
||||
|
||||
if (feedback->final) {
|
||||
running = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!feedback->target_time) {
|
||||
display->first_frame_time = ntime;
|
||||
display->refresh_nsec = refresh_nsec;
|
||||
queue_some_frames(window);
|
||||
goto out;
|
||||
}
|
||||
|
||||
delay = (ntime - feedback->target_time) / 1000000.0;
|
||||
|
||||
printf("%fms away from intended time\n", delay);
|
||||
if (fabs(delay) > display->refresh_nsec / 1000000)
|
||||
printf("Warning: we missed the intended target display cycle.\n");
|
||||
|
||||
out:
|
||||
wp_presentation_feedback_destroy(feedback->fb);
|
||||
free(feedback);
|
||||
}
|
||||
|
||||
static void
|
||||
feedback_discarded(void *data,
|
||||
struct wp_presentation_feedback *presentation_feedback)
|
||||
{
|
||||
struct feedback *feedback = data;
|
||||
|
||||
printf("Warning: a frame was discarded\n");
|
||||
|
||||
if (feedback->final)
|
||||
running = 0;
|
||||
|
||||
wp_presentation_feedback_destroy(feedback->fb);
|
||||
free(feedback);
|
||||
}
|
||||
|
||||
static const struct wp_presentation_feedback_listener feedback_listener = {
|
||||
feedback_sync_output,
|
||||
feedback_presented,
|
||||
feedback_discarded,
|
||||
};
|
||||
|
||||
static void
|
||||
finish_run(struct window *window)
|
||||
{
|
||||
struct display *display = window->display;
|
||||
struct feedback *feedback;
|
||||
struct buffer *buffer;
|
||||
|
||||
feedback = xzalloc(sizeof *feedback);
|
||||
feedback->window = window;
|
||||
feedback->final = true;
|
||||
feedback->target_time = 0;
|
||||
|
||||
buffer = window_next_buffer(window);
|
||||
assert(buffer);
|
||||
|
||||
paint_pixels(buffer->shm_data, window->width,
|
||||
window->height, 1);
|
||||
|
||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||
|
||||
feedback->fb = wp_presentation_feedback(display->presentation,
|
||||
window->surface);
|
||||
wp_presentation_feedback_add_listener(feedback->fb,
|
||||
&feedback_listener, feedback);
|
||||
|
||||
wp_fifo_v1_wait_barrier(window->fifo);
|
||||
wl_surface_commit(window->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_for_time(void *data, int64_t time, bool wait_fifo)
|
||||
{
|
||||
struct window *window = data;
|
||||
struct display *display = window->display;
|
||||
struct buffer *buffer;
|
||||
struct feedback *feedback;
|
||||
|
||||
assert(display->have_clock_id);
|
||||
|
||||
prune_old_released_buffers(window);
|
||||
|
||||
buffer = window_next_buffer(window);
|
||||
assert(buffer);
|
||||
|
||||
paint_pixels(buffer->shm_data, window->width,
|
||||
window->height, time / 1000000);
|
||||
|
||||
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
|
||||
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
|
||||
|
||||
feedback = xzalloc(sizeof *feedback);
|
||||
feedback->window = window;
|
||||
|
||||
feedback->fb = wp_presentation_feedback(display->presentation,
|
||||
window->surface);
|
||||
wp_presentation_feedback_add_listener(feedback->fb,
|
||||
&feedback_listener, feedback);
|
||||
|
||||
feedback->target_time = time;
|
||||
if (time) {
|
||||
struct timespec target;
|
||||
|
||||
timespec_from_nsec(&target, time);
|
||||
wp_commit_timer_v1_set_timestamp(window->commit_timer,
|
||||
(int64_t)target.tv_sec >> 32,
|
||||
target.tv_sec,
|
||||
target.tv_nsec);
|
||||
}
|
||||
wp_fifo_v1_set_barrier(window->fifo);
|
||||
wl_surface_commit(window->surface);
|
||||
buffer->busy = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
xdg_wm_base_ping(void *data, struct xdg_wm_base *shell, uint32_t serial)
|
||||
{
|
||||
xdg_wm_base_pong(shell, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
|
||||
xdg_wm_base_ping,
|
||||
};
|
||||
|
||||
static void
|
||||
presentation_handle_clock_id(void *data,
|
||||
struct wp_presentation *wp_presentation,
|
||||
uint32_t clock_id)
|
||||
{
|
||||
struct display *display = data;
|
||||
|
||||
display->presentation_clock_id = clock_id;
|
||||
display->have_clock_id = true;
|
||||
}
|
||||
|
||||
static const struct wp_presentation_listener presentation_listener = {
|
||||
presentation_handle_clock_id,
|
||||
};
|
||||
|
||||
static void
|
||||
registry_handle_global(void *data, struct wl_registry *registry,
|
||||
uint32_t id, const char *interface, uint32_t version)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
d->compositor =
|
||||
wl_registry_bind(registry,
|
||||
id, &wl_compositor_interface, 1);
|
||||
} else if (strcmp(interface, "xdg_wm_base") == 0) {
|
||||
d->wm_base = wl_registry_bind(registry,
|
||||
id, &xdg_wm_base_interface, 1);
|
||||
xdg_wm_base_add_listener(d->wm_base, &xdg_wm_base_listener, d);
|
||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||
d->seat = wl_registry_bind(registry, id,
|
||||
&wl_seat_interface, 1);
|
||||
wl_seat_add_listener(d->seat, &seat_listener, d);
|
||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||
d->shm = wl_registry_bind(registry,
|
||||
id, &wl_shm_interface, 1);
|
||||
} else if (strcmp(interface, wp_commit_timing_manager_v1_interface.name) == 0) {
|
||||
d->commit_timing_manager = wl_registry_bind(registry, id,
|
||||
&wp_commit_timing_manager_v1_interface,
|
||||
1);
|
||||
} else if (strcmp(interface, wp_fifo_manager_v1_interface.name) == 0) {
|
||||
d->fifo_manager = wl_registry_bind(registry, id,
|
||||
&wp_fifo_manager_v1_interface,
|
||||
1);
|
||||
} else if (strcmp(interface, wp_presentation_interface.name) == 0) {
|
||||
d->presentation = wl_registry_bind(registry, id,
|
||||
&wp_presentation_interface,
|
||||
2);
|
||||
wp_presentation_add_listener(d->presentation,
|
||||
&presentation_listener, d);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
registry_handle_global_remove(void *data, struct wl_registry *registry,
|
||||
uint32_t name)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_handle_global,
|
||||
registry_handle_global_remove
|
||||
};
|
||||
|
||||
static struct display *
|
||||
create_display(void)
|
||||
{
|
||||
struct display *display;
|
||||
|
||||
display = xzalloc(sizeof *display);
|
||||
|
||||
display->display = wl_display_connect(NULL);
|
||||
assert(display->display);
|
||||
|
||||
display->registry = wl_display_get_registry(display->display);
|
||||
wl_registry_add_listener(display->registry,
|
||||
®istry_listener, display);
|
||||
wl_display_roundtrip(display->display);
|
||||
if (display->shm == NULL) {
|
||||
fprintf(stderr, "No wl_shm global\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wl_display_roundtrip(display->display);
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_display(struct display *display)
|
||||
{
|
||||
if (display->shm)
|
||||
wl_shm_destroy(display->shm);
|
||||
|
||||
if (display->wm_base)
|
||||
xdg_wm_base_destroy(display->wm_base);
|
||||
|
||||
if (display->compositor)
|
||||
wl_compositor_destroy(display->compositor);
|
||||
|
||||
if (display->presentation)
|
||||
wp_presentation_destroy(display->presentation);
|
||||
|
||||
if (display->fifo_manager)
|
||||
wp_fifo_manager_v1_destroy(display->fifo_manager);
|
||||
|
||||
if (display->commit_timing_manager)
|
||||
wp_commit_timing_manager_v1_destroy(display->commit_timing_manager);
|
||||
|
||||
if (display->keyboard)
|
||||
wl_keyboard_destroy(display->keyboard);
|
||||
|
||||
if (display->seat)
|
||||
wl_seat_destroy(display->seat);
|
||||
|
||||
wl_registry_destroy(display->registry);
|
||||
wl_display_flush(display->display);
|
||||
wl_display_disconnect(display->display);
|
||||
free(display);
|
||||
}
|
||||
|
||||
static void
|
||||
signal_int(int signum)
|
||||
{
|
||||
running = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
usage(const char *program)
|
||||
{
|
||||
fprintf(stdout,
|
||||
"Usage: %s [OPTIONS]\n"
|
||||
"\n"
|
||||
"Schedule frames in the future with commit-timing\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
" -h, --help Show this help\n"
|
||||
"\n",
|
||||
program);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct sigaction sigint;
|
||||
struct display *display;
|
||||
struct window *window;
|
||||
int ret = 0, i;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-h") ||
|
||||
!strcmp(argv[i], "--help")) {
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid argument: '%s'\n", argv[i - 1]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
display = create_display();
|
||||
window = create_window(display, 256, 256);
|
||||
if (!window)
|
||||
return 1;
|
||||
|
||||
sigint.sa_handler = signal_int;
|
||||
sigemptyset(&sigint.sa_mask);
|
||||
sigint.sa_flags = SA_RESETHAND;
|
||||
sigaction(SIGINT, &sigint, NULL);
|
||||
|
||||
while (running && ret != -1)
|
||||
ret = wl_display_dispatch(display->display);
|
||||
|
||||
fprintf(stderr, "simple-timing exiting\n");
|
||||
|
||||
destroy_window(window);
|
||||
destroy_display(display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,9 +0,0 @@
|
|||
#version 450 core
|
||||
|
||||
layout(location = 0) in vec4 v_color;
|
||||
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = v_color;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
#version 450 core
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform block {
|
||||
uniform mat4 reflection;
|
||||
uniform float offset;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 pos;
|
||||
layout(location = 1) in vec4 color;
|
||||
|
||||
layout(location = 0) out vec4 v_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = reflection * (pos + vec4(offset, offset, 0.0, 0.0));
|
||||
v_color = color;
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#version 450 core
|
||||
|
||||
layout(location = 0) in vec4 vVaryingColor;
|
||||
layout(location = 0) out vec4 f_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
f_color = vVaryingColor;
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
#version 450 core
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform block {
|
||||
uniform mat4 rotation;
|
||||
};
|
||||
|
||||
layout(location = 0) in vec4 in_position;
|
||||
layout(location = 1) in vec4 in_color;
|
||||
|
||||
layout(location = 0) out vec4 vVaryingColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = rotation * in_position;
|
||||
vVaryingColor = vec4(in_color.rgba);
|
||||
}
|
||||
|
|
@ -58,7 +58,6 @@ static char *option_term;
|
|||
static char *option_shell;
|
||||
|
||||
static struct wl_list terminal_list;
|
||||
struct sigaction oldact;
|
||||
|
||||
static struct terminal *
|
||||
terminal_create(struct display *display);
|
||||
|
|
@ -3101,9 +3100,6 @@ terminal_run(struct terminal *terminal, const char *path)
|
|||
close(pipes[0]);
|
||||
setenv("TERM", option_term, 1);
|
||||
setenv("COLORTERM", option_term, 1);
|
||||
|
||||
sigaction(SIGPIPE, &oldact, NULL);
|
||||
|
||||
if (execl(path, path, NULL)) {
|
||||
printf("exec failed: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -3181,10 +3177,8 @@ int main(int argc, char *argv[])
|
|||
* socket whose reading end has been closed */
|
||||
sigpipe.sa_handler = SIG_IGN;
|
||||
sigemptyset(&sigpipe.sa_mask);
|
||||
sigemptyset(&oldact.sa_mask);
|
||||
|
||||
sigpipe.sa_flags = 0;
|
||||
sigaction(SIGPIPE, &sigpipe, &oldact);
|
||||
sigaction(SIGPIPE, &sigpipe, NULL);
|
||||
|
||||
d = display_create(&argc, argv);
|
||||
if (d == NULL) {
|
||||
|
|
|
|||
|
|
@ -330,9 +330,9 @@ compute_calibration(struct calibrator *cal, float *result)
|
|||
*/
|
||||
weston_matrix_init(&m);
|
||||
for (i = 0; i < 3; i++) {
|
||||
m.M.col[0].el[i] = cal->samples[i].touched.x;
|
||||
m.M.col[1].el[i] = cal->samples[i].touched.y;
|
||||
m.M.col[2].el[i] = 1.0f;
|
||||
m.d[i + 0] = cal->samples[i].touched.x;
|
||||
m.d[i + 4] = cal->samples[i].touched.y;
|
||||
m.d[i + 8] = 1.0f;
|
||||
}
|
||||
m.type = WESTON_MATRIX_TRANSFORM_OTHER;
|
||||
|
||||
|
|
@ -342,20 +342,20 @@ compute_calibration(struct calibrator *cal, float *result)
|
|||
}
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
x_calib.v.el[i] = cal->samples[i].drawn_cal.x;
|
||||
y_calib.v.el[i] = cal->samples[i].drawn_cal.y;
|
||||
x_calib.f[i] = cal->samples[i].drawn_cal.x;
|
||||
y_calib.f[i] = cal->samples[i].drawn_cal.y;
|
||||
}
|
||||
x_calib.v.el[3] = 0.0f;
|
||||
y_calib.v.el[3] = 0.0f;
|
||||
x_calib.f[3] = 0.0f;
|
||||
y_calib.f[3] = 0.0f;
|
||||
|
||||
/* Multiples into the vector */
|
||||
weston_matrix_transform(&inverse, &x_calib);
|
||||
weston_matrix_transform(&inverse, &y_calib);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
result[i] = x_calib.v.el[i];
|
||||
result[i] = x_calib.f[i];
|
||||
for (i = 0; i < 3; i++)
|
||||
result[i + 3] = y_calib.v.el[i];
|
||||
result[i + 3] = y_calib.f[i];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
194
clients/window.c
194
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)
|
||||
{
|
||||
|
|
@ -5946,19 +5898,6 @@ display_destroy_output(struct display *d, uint32_t id)
|
|||
|
||||
wl_list_for_each(output, &d->output_list, link) {
|
||||
if (output->server_output_id == id) {
|
||||
struct window *window;
|
||||
|
||||
/* If a window was on a destroyed output, we need to
|
||||
* make sure the output doesn't linger on the window's
|
||||
* output list.
|
||||
* surface_leave does nothing if the output isn't on
|
||||
* the list, so we can call it for all windows to remove
|
||||
* this output.
|
||||
*/
|
||||
wl_list_for_each(window, &d->window_list, link) {
|
||||
surface_leave(window, NULL, output->output);
|
||||
}
|
||||
|
||||
output_destroy(output);
|
||||
break;
|
||||
}
|
||||
|
|
@ -6732,7 +6671,7 @@ display_bind_tablets(struct display *d, uint32_t id)
|
|||
}
|
||||
|
||||
static void
|
||||
cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_intent(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t render_intent)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
|
@ -6741,7 +6680,7 @@ cm_supported_intent(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
|||
}
|
||||
|
||||
static void
|
||||
cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_feature(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t feature)
|
||||
{
|
||||
struct display *d = data;
|
||||
|
|
@ -6750,31 +6689,24 @@ cm_supported_feature(void *data, struct wp_color_manager_v1 *wp_color_manager_v1
|
|||
}
|
||||
|
||||
static void
|
||||
cm_supported_tf_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_tf_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t tf_code)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static void
|
||||
cm_supported_primaries_named(void *data, struct wp_color_manager_v1 *wp_color_manager_v1,
|
||||
cm_supported_primaries_named(void *data, struct xx_color_manager_v4 *xx_color_manager_v4,
|
||||
uint32_t primaries_code)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static void
|
||||
cm_done(void *data, struct wp_color_manager_v1 *wp_color_manager_v1)
|
||||
{
|
||||
/* unused in this file */
|
||||
}
|
||||
|
||||
static const struct wp_color_manager_v1_listener cm_listener = {
|
||||
static const struct xx_color_manager_v4_listener cm_listener = {
|
||||
.supported_intent = cm_supported_intent,
|
||||
.supported_feature = cm_supported_feature,
|
||||
.supported_tf_named = cm_supported_tf_named,
|
||||
.supported_primaries_named = cm_supported_primaries_named,
|
||||
.done = cm_done,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -6845,17 +6777,12 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
|||
&wp_viewporter_interface, 1);
|
||||
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
||||
display_bind_tablets(d, id);
|
||||
} else if (strcmp(interface, "wp_color_manager_v1") == 0) {
|
||||
} else if (strcmp(interface, "xx_color_manager_v4") == 0) {
|
||||
d->color_manager =
|
||||
wl_registry_bind(registry, id,
|
||||
&wp_color_manager_v1_interface, 1);
|
||||
wp_color_manager_v1_add_listener(d->color_manager,
|
||||
&xx_color_manager_v4_interface, 1);
|
||||
xx_color_manager_v4_add_listener(d->color_manager,
|
||||
&cm_listener, d);
|
||||
} else if (strcmp(interface, wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
|
||||
d->single_pixel_buffer_manager =
|
||||
wl_registry_bind(registry, id,
|
||||
&wp_single_pixel_buffer_manager_v1_interface,
|
||||
1);
|
||||
}
|
||||
|
||||
if (d->global_handler)
|
||||
|
|
@ -7078,10 +7005,7 @@ display_destroy(struct display *display)
|
|||
xdg_wm_base_destroy(display->xdg_shell);
|
||||
|
||||
if (display->color_manager)
|
||||
wp_color_manager_v1_destroy(display->color_manager);
|
||||
|
||||
if (display->single_pixel_buffer_manager)
|
||||
wp_single_pixel_buffer_manager_v1_destroy(display->single_pixel_buffer_manager);
|
||||
xx_color_manager_v4_destroy(display->color_manager);
|
||||
|
||||
if (display->shm)
|
||||
wl_shm_destroy(display->shm);
|
||||
|
|
@ -7147,12 +7071,6 @@ display_get_compositor(struct display *display)
|
|||
return display->compositor;
|
||||
}
|
||||
|
||||
struct wp_single_pixel_buffer_manager_v1 *
|
||||
display_get_single_pixel_buffer_manager(struct display *display)
|
||||
{
|
||||
return display->single_pixel_buffer_manager;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
display_get_serial(struct display *display)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -76,9 +76,6 @@ display_has_subcompositor(struct display *display);
|
|||
struct wl_compositor *
|
||||
display_get_compositor(struct display *display);
|
||||
|
||||
struct wp_single_pixel_buffer_manager_v1 *
|
||||
display_get_single_pixel_buffer_manager(struct display *display);
|
||||
|
||||
struct output *
|
||||
display_get_output(struct display *display);
|
||||
|
||||
|
|
@ -533,12 +530,6 @@ void
|
|||
window_set_locked_pointer_motion_handler(
|
||||
struct window *window, window_locked_pointer_motion_handler_t handler);
|
||||
|
||||
void
|
||||
window_set_shadow(struct window *window);
|
||||
|
||||
void
|
||||
window_unset_shadow(struct window *window);
|
||||
|
||||
void
|
||||
window_set_title(struct window *window, const char *title);
|
||||
|
||||
|
|
@ -613,9 +604,6 @@ widget_cairo_create(struct widget *widget);
|
|||
struct wl_surface *
|
||||
widget_get_wl_surface(struct widget *widget);
|
||||
|
||||
void
|
||||
widget_surface_flush(struct widget *widget);
|
||||
|
||||
uint32_t
|
||||
widget_get_last_time(struct widget *widget);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
prog_gcovr = find_program('gcovr', required: false, disabler: true)
|
||||
|
||||
# Configure the build:
|
||||
# $ meson configure -Db_sanitize=none -Db_coverage=true -Dwerror=true
|
||||
#
|
||||
# Ensure there are no stale .gcno or .gcda files around:
|
||||
# $ meson setup --wipe ~/git/weston
|
||||
#
|
||||
# Run the test suite:
|
||||
# $ meson compile
|
||||
# $ meson test
|
||||
#
|
||||
# Generate the reports:
|
||||
# $ meson compile gcovr-report
|
||||
|
||||
run_target(
|
||||
'gcovr-report',
|
||||
command: [
|
||||
prog_gcovr,
|
||||
'--root', '@SOURCE_ROOT@',
|
||||
'--cobertura', meson.current_build_dir() / 'cobertura.xml',
|
||||
'--html', meson.current_build_dir() / 'index.html',
|
||||
'--html-nested',
|
||||
'--html-theme', 'github.green',
|
||||
'--html-title', 'Weston test suite coverage',
|
||||
'--print-summary',
|
||||
meson.project_build_root(),
|
||||
],
|
||||
)
|
||||
|
|
@ -33,7 +33,6 @@ home.png
|
|||
icon_ivi_clickdot.png
|
||||
icon_ivi_flower.png
|
||||
icon_ivi_simple-egl.png
|
||||
icon_ivi_simple-egl-vertical.png
|
||||
icon_ivi_simple-shm.png
|
||||
icon_ivi_smoke.png
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 4.8 KiB |
|
|
@ -9,7 +9,6 @@ install_data(
|
|||
'icon_ivi_clickdot.png',
|
||||
'icon_ivi_flower.png',
|
||||
'icon_ivi_simple-egl.png',
|
||||
'icon_ivi_simple-egl-vertical.png',
|
||||
'icon_ivi_simple-shm.png',
|
||||
'icon_ivi_smoke.png',
|
||||
'icon_terminal.png',
|
||||
|
|
|
|||
|
|
@ -180,6 +180,12 @@ update_input_panels(struct wl_listener *listener, void *data)
|
|||
memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
|
||||
}
|
||||
|
||||
static int
|
||||
input_panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "input panel");
|
||||
}
|
||||
|
||||
static void
|
||||
input_panel_committed(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -208,7 +214,7 @@ destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
|
|||
wl_list_remove(&input_panel_surface->link);
|
||||
|
||||
input_panel_surface->surface->committed = NULL;
|
||||
weston_surface_set_label(input_panel_surface->surface, NULL);
|
||||
weston_surface_set_label_func(input_panel_surface->surface, NULL);
|
||||
weston_view_destroy(input_panel_surface->view);
|
||||
|
||||
free(input_panel_surface);
|
||||
|
|
@ -250,7 +256,7 @@ create_input_panel_surface(struct desktop_shell *shell,
|
|||
|
||||
surface->committed = input_panel_committed;
|
||||
surface->committed_private = input_panel_surface;
|
||||
weston_surface_set_label_static(surface, "input panel");
|
||||
weston_surface_set_label_func(surface, input_panel_get_label);
|
||||
|
||||
input_panel_surface->shell = shell;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,14 +42,174 @@
|
|||
#include <libweston/config-parser.h>
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "shared/string-helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
#include <libweston/desktop.h>
|
||||
|
||||
#define DEFAULT_NUM_WORKSPACES 1
|
||||
#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
|
||||
|
||||
struct focus_state {
|
||||
struct desktop_shell *shell;
|
||||
struct weston_seat *seat;
|
||||
struct workspace *ws;
|
||||
struct weston_surface *keyboard_focus;
|
||||
struct wl_list link;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
};
|
||||
|
||||
/*
|
||||
* Surface stacking and ordering.
|
||||
*
|
||||
* This is handled using several linked lists of surfaces, organised into
|
||||
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
||||
* above all of the surfaces in the layer below. The set of layers is static and
|
||||
* in the following order (top-most first):
|
||||
* • Lock layer (only ever displayed on its own)
|
||||
* • Cursor layer
|
||||
* • Input panel layer
|
||||
* • Fullscreen layer
|
||||
* • Panel layer
|
||||
* • Workspace layers
|
||||
* • Background layer
|
||||
*
|
||||
* The list of layers may be manipulated to remove whole layers of surfaces from
|
||||
* display. For example, when locking the screen, all layers except the lock
|
||||
* layer are removed.
|
||||
*
|
||||
* A surface’s layer is modified on configuring the surface, in
|
||||
* set_surface_type() (which is only called when the surface’s type change is
|
||||
* _committed_). If a surface’s type changes (e.g. when making a window
|
||||
* fullscreen) its layer changes too.
|
||||
*
|
||||
* In order to allow popup and transient surfaces to be correctly stacked above
|
||||
* their parent surfaces, each surface tracks both its parent surface, and a
|
||||
* linked list of its children. When a surface’s layer is updated, so are the
|
||||
* layers of its children. Note that child surfaces are *not* the same as
|
||||
* subsurfaces — child/parent surfaces are purely for maintaining stacking
|
||||
* order.
|
||||
*
|
||||
* The children_link list of siblings of a surface (i.e. those surfaces which
|
||||
* have the same parent) only contains weston_surfaces which have a
|
||||
* shell_surface. Stacking is not implemented for non-shell_surface
|
||||
* weston_surfaces. This means that the following implication does *not* hold:
|
||||
* (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link)
|
||||
*/
|
||||
|
||||
struct shell_surface {
|
||||
struct wl_signal destroy_signal;
|
||||
|
||||
struct weston_desktop_surface *desktop_surface;
|
||||
struct weston_view *view;
|
||||
struct weston_surface *wsurface_anim_fade;
|
||||
struct weston_view *wview_anim_fade;
|
||||
int32_t last_width, last_height;
|
||||
|
||||
struct desktop_shell *shell;
|
||||
|
||||
struct wl_list children_list;
|
||||
struct wl_list children_link;
|
||||
|
||||
struct weston_coord_global saved_pos;
|
||||
bool saved_position_valid;
|
||||
bool saved_rotation_valid;
|
||||
int unresponsive, grabbed;
|
||||
uint32_t resize_edges;
|
||||
uint32_t orientation;
|
||||
|
||||
struct {
|
||||
struct weston_transform transform;
|
||||
struct weston_matrix rotation;
|
||||
} rotation;
|
||||
|
||||
struct {
|
||||
struct weston_curtain *black_view;
|
||||
} fullscreen;
|
||||
|
||||
struct weston_output *fullscreen_output;
|
||||
struct weston_output *output;
|
||||
struct wl_listener output_destroy_listener;
|
||||
|
||||
struct surface_state {
|
||||
bool fullscreen;
|
||||
bool maximized;
|
||||
bool lowered;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
bool is_set;
|
||||
struct weston_coord_global pos;
|
||||
} xwayland;
|
||||
|
||||
int focus_count;
|
||||
|
||||
bool destroying;
|
||||
struct wl_list link; /** desktop_shell::shsurf_list */
|
||||
};
|
||||
|
||||
struct shell_grab {
|
||||
struct weston_pointer_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
};
|
||||
|
||||
struct shell_touch_grab {
|
||||
struct weston_touch_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_touch *touch;
|
||||
};
|
||||
|
||||
struct shell_tablet_tool_grab {
|
||||
struct weston_tablet_tool_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_tablet_tool *tool;
|
||||
};
|
||||
|
||||
struct weston_move_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_coord_global delta;
|
||||
bool client_initiated;
|
||||
};
|
||||
|
||||
struct weston_touch_move_grab {
|
||||
struct shell_touch_grab base;
|
||||
int active;
|
||||
struct weston_coord_global delta;
|
||||
};
|
||||
|
||||
struct weston_tablet_tool_move_grab {
|
||||
struct shell_tablet_tool_grab base;
|
||||
wl_fixed_t dx, dy;
|
||||
};
|
||||
|
||||
struct rotate_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_matrix rotation;
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
} center;
|
||||
};
|
||||
|
||||
struct shell_seat {
|
||||
struct weston_seat *seat;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct weston_surface *focused_surface;
|
||||
|
||||
struct wl_listener caps_changed_listener;
|
||||
struct wl_listener pointer_focus_listener;
|
||||
struct wl_listener keyboard_focus_listener;
|
||||
struct wl_listener tablet_tool_added_listener;
|
||||
|
||||
struct wl_list link; /** shell::seat_list */
|
||||
};
|
||||
|
||||
struct tablet_tool_listener {
|
||||
struct wl_listener base;
|
||||
struct wl_listener removed_listener;
|
||||
};
|
||||
|
||||
static struct desktop_shell *
|
||||
shell_surface_get_shell(struct shell_surface *shsurf);
|
||||
|
|
@ -75,6 +235,20 @@ shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
|
|||
static void
|
||||
get_maximized_size(struct shell_surface *shsurf, int32_t *width, int32_t *height);
|
||||
|
||||
static struct shell_output *
|
||||
find_shell_output_from_weston_output(struct desktop_shell *shell,
|
||||
struct weston_output *output)
|
||||
{
|
||||
struct shell_output *shell_output;
|
||||
|
||||
wl_list_for_each(shell_output, &shell->output_list, link) {
|
||||
if (shell_output->output == output)
|
||||
return shell_output;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
shsurf_is_max_or_fullscreen(struct shell_surface *shsurf)
|
||||
{
|
||||
|
|
@ -95,8 +269,8 @@ set_shsurf_size_maximized_or_fullscreen(struct shell_surface *shsurf,
|
|||
|
||||
if (fullscreen_requested) {
|
||||
if (shsurf->output) {
|
||||
width = shsurf->output->output->width;
|
||||
height = shsurf->output->output->height;
|
||||
width = shsurf->output->width;
|
||||
height = shsurf->output->height;
|
||||
}
|
||||
} else if (max_requested) {
|
||||
/* take the panels into considerations */
|
||||
|
|
@ -163,8 +337,6 @@ desktop_shell_destroy_surface(struct shell_surface *shsurf)
|
|||
shsurf->output_destroy_listener.notify = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&shsurf->surface_label_update.link);
|
||||
|
||||
free(shsurf);
|
||||
}
|
||||
|
||||
|
|
@ -197,18 +369,21 @@ shell_grab_start(struct shell_grab *grab,
|
|||
|
||||
void
|
||||
get_output_work_area(struct desktop_shell *shell,
|
||||
struct shell_output *sh_output,
|
||||
struct weston_output *output,
|
||||
pixman_rectangle32_t *area)
|
||||
{
|
||||
struct weston_output *output;
|
||||
struct shell_output *sh_output;
|
||||
|
||||
area->x = 0;
|
||||
area->y = 0;
|
||||
area->width = 0;
|
||||
area->height = 0;
|
||||
|
||||
if (!sh_output)
|
||||
if (!output)
|
||||
return;
|
||||
output = sh_output->output;
|
||||
|
||||
sh_output = find_shell_output_from_weston_output(shell, output);
|
||||
assert(sh_output);
|
||||
|
||||
area->x = output->pos.c.x;
|
||||
area->y = output->pos.c.y;
|
||||
|
|
@ -348,7 +523,6 @@ shell_configuration(struct desktop_shell *shell)
|
|||
struct weston_config *config;
|
||||
char *s, *client;
|
||||
bool allow_zap;
|
||||
bool disallow_output_changed_move;
|
||||
|
||||
config = wet_get_config(shell->compositor);
|
||||
section = weston_config_get_section(config, "shell", NULL, NULL);
|
||||
|
|
@ -361,11 +535,6 @@ shell_configuration(struct desktop_shell *shell)
|
|||
"allow-zap", &allow_zap, true);
|
||||
shell->allow_zap = allow_zap;
|
||||
|
||||
weston_config_section_get_bool(section,
|
||||
"disallow-output-changed-move",
|
||||
&disallow_output_changed_move, false);
|
||||
shell->disallow_output_changed_move = disallow_output_changed_move;
|
||||
|
||||
shell->binding_modifier = weston_config_get_binding_modifier(config, MODIFIER_SUPER);
|
||||
|
||||
weston_config_section_get_string(section, "animation", &s, "none");
|
||||
|
|
@ -398,6 +567,13 @@ shell_configuration(struct desktop_shell *shell)
|
|||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
focus_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "focus highlight effect for output %s",
|
||||
(surface->output ? surface->output->name : "NULL"));
|
||||
}
|
||||
|
||||
/* no-op func for checking focus surface */
|
||||
static void
|
||||
focus_surface_committed(struct weston_surface *es,
|
||||
|
|
@ -421,6 +597,7 @@ create_focus_surface(struct weston_compositor *ec,
|
|||
.pos = output->pos,
|
||||
.width = output->width, .height = output->height,
|
||||
.surface_committed = focus_surface_committed,
|
||||
.get_label = focus_surface_get_label,
|
||||
.surface_private = NULL,
|
||||
.capture_input = false,
|
||||
};
|
||||
|
|
@ -430,11 +607,8 @@ create_focus_surface(struct weston_compositor *ec,
|
|||
return NULL;
|
||||
|
||||
curtain_params.surface_private = fsurf;
|
||||
str_printf(&curtain_params.label, "focus highlight effect for output %s",
|
||||
output->name);
|
||||
|
||||
fsurf->curtain = weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||
|
||||
weston_view_set_output(fsurf->curtain->view, output);
|
||||
|
||||
return fsurf;
|
||||
|
|
@ -887,12 +1061,7 @@ constrain_position(struct weston_move_grab *move)
|
|||
|
||||
if (shsurf->shell->panel_position ==
|
||||
WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
|
||||
struct shell_output *shoutput = NULL;
|
||||
|
||||
if (surface->output)
|
||||
shoutput = weston_output_get_shell_private(surface->output);
|
||||
|
||||
get_output_work_area(shsurf->shell, shoutput, &area);
|
||||
get_output_work_area(shsurf->shell, surface->output, &area);
|
||||
geometry =
|
||||
weston_desktop_surface_get_geometry(shsurf->desktop_surface);
|
||||
|
||||
|
|
@ -1533,26 +1702,15 @@ shell_surface_set_output(struct shell_surface *shsurf,
|
|||
{
|
||||
struct weston_surface *es =
|
||||
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||
struct shell_output *shoutput = NULL;
|
||||
|
||||
if (output)
|
||||
shoutput = weston_output_get_shell_private(output);
|
||||
|
||||
/* get the default output, if the client set it as NULL
|
||||
check whether the output is available */
|
||||
if (shoutput)
|
||||
shsurf->output = shoutput;
|
||||
if (output)
|
||||
shsurf->output = output;
|
||||
else if (es->output)
|
||||
shsurf->output = weston_output_get_shell_private(es->output);
|
||||
else {
|
||||
struct shell_output *shoutput = NULL;
|
||||
struct weston_output *w_output;
|
||||
|
||||
w_output = weston_shell_utils_get_default_output(es->compositor);
|
||||
if (w_output)
|
||||
shoutput = weston_output_get_shell_private(w_output);
|
||||
shsurf->output = shoutput;
|
||||
}
|
||||
shsurf->output = es->output;
|
||||
else
|
||||
shsurf->output = weston_shell_utils_get_default_output(es->compositor);
|
||||
|
||||
if (shsurf->output_destroy_listener.notify) {
|
||||
wl_list_remove(&shsurf->output_destroy_listener.link);
|
||||
|
|
@ -1563,7 +1721,7 @@ shell_surface_set_output(struct shell_surface *shsurf,
|
|||
return;
|
||||
|
||||
shsurf->output_destroy_listener.notify = notify_output_destroy;
|
||||
wl_signal_add(&shsurf->output->output->destroy_signal,
|
||||
wl_signal_add(&shsurf->output->destroy_signal,
|
||||
&shsurf->output_destroy_listener);
|
||||
}
|
||||
|
||||
|
|
@ -1654,6 +1812,34 @@ shell_surface_get_shell(struct shell_surface *shsurf)
|
|||
return shsurf->shell;
|
||||
}
|
||||
|
||||
static int
|
||||
black_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
struct weston_view *fs_view = surface->committed_private;
|
||||
struct weston_surface *fs_surface = fs_view->surface;
|
||||
int n;
|
||||
int rem;
|
||||
int ret;
|
||||
|
||||
n = snprintf(buf, len, "black background surface for ");
|
||||
if (n < 0)
|
||||
return n;
|
||||
|
||||
rem = (int)len - n;
|
||||
if (rem < 0)
|
||||
rem = 0;
|
||||
|
||||
if (fs_surface->get_label)
|
||||
ret = fs_surface->get_label(fs_surface, buf + n, rem);
|
||||
else
|
||||
ret = snprintf(buf + n, rem, "<unknown>");
|
||||
|
||||
if (ret < 0)
|
||||
return n;
|
||||
|
||||
return n + ret;
|
||||
}
|
||||
|
||||
static void
|
||||
black_surface_committed(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -1681,18 +1867,13 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
|
|||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(shsurf->desktop_surface);
|
||||
struct weston_compositor *ec = surface->compositor;
|
||||
struct weston_output *output = NULL;
|
||||
|
||||
if (!shsurf->fullscreen_output)
|
||||
return;
|
||||
|
||||
output = shsurf->fullscreen_output->output;
|
||||
|
||||
struct weston_output *output = shsurf->fullscreen_output;
|
||||
struct weston_curtain_params curtain_params = {
|
||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||
.pos = output->pos,
|
||||
.width = output->width, .height = output->height,
|
||||
.surface_committed = black_surface_committed,
|
||||
.get_label = black_surface_get_label,
|
||||
.surface_private = shsurf->view,
|
||||
.capture_input = true,
|
||||
};
|
||||
|
|
@ -1701,16 +1882,14 @@ shell_set_view_fullscreen(struct shell_surface *shsurf)
|
|||
|
||||
weston_view_move_to_layer(shsurf->view,
|
||||
&shsurf->shell->fullscreen_layer.view_list);
|
||||
weston_shell_utils_center_on_output(shsurf->view, output);
|
||||
weston_shell_utils_center_on_output(shsurf->view, shsurf->fullscreen_output);
|
||||
|
||||
if (!shsurf->fullscreen.black_view) {
|
||||
str_printf(&curtain_params.label, "black background surface for %s",
|
||||
surface->label);
|
||||
shsurf->fullscreen.black_view =
|
||||
weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||
}
|
||||
weston_view_set_output(shsurf->fullscreen.black_view->view,
|
||||
output);
|
||||
shsurf->fullscreen_output);
|
||||
weston_view_move_to_layer(shsurf->fullscreen.black_view->view,
|
||||
&shsurf->view->layer_link);
|
||||
|
||||
|
|
@ -1876,8 +2055,8 @@ fade_out_done(struct weston_view_animation *animation, void *data)
|
|||
|
||||
if (weston_view_is_mapped(shsurf->wview_anim_fade)) {
|
||||
weston_view_move_to_layer(shsurf->wview_anim_fade, NULL);
|
||||
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
||||
}
|
||||
wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
|
||||
}
|
||||
|
||||
struct shell_surface *
|
||||
|
|
@ -1891,18 +2070,6 @@ get_shell_surface(struct weston_surface *surface)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_update_label(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface = data;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
}
|
||||
|
||||
/*
|
||||
* libweston-desktop
|
||||
*/
|
||||
|
|
@ -1919,7 +2086,6 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
struct shell_surface *shsurf;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
view = weston_desktop_surface_create_view(desktop_surface);
|
||||
if (!view)
|
||||
|
|
@ -1934,6 +2100,8 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
return;
|
||||
}
|
||||
|
||||
weston_surface_set_label_func(surface, weston_shell_utils_surface_get_label);
|
||||
|
||||
shsurf->shell = (struct desktop_shell *) shell;
|
||||
shsurf->unresponsive = 0;
|
||||
shsurf->saved_position_valid = false;
|
||||
|
|
@ -1961,14 +2129,6 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
wl_list_insert(&shsurf->shell->shsurf_list, &shsurf->link);
|
||||
|
||||
weston_desktop_surface_set_user_data(desktop_surface, shsurf);
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
|
||||
/* client-controllable from xdg-shell */
|
||||
shsurf->surface_label_update.notify = desktop_surface_update_label;
|
||||
weston_desktop_surface_add_metadata_listener(desktop_surface,
|
||||
&shsurf->surface_label_update);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2001,9 +2161,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
|
|||
shsurf->fullscreen.black_view = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&shsurf->surface_label_update.link);
|
||||
wl_list_init(&shsurf->surface_label_update.link);
|
||||
|
||||
weston_surface_set_label_func(surface, NULL);
|
||||
weston_desktop_surface_set_user_data(shsurf->desktop_surface, NULL);
|
||||
shsurf->desktop_surface = NULL;
|
||||
|
||||
|
|
@ -2111,13 +2269,8 @@ map(struct desktop_shell *shell, struct shell_surface *shsurf)
|
|||
shell_surface_update_layer(shsurf);
|
||||
|
||||
if (shsurf->state.maximized) {
|
||||
struct weston_output *w_output = NULL;
|
||||
|
||||
if (shsurf->output)
|
||||
w_output = shsurf->output->output;
|
||||
|
||||
surface->output = w_output;
|
||||
weston_view_set_output(shsurf->view, w_output);
|
||||
surface->output = shsurf->output;
|
||||
weston_view_set_output(shsurf->view, shsurf->output);
|
||||
}
|
||||
|
||||
if (!shell->locked) {
|
||||
|
|
@ -2223,12 +2376,8 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
WESTON_ACTIVATE_FLAG_FULLSCREEN);
|
||||
}
|
||||
} else if (shsurf->state.maximized) {
|
||||
struct weston_output *w_output = NULL;
|
||||
|
||||
set_maximized_position(shell, shsurf);
|
||||
if (surface->output)
|
||||
w_output = shsurf->output->output;
|
||||
surface->output = w_output;
|
||||
surface->output = shsurf->output;
|
||||
} else {
|
||||
struct weston_coord_surface offset = buf_offset;
|
||||
struct weston_coord_global pos;
|
||||
|
|
@ -2616,19 +2765,19 @@ static const struct weston_desktop_api shell_desktop_api = {
|
|||
/* ************************ *
|
||||
* end of libweston-desktop *
|
||||
* ************************ */
|
||||
static int
|
||||
background_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "background for output %s",
|
||||
(surface->output ? surface->output->name : "NULL"));
|
||||
}
|
||||
|
||||
static void
|
||||
background_committed(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
struct shell_output *sh_output = es->committed_private;
|
||||
struct desktop_shell *shell;
|
||||
|
||||
/* The output was destroyed before the background was committed */
|
||||
if (!sh_output)
|
||||
return;
|
||||
|
||||
shell = sh_output->shell;
|
||||
struct desktop_shell *shell = sh_output->shell;
|
||||
|
||||
if (!weston_surface_has_content(es))
|
||||
return;
|
||||
|
|
@ -2644,7 +2793,6 @@ background_committed(struct weston_surface *es,
|
|||
sh_output->output->pos);
|
||||
weston_view_move_to_layer(sh_output->background_view,
|
||||
&shell->background_layer.view_list);
|
||||
weston_output_set_ready(sh_output->output);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2664,11 +2812,11 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
struct wl_resource *output_resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(surface_resource);
|
||||
struct shell_output *sh_output;
|
||||
struct weston_head *head = weston_head_from_resource(output_resource);
|
||||
char *label;
|
||||
|
||||
if (surface->committed) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
|
|
@ -2681,7 +2829,7 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
return;
|
||||
|
||||
surface->output = head->output;
|
||||
sh_output = weston_output_get_shell_private(surface->output);
|
||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
||||
if (sh_output->background_surface) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
WL_DISPLAY_ERROR_INVALID_OBJECT,
|
||||
|
|
@ -2691,9 +2839,7 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
|
||||
surface->committed = background_committed;
|
||||
surface->committed_private = sh_output;
|
||||
|
||||
str_printf(&label, "background for output %s", surface->output->name);
|
||||
weston_surface_set_label(surface, label);
|
||||
weston_surface_set_label_func(surface, background_get_label);
|
||||
|
||||
weston_desktop_shell_send_configure(resource, 0,
|
||||
surface_resource,
|
||||
|
|
@ -2708,22 +2854,21 @@ desktop_shell_set_background(struct wl_client *client,
|
|||
&sh_output->background_surface_listener);
|
||||
}
|
||||
|
||||
static int
|
||||
panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "panel for output %s",
|
||||
(surface->output ? surface->output->name : "NULL"));
|
||||
}
|
||||
|
||||
static void
|
||||
panel_committed(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
struct shell_output *sh_output = es->committed_private;
|
||||
struct weston_output *output;
|
||||
struct weston_coord_global pos;
|
||||
struct desktop_shell *shell;
|
||||
|
||||
/* The output was destroyed before the panel was committed */
|
||||
if (!sh_output)
|
||||
return;
|
||||
|
||||
output = sh_output->output;
|
||||
pos = output->pos;
|
||||
shell = sh_output->shell;
|
||||
struct weston_output *output = sh_output->output;
|
||||
struct weston_coord_global pos = output->pos;
|
||||
struct desktop_shell *shell = sh_output->shell;
|
||||
|
||||
if (!weston_surface_has_content(es))
|
||||
return;
|
||||
|
|
@ -2778,11 +2923,11 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
struct wl_resource *output_resource,
|
||||
struct wl_resource *surface_resource)
|
||||
{
|
||||
struct desktop_shell *shell = wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface =
|
||||
wl_resource_get_user_data(surface_resource);
|
||||
struct shell_output *sh_output;
|
||||
struct weston_head *head = weston_head_from_resource(output_resource);
|
||||
char *label;
|
||||
|
||||
if (surface->committed) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
|
|
@ -2795,7 +2940,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
return;
|
||||
|
||||
surface->output = head->output;
|
||||
sh_output = weston_output_get_shell_private(surface->output);
|
||||
sh_output = find_shell_output_from_weston_output(shell, surface->output);
|
||||
|
||||
if (sh_output->panel_surface) {
|
||||
wl_resource_post_error(surface_resource,
|
||||
|
|
@ -2806,9 +2951,7 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
|
||||
surface->committed = panel_committed;
|
||||
surface->committed_private = sh_output;
|
||||
|
||||
str_printf(&label, "panel for output %s", surface->output->name);
|
||||
weston_surface_set_label(surface, label);
|
||||
weston_surface_set_label_func(surface, panel_get_label);
|
||||
|
||||
weston_desktop_shell_send_configure(resource, 0,
|
||||
surface_resource,
|
||||
|
|
@ -2821,6 +2964,12 @@ desktop_shell_set_panel(struct wl_client *client,
|
|||
wl_signal_add(&surface->destroy_signal, &sh_output->panel_surface_listener);
|
||||
}
|
||||
|
||||
static int
|
||||
lock_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "lock window");
|
||||
}
|
||||
|
||||
static void
|
||||
lock_surface_committed(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -2877,7 +3026,7 @@ desktop_shell_set_lock_surface(struct wl_client *client,
|
|||
|
||||
surface->committed = lock_surface_committed;
|
||||
surface->committed_private = shell;
|
||||
weston_surface_set_label_static(surface, "lock window");
|
||||
weston_surface_set_label_func(surface, lock_surface_get_label);
|
||||
|
||||
shell->lock_surface = surface;
|
||||
shell->lock_surface_listener.notify = handle_lock_surface_destroy;
|
||||
|
|
@ -3283,6 +3432,7 @@ rotate_grab_motion(struct weston_pointer_grab *grab,
|
|||
}
|
||||
|
||||
weston_view_update_transform(shsurf->view);
|
||||
weston_surface_damage(shsurf->view->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3406,7 +3556,7 @@ rotate_binding(struct weston_pointer *pointer, const struct timespec *time,
|
|||
* the alt-tab switcher, which need to de-promote fullscreen layers. */
|
||||
void
|
||||
lower_fullscreen_layer(struct desktop_shell *shell,
|
||||
struct shell_output *lowering_output)
|
||||
struct weston_output *lowering_output)
|
||||
{
|
||||
struct workspace *ws;
|
||||
struct weston_view *view, *prev;
|
||||
|
|
@ -3674,6 +3824,13 @@ shell_fade_done(struct weston_view_animation *animation, void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
fade_surface_get_label(struct weston_surface *surface,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "desktop shell fade surface");
|
||||
}
|
||||
|
||||
static struct weston_curtain *
|
||||
shell_fade_create_view(struct desktop_shell *shell)
|
||||
{
|
||||
|
|
@ -3682,9 +3839,9 @@ shell_fade_create_view(struct desktop_shell *shell)
|
|||
struct weston_curtain_params curtain_params = {
|
||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||
.surface_committed = black_surface_committed,
|
||||
.get_label = fade_surface_get_label,
|
||||
.surface_private = shell,
|
||||
.capture_input = true,
|
||||
.label = xstrdup("desktop shell fade surface"),
|
||||
};
|
||||
struct weston_curtain *curtain;
|
||||
bool first = true;
|
||||
|
|
@ -3711,7 +3868,6 @@ shell_fade_create_view(struct desktop_shell *shell)
|
|||
curtain_params.pos.c.y = y1;
|
||||
curtain_params.width = x2 - x1;
|
||||
curtain_params.height = y2 - y1;
|
||||
|
||||
curtain = weston_shell_utils_curtain_create(compositor, &curtain_params);
|
||||
assert(curtain);
|
||||
|
||||
|
|
@ -3820,6 +3976,9 @@ shell_fade_init(struct desktop_shell *shell)
|
|||
if (!shell->fade.curtain)
|
||||
return;
|
||||
|
||||
weston_view_update_transform(shell->fade.curtain->view);
|
||||
weston_surface_damage(shell->fade.curtain->view->surface);
|
||||
|
||||
loop = wl_display_get_event_loop(shell->compositor->wl_display);
|
||||
shell->fade.startup_timer =
|
||||
wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
|
||||
|
|
@ -3850,12 +4009,6 @@ wake_handler(struct wl_listener *listener, void *data)
|
|||
unlock(shell);
|
||||
}
|
||||
|
||||
static void
|
||||
sleep_handler(struct wl_listener *listener, void *data)
|
||||
{
|
||||
weston_log("entering sleep mode: DPMS off\n");
|
||||
}
|
||||
|
||||
static void
|
||||
transform_handler(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -3895,7 +4048,6 @@ weston_view_set_initial_position(struct weston_view *view,
|
|||
int32_t range_x, range_y;
|
||||
int32_t x, y;
|
||||
struct weston_output *output, *target_output = NULL;
|
||||
struct shell_output *shoutput;
|
||||
struct weston_seat *seat;
|
||||
pixman_rectangle32_t area;
|
||||
struct weston_coord_global pos;
|
||||
|
|
@ -3933,9 +4085,7 @@ weston_view_set_initial_position(struct weston_view *view,
|
|||
* If this is negative it means that the surface is bigger than
|
||||
* output.
|
||||
*/
|
||||
assert(target_output);
|
||||
shoutput = weston_output_get_shell_private(target_output);
|
||||
get_output_work_area(shell, shoutput, &area);
|
||||
get_output_work_area(shell, target_output, &area);
|
||||
|
||||
x = area.x;
|
||||
y = area.y;
|
||||
|
|
@ -4317,12 +4467,6 @@ shell_reposition_view_on_output_change(struct weston_view *view)
|
|||
struct shell_surface *shsurf;
|
||||
int visible;
|
||||
|
||||
/* We can't simply reposition popups and such, they must move with
|
||||
* the parent.
|
||||
*/
|
||||
if (view->geometry.parent)
|
||||
return;
|
||||
|
||||
if (wl_list_empty(&ec->output_list))
|
||||
return;
|
||||
|
||||
|
|
@ -4398,18 +4542,12 @@ shell_output_destroy(struct shell_output *shell_output)
|
|||
{
|
||||
struct desktop_shell *shell = shell_output->shell;
|
||||
|
||||
if (!shell->disallow_output_changed_move) {
|
||||
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
|
||||
}
|
||||
shell_for_each_layer(shell, shell_output_changed_move_layer, NULL);
|
||||
|
||||
if (shell_output->panel_surface) {
|
||||
if (shell_output->panel_surface)
|
||||
wl_list_remove(&shell_output->panel_surface_listener.link);
|
||||
shell_output->panel_surface->committed_private = NULL;
|
||||
}
|
||||
if (shell_output->background_surface) {
|
||||
if (shell_output->background_surface)
|
||||
wl_list_remove(&shell_output->background_surface_listener.link);
|
||||
shell_output->background_surface->committed_private = NULL;
|
||||
}
|
||||
wl_list_remove(&shell_output->destroy_listener.link);
|
||||
wl_list_remove(&shell_output->link);
|
||||
free(shell_output);
|
||||
|
|
@ -4469,7 +4607,7 @@ handle_output_resized(struct wl_listener *listener, void *data)
|
|||
struct desktop_shell *shell =
|
||||
container_of(listener, struct desktop_shell, resized_listener);
|
||||
struct weston_output *output = (struct weston_output *)data;
|
||||
struct shell_output *sh_output = weston_output_get_shell_private(output);
|
||||
struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
|
||||
|
||||
handle_output_resized_shsurfs(shell);
|
||||
|
||||
|
|
@ -4487,8 +4625,6 @@ create_shell_output(struct desktop_shell *shell,
|
|||
if (shell_output == NULL)
|
||||
return;
|
||||
|
||||
weston_output_set_shell_private(output, shell_output);
|
||||
|
||||
shell_output->output = output;
|
||||
shell_output->shell = shell;
|
||||
shell_output->destroy_listener.notify = handle_output_destroy;
|
||||
|
|
@ -4496,7 +4632,7 @@ create_shell_output(struct desktop_shell *shell,
|
|||
&shell_output->destroy_listener);
|
||||
wl_list_insert(shell->output_list.prev, &shell_output->link);
|
||||
|
||||
if (!shell->disallow_output_changed_move && wl_list_length(&shell->output_list) == 1)
|
||||
if (wl_list_length(&shell->output_list) == 1)
|
||||
shell_for_each_layer(shell,
|
||||
shell_output_changed_move_layer, NULL);
|
||||
}
|
||||
|
|
@ -4523,12 +4659,6 @@ handle_output_move_layer(struct desktop_shell *shell,
|
|||
if (view->output != output)
|
||||
continue;
|
||||
|
||||
/* We can't simply reposition popups and such, they must move with
|
||||
* the parent.
|
||||
*/
|
||||
if (view->geometry.parent)
|
||||
continue;
|
||||
|
||||
pos = weston_coord_global_add(
|
||||
weston_view_get_pos_offset_global(view),
|
||||
output->move);
|
||||
|
|
@ -4627,7 +4757,6 @@ shell_destroy(struct wl_listener *listener, void *data)
|
|||
wl_list_remove(&shell->destroy_listener.link);
|
||||
wl_list_remove(&shell->idle_listener.link);
|
||||
wl_list_remove(&shell->wake_listener.link);
|
||||
wl_list_remove(&shell->sleep_listener.link);
|
||||
wl_list_remove(&shell->transform_listener.link);
|
||||
|
||||
text_backend_destroy(shell->text_backend);
|
||||
|
|
@ -4809,8 +4938,6 @@ wet_shell_init(struct weston_compositor *ec,
|
|||
wl_signal_add(&ec->idle_signal, &shell->idle_listener);
|
||||
shell->wake_listener.notify = wake_handler;
|
||||
wl_signal_add(&ec->wake_signal, &shell->wake_listener);
|
||||
shell->sleep_listener.notify = sleep_handler;
|
||||
wl_signal_add(&ec->sleep_signal, &shell->sleep_listener);
|
||||
shell->transform_listener.notify = transform_handler;
|
||||
wl_signal_add(&ec->transform_signal, &shell->transform_listener);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,9 +23,6 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef WESTON_DESKTOP_SHELL_H
|
||||
#define WESTON_DESKTOP_SHELL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
|
@ -35,170 +32,6 @@
|
|||
|
||||
#include "weston-desktop-shell-server-protocol.h"
|
||||
|
||||
struct focus_state {
|
||||
struct desktop_shell *shell;
|
||||
struct weston_seat *seat;
|
||||
struct workspace *ws;
|
||||
struct weston_surface *keyboard_focus;
|
||||
struct wl_list link;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct wl_listener surface_destroy_listener;
|
||||
};
|
||||
|
||||
/*
|
||||
* Surface stacking and ordering.
|
||||
*
|
||||
* This is handled using several linked lists of surfaces, organised into
|
||||
* ‘layers’. The layers are ordered, and each of the surfaces in one layer are
|
||||
* above all of the surfaces in the layer below. The set of layers is static and
|
||||
* in the following order (top-most first):
|
||||
* • Lock layer (only ever displayed on its own)
|
||||
* • Cursor layer
|
||||
* • Input panel layer
|
||||
* • Fullscreen layer
|
||||
* • Panel layer
|
||||
* • Workspace layers
|
||||
* • Background layer
|
||||
*
|
||||
* The list of layers may be manipulated to remove whole layers of surfaces from
|
||||
* display. For example, when locking the screen, all layers except the lock
|
||||
* layer are removed.
|
||||
*
|
||||
* A surface’s layer is modified on configuring the surface, in
|
||||
* set_surface_type() (which is only called when the surface’s type change is
|
||||
* _committed_). If a surface’s type changes (e.g. when making a window
|
||||
* fullscreen) its layer changes too.
|
||||
*
|
||||
* In order to allow popup and transient surfaces to be correctly stacked above
|
||||
* their parent surfaces, each surface tracks both its parent surface, and a
|
||||
* linked list of its children. When a surface’s layer is updated, so are the
|
||||
* layers of its children. Note that child surfaces are *not* the same as
|
||||
* subsurfaces — child/parent surfaces are purely for maintaining stacking
|
||||
* order.
|
||||
*
|
||||
* The children_link list of siblings of a surface (i.e. those surfaces which
|
||||
* have the same parent) only contains weston_surfaces which have a
|
||||
* shell_surface. Stacking is not implemented for non-shell_surface
|
||||
* weston_surfaces. This means that the following implication does *not* hold:
|
||||
* (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link)
|
||||
*/
|
||||
|
||||
struct shell_surface {
|
||||
struct wl_signal destroy_signal;
|
||||
|
||||
struct weston_desktop_surface *desktop_surface;
|
||||
struct weston_view *view;
|
||||
struct weston_surface *wsurface_anim_fade;
|
||||
struct weston_view *wview_anim_fade;
|
||||
int32_t last_width, last_height;
|
||||
|
||||
struct desktop_shell *shell;
|
||||
|
||||
struct wl_list children_list;
|
||||
struct wl_list children_link;
|
||||
|
||||
struct weston_coord_global saved_pos;
|
||||
bool saved_position_valid;
|
||||
bool saved_rotation_valid;
|
||||
int unresponsive, grabbed;
|
||||
uint32_t resize_edges;
|
||||
uint32_t orientation;
|
||||
|
||||
struct {
|
||||
struct weston_transform transform;
|
||||
struct weston_matrix rotation;
|
||||
} rotation;
|
||||
|
||||
struct {
|
||||
struct weston_curtain *black_view;
|
||||
} fullscreen;
|
||||
|
||||
struct shell_output *fullscreen_output;
|
||||
struct shell_output *output;
|
||||
struct wl_listener output_destroy_listener;
|
||||
struct wl_listener surface_label_update;
|
||||
|
||||
struct surface_state {
|
||||
bool fullscreen;
|
||||
bool maximized;
|
||||
bool lowered;
|
||||
} state;
|
||||
|
||||
struct {
|
||||
bool is_set;
|
||||
struct weston_coord_global pos;
|
||||
} xwayland;
|
||||
|
||||
int focus_count;
|
||||
|
||||
bool destroying;
|
||||
struct wl_list link; /** desktop_shell::shsurf_list */
|
||||
};
|
||||
|
||||
struct shell_grab {
|
||||
struct weston_pointer_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
};
|
||||
|
||||
struct shell_touch_grab {
|
||||
struct weston_touch_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_touch *touch;
|
||||
};
|
||||
|
||||
struct shell_tablet_tool_grab {
|
||||
struct weston_tablet_tool_grab grab;
|
||||
struct shell_surface *shsurf;
|
||||
struct wl_listener shsurf_destroy_listener;
|
||||
struct weston_tablet_tool *tool;
|
||||
};
|
||||
|
||||
struct weston_move_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_coord_global delta;
|
||||
bool client_initiated;
|
||||
};
|
||||
|
||||
struct weston_touch_move_grab {
|
||||
struct shell_touch_grab base;
|
||||
int active;
|
||||
struct weston_coord_global delta;
|
||||
};
|
||||
|
||||
struct weston_tablet_tool_move_grab {
|
||||
struct shell_tablet_tool_grab base;
|
||||
wl_fixed_t dx, dy;
|
||||
};
|
||||
|
||||
struct rotate_grab {
|
||||
struct shell_grab base;
|
||||
struct weston_matrix rotation;
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
} center;
|
||||
};
|
||||
|
||||
struct shell_seat {
|
||||
struct weston_seat *seat;
|
||||
struct wl_listener seat_destroy_listener;
|
||||
struct weston_surface *focused_surface;
|
||||
|
||||
struct wl_listener caps_changed_listener;
|
||||
struct wl_listener pointer_focus_listener;
|
||||
struct wl_listener keyboard_focus_listener;
|
||||
struct wl_listener tablet_tool_added_listener;
|
||||
|
||||
struct wl_list link; /** shell::seat_list */
|
||||
};
|
||||
|
||||
struct tablet_tool_listener {
|
||||
struct wl_listener base;
|
||||
struct wl_listener removed_listener;
|
||||
};
|
||||
|
||||
enum animation_type {
|
||||
ANIMATION_NONE,
|
||||
|
||||
|
|
@ -251,7 +84,6 @@ struct desktop_shell {
|
|||
|
||||
struct wl_listener idle_listener;
|
||||
struct wl_listener wake_listener;
|
||||
struct wl_listener sleep_listener;
|
||||
struct wl_listener transform_listener;
|
||||
struct wl_listener resized_listener;
|
||||
struct wl_listener destroy_listener;
|
||||
|
|
@ -308,7 +140,6 @@ struct desktop_shell {
|
|||
} fade;
|
||||
|
||||
bool allow_zap;
|
||||
bool disallow_output_changed_move;
|
||||
uint32_t binding_modifier;
|
||||
enum animation_type win_animation_type;
|
||||
enum animation_type win_close_animation_type;
|
||||
|
|
@ -345,12 +176,12 @@ get_current_workspace(struct desktop_shell *shell);
|
|||
|
||||
void
|
||||
get_output_work_area(struct desktop_shell *shell,
|
||||
struct shell_output *output,
|
||||
struct weston_output *output,
|
||||
pixman_rectangle32_t *area);
|
||||
|
||||
void
|
||||
lower_fullscreen_layer(struct desktop_shell *shell,
|
||||
struct shell_output *lowering_output);
|
||||
struct weston_output *lowering_output);
|
||||
|
||||
void
|
||||
activate(struct desktop_shell *shell, struct weston_view *view,
|
||||
|
|
@ -368,5 +199,3 @@ void
|
|||
shell_for_each_layer(struct desktop_shell *shell,
|
||||
shell_for_each_layer_func_t func,
|
||||
void *data);
|
||||
|
||||
#endif /* WESTON_DESKTOP_SHELL_H */
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
buffers {
|
||||
size_kb: 16384
|
||||
fill_policy: RING_BUFFER
|
||||
}
|
||||
|
||||
data_sources {
|
||||
config {
|
||||
name: "track_event"
|
||||
track_event_config {
|
||||
enabled_categories: "mesa.default"
|
||||
enabled_categories: "mesa.slow"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
duration_ms: 5000
|
||||
write_into_file: true
|
||||
file_write_period_ms: 500
|
||||
flush_period_ms: 500
|
||||
|
|
@ -196,8 +196,7 @@ epub_exclude_files = ['search.html']
|
|||
# -- Options for intersphinx extension ---------------------------------------
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
|
||||
|
||||
intersphinx_mapping = {'https://docs.python.org/3': None}
|
||||
|
||||
# -- Options for todo extension ----------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1208,6 +1208,15 @@ HTML_COLORSTYLE_SAT = 100
|
|||
|
||||
HTML_COLORSTYLE_GAMMA = 80
|
||||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
# to YES can help to show when doxygen was last run and thus if the
|
||||
# documentation is up to date.
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_TIMESTAMP = NO
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
# page has loaded.
|
||||
|
|
|
|||
|
|
@ -14,16 +14,14 @@ Welcome to Weston documentation!
|
|||
Weston
|
||||
------
|
||||
|
||||
Weston is a Wayland compositor designed for correctness, reliability,
|
||||
predictability, and performance.
|
||||
Weston is the reference implementation of a Wayland compositor, as well as a
|
||||
useful environment in and of itself.
|
||||
|
||||
Out of the box, Weston provides a very basic desktop, or a full-featured
|
||||
environment for non-desktop uses such as automotive, embedded, in-flight,
|
||||
industrial, kiosks, set-top boxes and TVs.
|
||||
|
||||
It also provides a library called :ref:`libweston-label` which allows
|
||||
users to build their own custom full-featured environments on top of
|
||||
Weston's core.
|
||||
industrial, kiosks, set-top boxes and TVs. It also provides a library allowing
|
||||
other projects to build their own full-featured environments on top of Weston's
|
||||
core.
|
||||
|
||||
The core focus of Weston is correctness and reliability. Weston aims to be lean
|
||||
and fast, but more importantly, to be predictable. Whilst Weston does have
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ doxygen_conf_weston = configure_file(
|
|||
|
||||
script_data = configuration_data()
|
||||
script_data.set('SRCDIR', meson.current_build_dir())
|
||||
script_data.set('OUTDIR', meson.current_build_dir() / 'weston')
|
||||
script_data.set('OUTDIR', meson.current_build_dir() + '/doc')
|
||||
|
||||
# Set a different directory for doctrees to avoid installing them
|
||||
script_data.set('DOCTREES_DIR', meson.current_build_dir() + '/doctrees')
|
||||
|
|
@ -82,11 +82,9 @@ endif
|
|||
sphinx_doc = custom_target(
|
||||
'weston-doc-breathe',
|
||||
command: script_doxy_sphinx,
|
||||
output: 'weston',
|
||||
output: 'doc',
|
||||
build_by_default: true,
|
||||
env: sphinx_env,
|
||||
install: true,
|
||||
install_dir: dir_data / 'doc',
|
||||
)
|
||||
|
||||
# we need this because we will have a stale 'doc' directory
|
||||
|
|
@ -95,3 +93,10 @@ docs = run_target(
|
|||
'docs',
|
||||
command: script_doxy_sphinx,
|
||||
)
|
||||
|
||||
install_subdir(
|
||||
sphinx_doc.full_path(),
|
||||
install_dir: dir_data / 'doc' / 'weston',
|
||||
exclude_files: '.buildinfo',
|
||||
strip_directory: true,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,15 +6,4 @@ else
|
|||
SPHINX_WERROR=""
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
BUILDINFO_ORIG="@OUTDIR@/.buildinfo"
|
||||
BUILDINFO_SAVE="@SRCDIR@/buildinfo.save"
|
||||
|
||||
[ -f "$BUILDINFO_SAVE" ] && mv -f "$BUILDINFO_SAVE" "$BUILDINFO_ORIG"
|
||||
|
||||
@DOXYGEN_CMD@ @DOXYGEN_CONF@
|
||||
|
||||
@SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
|
||||
|
||||
mv -f "$BUILDINFO_ORIG" "$BUILDINFO_SAVE"
|
||||
@DOXYGEN_CMD@ @DOXYGEN_CONF@ && @SPHINX_CMD@ $SPHINX_WERROR -E -q -j auto -d @DOCTREES_DIR@ @SRCDIR@ @OUTDIR@
|
||||
|
|
|
|||
|
|
@ -86,8 +86,7 @@ the surface was added to. However, the views are not provided to the IVI
|
|||
controller.
|
||||
|
||||
After configuring all expected changes, the controller must call the
|
||||
``commit_changes`` to atomically update the display layout and call
|
||||
``screen_ready`` to inform the compositor that it can start issueing repaints.
|
||||
``commit_changes`` to atomically update the display layout.
|
||||
|
||||
IVI-shell example implementation
|
||||
--------------------------------
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
.. _libweston-label:
|
||||
|
||||
Libweston
|
||||
=========
|
||||
|
||||
|
|
@ -12,7 +10,6 @@ Libweston
|
|||
libweston/shell-utils.rst
|
||||
libweston/output-management.rst
|
||||
libweston/log.rst
|
||||
libweston/debug-flight-recorder.rst
|
||||
|
||||
`Libweston` is an effort to separate the re-usable parts of Weston into a
|
||||
library. `Libweston` provides most of the boring and tedious bits of correctly
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
.. _debugging flight recorder:
|
||||
|
||||
|
||||
Debugging with Flight Recorder
|
||||
==============================
|
||||
|
||||
Weston can write debug scopes data to a circular ring buffer. This ring
|
||||
buffer can be accessed through a debug key, assuming you have a keyboard
|
||||
attached, or in case Weston dies, through a coredump. This document describes
|
||||
how to access that data in the later case.
|
||||
|
||||
The ring buffer data can be accessed with a gdb python script that searches
|
||||
the coredump file for the that ring buffer address in order to retrieve
|
||||
data from it.
|
||||
|
||||
Prior to setting this up make sure that flight recorder is configured
|
||||
accordingly. Make sure that Weston is started with the debug scopes that
|
||||
you're interested into. For instance if you'd like to get the :samp:`drm-backend` one
|
||||
Weston should show when starting up:
|
||||
|
||||
::
|
||||
|
||||
Flight recorder: enabled, scopes subscribed: drm-backend
|
||||
|
||||
For that Weston needs to be started with :samp:`--debug -f drm-backend`.
|
||||
|
||||
Also, make sure that the system is configured to generate a core dump. Refer
|
||||
to :samp:`man core(5)` for how to do that.
|
||||
|
||||
Next you'll need the `gdb python
|
||||
script <https://gitlab.freedesktop.org/wayland/weston/-/blob/main/doc/scripts/gdb/flight_rec.py>`_,
|
||||
as that will be needed to search for the ring buffer within the coredump.
|
||||
|
||||
Finally, to make this easier and push everything from the ring buffer to a
|
||||
file, we would need to create a batch gdb file script to invoke the commands
|
||||
for us.
|
||||
|
||||
As an example name that file :file:`test.gdb` and add the following to entries
|
||||
to it, making sure to adjust the path for the python script.
|
||||
|
||||
::
|
||||
|
||||
source /path/to/flight_rec.py
|
||||
display_flight_rec
|
||||
|
||||
Then run the following commands to dump the contents of the ring buffer
|
||||
straight to a file:
|
||||
|
||||
::
|
||||
|
||||
$ gdb --batch --command=/path/to/test.gdb -q /path/to/test/weston/binary --core /path/to/coredump &> dump.log.txt
|
||||
|
|
@ -141,9 +141,8 @@ force the contents to be printed on :samp:`stdout` file-descriptor.
|
|||
The user has first to specify which log scope to subscribe to.
|
||||
|
||||
Specifying which scopes to subscribe for the flight-recorder can be done using
|
||||
:samp:`-f|--flight-rec-scopes`. By default, only the 'log' scope is subscribed
|
||||
to. See :ref:`debugging flight recorder` on how retrieve the contents of the
|
||||
flight recorder in case Weston dies/crashes unexpectedly.
|
||||
:samp:`--flight-rec-scopes`. By default, the 'log' scope and 'drm-backend' are
|
||||
the scopes subscribed to.
|
||||
|
||||
weston-debug protocol
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
@ -179,17 +178,6 @@ The following illustrates how to use it:
|
|||
./weston-debug timeline > log.json
|
||||
./wesgr -i log.json -o log.svg
|
||||
|
||||
Weston has experimental support for `Perfetto <https://perfetto.dev>`_ for
|
||||
performance profiling. It can be enabled by using `-Dperfetto=true` during
|
||||
the meson invocation to configure the build.
|
||||
|
||||
If Perfetto support is built in, timeline points are added to Perfetto tracks
|
||||
when Perfetto is running, even when the 'timeline' scope is not enabled.
|
||||
|
||||
For capturing a trace you can use the supplied
|
||||
`out of process trace <https://gitlab.freedesktop.org/wayland/weston/-/tree/main/doc/perfetto/perfetto_out_of_process_trace.cfg>`_.
|
||||
config file.
|
||||
|
||||
Inserting timeline points
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
@ -198,13 +186,6 @@ take the :type:`weston_compositor` instance, followed by the name of the
|
|||
timeline point. What follows next is a variable number of arguments, which
|
||||
**must** end with the macro :c:macro:`TLP_END`.
|
||||
|
||||
Adding Perfetto trace points
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In addition to timeline points, Perfetto can also display timing information
|
||||
for individual functions. The easiest way to add profiling data for a function
|
||||
is to insert the :c:macro:`WESTON_TRACE_FUNC` at the top of the function.
|
||||
|
||||
Debug protocol API
|
||||
------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
files = [
|
||||
'compositor.rst',
|
||||
'head.rst',
|
||||
'debug-flight-recorder.rst',
|
||||
'log.rst',
|
||||
'output.rst',
|
||||
'output-management.rst',
|
||||
|
|
|
|||
|
|
@ -35,15 +35,12 @@ stitching them together is performed by a *renderer*. By doing so, it is
|
|||
compositing all surfaces into a single image, which is being handed out to a
|
||||
back-end, and finally, displayed on the screen.
|
||||
|
||||
libweston provides multiple useful renderers. There are
|
||||
`OpenGL ES <https://www.khronos.org/opengles/>`_ and
|
||||
`Vulkan <https://www.vulkan.org/>`_ renderers, which will often be accelerated
|
||||
by your GPU when suitable drivers are installed.
|
||||
Another uses the `Pixman <http://www.pixman.org>`_ library which is entirely
|
||||
CPU (software) rendered.
|
||||
|
||||
You can select between these with the ``--renderer=gl``, ``--renderer=vulkan``
|
||||
and ``--renderer=pixman`` arguments when starting Weston.
|
||||
libweston provides two useful renderers. One uses
|
||||
`OpenGL ES <https://www.khronos.org/opengles/>`_, which will often be accelerated
|
||||
by your GPU when suitable drivers are installed. The other uses the
|
||||
`Pixman <http://www.pixman.org>`_ library which is entirely CPU (software)
|
||||
rendered. You can select between these with the ``--renderer=gl`` and
|
||||
``--renderer=pixman`` arguments when starting Weston.
|
||||
|
||||
Multi-back-end support
|
||||
----------------------
|
||||
|
|
|
|||
|
|
@ -90,8 +90,7 @@ Standalone tests
|
|||
Standalone tests do not have a fixture setup function defined in the test
|
||||
program or the fixture setup function calls
|
||||
:func:`weston_test_harness_execute_standalone` explicitly. All test cases must
|
||||
be defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
|
||||
return a value from :type:`test_result_code`.
|
||||
be defined with :c:func:`TEST` or :c:func:`TEST_P`.
|
||||
|
||||
This is the simplest possible test example:
|
||||
|
||||
|
|
@ -99,7 +98,7 @@ This is the simplest possible test example:
|
|||
|
||||
TEST(always_success)
|
||||
{
|
||||
return RESULT_OK;
|
||||
/* true */
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -111,8 +110,7 @@ Plugin tests
|
|||
Plugin tests must have a fixture setup function that calls
|
||||
:func:`weston_test_harness_execute_as_plugin`. All test cases must be defined
|
||||
with :c:func:`PLUGIN_TEST` which declares an implicit function argument
|
||||
:type:`weston_compositor` ``*compositor``. Each such function must
|
||||
return a value from :type:`test_result_code`.
|
||||
:type:`weston_compositor` ``*compositor``.
|
||||
|
||||
The compositor fixture manufactures the necessary environment variables and the
|
||||
command line argument array to launch Weston, and calls :func:`wet_main`
|
||||
|
|
@ -139,7 +137,6 @@ This is an example of a plugin test that just logs a line:
|
|||
{
|
||||
/* struct weston_compositor *compositor; */
|
||||
testlog("Got compositor %p\n", compositor);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -150,8 +147,7 @@ Client tests
|
|||
|
||||
Plugin tests must have a fixture setup function that calls
|
||||
:func:`weston_test_harness_execute_as_client`. All test cases must be
|
||||
defined with :c:func:`TEST` or :c:func:`TEST_P`, and each such function must
|
||||
return a value from :type:`test_result_code`.
|
||||
defined with :c:func:`TEST` or :c:func:`TEST_P`.
|
||||
|
||||
The compositor fixture manufactures the necessary environment variables and the
|
||||
command line argument array to launch Weston, and calls :func:`wet_main`
|
||||
|
|
@ -206,7 +202,6 @@ clients:
|
|||
|
||||
expect_protocol_error(client, &wp_viewport_interface,
|
||||
WP_VIEWPORT_ERROR_BAD_VALUE);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
TEST(test_roundtrip)
|
||||
|
|
@ -215,7 +210,6 @@ clients:
|
|||
|
||||
client = create_client_and_test_surface(100, 50, 123, 77);
|
||||
client_roundtrip(client);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -263,6 +257,15 @@ type of tests to keep the fixture setup simple. See
|
|||
:ref:`test-suite-standalone`, :ref:`test-suite-plugin` and
|
||||
:ref:`test-suite-client` how to set up each type in a test program.
|
||||
|
||||
.. note::
|
||||
|
||||
**TODO:** Currently it is not possible to gracefully skip or fail a test.
|
||||
You can skip with ``exit(RESULT_SKIP)`` but that will quit the whole test
|
||||
program and all defined tests that were not ran yet will be counted as
|
||||
failed. You can fail a test by any means, e.g. ``exit(RESULT_FAIL)``, but
|
||||
the same caveat applies. Succeeded tests must simply return and not call any
|
||||
exit function.
|
||||
|
||||
|
||||
.. toctree::
|
||||
:hidden:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#include <libweston/config-parser.h>
|
||||
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/string-helpers.h"
|
||||
#include "weston-private.h"
|
||||
|
||||
struct {
|
||||
|
|
@ -65,10 +64,12 @@ get_backend_from_string(const char *name,
|
|||
return false;
|
||||
}
|
||||
|
||||
static const struct weston_enum_map renderer_name_map[] = {
|
||||
struct {
|
||||
char *name;
|
||||
enum weston_renderer_type renderer;
|
||||
} renderer_name_map[] = {
|
||||
{ "auto", WESTON_RENDERER_AUTO },
|
||||
{ "gl", WESTON_RENDERER_GL },
|
||||
{ "vulkan", WESTON_RENDERER_VULKAN },
|
||||
{ "noop", WESTON_RENDERER_NOOP },
|
||||
{ "pixman", WESTON_RENDERER_PIXMAN },
|
||||
};
|
||||
|
|
@ -77,15 +78,16 @@ bool
|
|||
get_renderer_from_string(const char *name,
|
||||
enum weston_renderer_type *renderer)
|
||||
{
|
||||
const struct weston_enum_map *entry;
|
||||
size_t i;
|
||||
|
||||
if (!name)
|
||||
name = "auto";
|
||||
|
||||
entry = weston_enum_map_find_name(renderer_name_map, name);
|
||||
if (entry) {
|
||||
*renderer = entry->value;
|
||||
return true;
|
||||
for (i = 0; i < ARRAY_LENGTH(renderer_name_map); i++) {
|
||||
if (strcmp(name, renderer_name_map[i].name) == 0) {
|
||||
*renderer = renderer_name_map[i].renderer;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
1242
frontend/main.c
1242
frontend/main.c
File diff suppressed because it is too large
Load diff
|
|
@ -16,7 +16,6 @@ deps_weston = [
|
|||
dep_libevdev,
|
||||
dep_libdl,
|
||||
dep_threads,
|
||||
dep_libdisplay_info,
|
||||
]
|
||||
|
||||
if get_option('xwayland')
|
||||
|
|
@ -68,6 +67,32 @@ install_data(
|
|||
install_dir: dir_data / 'wayland-sessions'
|
||||
)
|
||||
|
||||
if get_option('screenshare')
|
||||
srcs_screenshare = [
|
||||
'screen-share.c',
|
||||
fullscreen_shell_unstable_v1_client_protocol_h,
|
||||
fullscreen_shell_unstable_v1_protocol_c,
|
||||
]
|
||||
deps_screenshare = [
|
||||
dep_libexec_weston,
|
||||
dep_libshared,
|
||||
dep_libweston_public,
|
||||
dep_libweston_private_h, # XXX: https://gitlab.freedesktop.org/wayland/weston/issues/292
|
||||
dep_wayland_client,
|
||||
]
|
||||
plugin_screenshare = shared_library(
|
||||
'screen-share',
|
||||
srcs_screenshare,
|
||||
include_directories: common_inc,
|
||||
dependencies: deps_screenshare,
|
||||
name_prefix: '',
|
||||
install: true,
|
||||
install_dir: dir_module_weston,
|
||||
install_rpath: '$ORIGIN'
|
||||
)
|
||||
env_modmap += 'screen-share.so=@0@;'.format(plugin_screenshare.full_path())
|
||||
endif
|
||||
|
||||
if get_option('systemd')
|
||||
dep_libsystemd = dependency('libsystemd', required: false)
|
||||
if not dep_libsystemd.found()
|
||||
|
|
|
|||
1247
frontend/screen-share.c
Normal file
1247
frontend/screen-share.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -36,6 +36,11 @@ bool
|
|||
get_renderer_from_string(const char *name,
|
||||
enum weston_renderer_type *renderer);
|
||||
|
||||
int
|
||||
wet_output_set_color_characteristics(struct weston_output *output,
|
||||
struct weston_config *wc,
|
||||
struct weston_config_section *section);
|
||||
|
||||
int
|
||||
wet_output_set_eotf_mode(struct weston_output *output,
|
||||
struct weston_config_section *section,
|
||||
|
|
@ -48,8 +53,3 @@ wet_output_set_colorimetry_mode(struct weston_output *output,
|
|||
|
||||
typedef void (*wet_head_additional_setup)(struct weston_head *head,
|
||||
struct weston_head *head_to_mirror);
|
||||
|
||||
struct weston_color_profile *
|
||||
wet_create_output_color_profile(struct weston_output *output,
|
||||
struct weston_config *wc,
|
||||
const char *prof_name);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ struct screenshooter {
|
|||
struct wl_client *client;
|
||||
struct wl_listener client_destroy_listener;
|
||||
struct wl_listener compositor_destroy_listener;
|
||||
struct weston_recorder *recorder;
|
||||
struct wl_listener authorization;
|
||||
};
|
||||
|
||||
|
|
@ -79,6 +80,30 @@ screenshooter_binding(struct weston_keyboard *keyboard,
|
|||
&shooter->client_destroy_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
recorder_binding(struct weston_keyboard *keyboard, const struct timespec *time,
|
||||
uint32_t key, void *data)
|
||||
{
|
||||
struct weston_compositor *ec = keyboard->seat->compositor;
|
||||
struct weston_output *output;
|
||||
struct screenshooter *shooter = data;
|
||||
struct weston_recorder *recorder = shooter->recorder;;
|
||||
static const char filename[] = "capture.wcap";
|
||||
|
||||
if (recorder) {
|
||||
weston_recorder_stop(recorder);
|
||||
shooter->recorder = NULL;
|
||||
} else {
|
||||
if (keyboard->focus && keyboard->focus->output)
|
||||
output = keyboard->focus->output;
|
||||
else
|
||||
output = container_of(ec->output_list.next,
|
||||
struct weston_output, link);
|
||||
|
||||
shooter->recorder = weston_recorder_start(output, filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
authorize_screenshooter(struct wl_listener *l,
|
||||
struct weston_output_capture_attempt *att)
|
||||
|
|
@ -116,6 +141,8 @@ screenshooter_create(struct weston_compositor *ec)
|
|||
|
||||
weston_compositor_add_key_binding(ec, KEY_S, MODIFIER_SUPER,
|
||||
screenshooter_binding, shooter);
|
||||
weston_compositor_add_key_binding(ec, KEY_R, MODIFIER_SUPER,
|
||||
recorder_binding, shooter);
|
||||
|
||||
shooter->compositor_destroy_listener.notify = screenshooter_destroy;
|
||||
wl_signal_add(&ec->destroy_signal,
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
|||
struct weston_config *config = wet_get_config(wxw->compositor);
|
||||
struct weston_config_section *section;
|
||||
struct wl_client *client;
|
||||
struct weston_client *wcl;
|
||||
struct wl_event_loop *loop;
|
||||
struct custom_env child_env;
|
||||
int no_cloexec_fds[5];
|
||||
|
|
@ -186,10 +185,6 @@ spawn_xserver(void *user_data, const char *display, int abstract_fd, int unix_fd
|
|||
goto err_proc;
|
||||
}
|
||||
|
||||
wcl = weston_compositor_get_client(wxw->compositor, client);
|
||||
weston_client_set_internal_name(wcl, "(Xw)%" PRIu64,
|
||||
weston_client_get_internal_id(wcl));
|
||||
|
||||
wxw->wm_fd = x11_wm_socket.fds[0];
|
||||
|
||||
/* Now we can no longer fail, close the child end of our sockets */
|
||||
|
|
@ -265,10 +260,8 @@ wet_load_xwayland(struct weston_compositor *comp)
|
|||
wxw->compositor = comp;
|
||||
wxw->api = api;
|
||||
wxw->xwayland = xwayland;
|
||||
if (api->listen(xwayland, wxw, spawn_xserver) < 0) {
|
||||
free(wxw);
|
||||
if (api->listen(xwayland, wxw, spawn_xserver) < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return wxw;
|
||||
}
|
||||
|
|
|
|||
974
fullscreen-shell/fullscreen-shell.c
Normal file
974
fullscreen-shell/fullscreen-shell.c
Normal file
|
|
@ -0,0 +1,974 @@
|
|||
/*
|
||||
* Copyright © 2013 Jason Ekstrand
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <libweston/libweston.h>
|
||||
#include "frontend/weston.h"
|
||||
#include "fullscreen-shell-unstable-v1-server-protocol.h"
|
||||
#include "shared/helpers.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
|
||||
struct fullscreen_shell {
|
||||
struct wl_client *client;
|
||||
struct wl_listener client_destroyed;
|
||||
struct wl_listener destroy_listener;
|
||||
struct weston_compositor *compositor;
|
||||
|
||||
struct weston_layer layer;
|
||||
struct wl_list output_list;
|
||||
struct wl_listener output_created_listener;
|
||||
struct wl_listener output_resized_listener;
|
||||
struct wl_listener output_moved_listener;
|
||||
|
||||
struct wl_listener seat_created_listener;
|
||||
|
||||
/* List of one surface per client, presented for the NULL output
|
||||
*
|
||||
* This is implemented as a list in case someone fixes the shell
|
||||
* implementation to support more than one client.
|
||||
*/
|
||||
struct wl_list default_surface_list; /* struct fs_client_surface::link */
|
||||
};
|
||||
|
||||
struct fs_output {
|
||||
struct fullscreen_shell *shell;
|
||||
struct wl_list link;
|
||||
|
||||
struct weston_output *output;
|
||||
struct wl_listener output_destroyed;
|
||||
|
||||
struct {
|
||||
struct weston_surface *surface;
|
||||
struct wl_listener surface_destroyed;
|
||||
struct wl_resource *mode_feedback;
|
||||
|
||||
int presented_for_mode;
|
||||
enum zwp_fullscreen_shell_v1_present_method method;
|
||||
int32_t framerate;
|
||||
} pending;
|
||||
|
||||
struct weston_surface *surface;
|
||||
struct wl_listener surface_destroyed;
|
||||
struct weston_view *view;
|
||||
struct weston_curtain *curtain;
|
||||
struct weston_transform transform; /* matrix from x, y */
|
||||
|
||||
int presented_for_mode;
|
||||
enum zwp_fullscreen_shell_v1_present_method method;
|
||||
uint32_t framerate;
|
||||
};
|
||||
|
||||
struct pointer_focus_listener {
|
||||
struct fullscreen_shell *shell;
|
||||
struct wl_listener pointer_focus;
|
||||
struct wl_listener seat_caps;
|
||||
struct wl_listener seat_destroyed;
|
||||
};
|
||||
|
||||
struct fs_client_surface {
|
||||
struct weston_surface *surface;
|
||||
enum zwp_fullscreen_shell_v1_present_method method;
|
||||
struct wl_list link; /* struct fullscreen_shell::default_surface_list */
|
||||
struct wl_listener surface_destroyed;
|
||||
};
|
||||
|
||||
static void
|
||||
remove_default_surface(struct fs_client_surface *surf)
|
||||
{
|
||||
wl_list_remove(&surf->surface_destroyed.link);
|
||||
wl_list_remove(&surf->link);
|
||||
free(surf);
|
||||
}
|
||||
|
||||
static void
|
||||
default_surface_destroy_listener(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_client_surface *surf;
|
||||
|
||||
surf = container_of(listener, struct fs_client_surface, surface_destroyed);
|
||||
|
||||
remove_default_surface(surf);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_default_surface(struct fullscreen_shell *shell, struct weston_surface *surface,
|
||||
enum zwp_fullscreen_shell_v1_present_method method)
|
||||
{
|
||||
struct fs_client_surface *surf, *prev = NULL;
|
||||
|
||||
if (!wl_list_empty(&shell->default_surface_list))
|
||||
prev = container_of(shell->default_surface_list.prev,
|
||||
struct fs_client_surface, link);
|
||||
|
||||
if (prev)
|
||||
remove_default_surface(prev);
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
surf = zalloc(sizeof *surf);
|
||||
if (!surf)
|
||||
return;
|
||||
|
||||
surf->surface = surface;
|
||||
surf->method = method;
|
||||
|
||||
wl_list_insert(shell->default_surface_list.prev, &surf->link);
|
||||
|
||||
surf->surface_destroyed.notify = default_surface_destroy_listener;
|
||||
wl_signal_add(&surface->destroy_signal, &surf->surface_destroyed);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_focus_changed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_pointer *pointer = data;
|
||||
|
||||
if (pointer->focus && pointer->focus->surface->resource)
|
||||
weston_seat_set_keyboard_focus(pointer->seat, pointer->focus->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
seat_caps_changed(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct weston_seat *seat = data;
|
||||
struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
|
||||
struct weston_pointer *pointer = weston_seat_get_pointer(seat);
|
||||
struct pointer_focus_listener *listener;
|
||||
struct fs_output *fsout;
|
||||
|
||||
listener = container_of(l, struct pointer_focus_listener, seat_caps);
|
||||
|
||||
/* no pointer */
|
||||
if (pointer) {
|
||||
if (!listener->pointer_focus.link.prev) {
|
||||
wl_signal_add(&pointer->focus_signal,
|
||||
&listener->pointer_focus);
|
||||
}
|
||||
} else {
|
||||
if (listener->pointer_focus.link.prev) {
|
||||
wl_list_remove(&listener->pointer_focus.link);
|
||||
}
|
||||
}
|
||||
|
||||
if (keyboard && keyboard->focus != NULL) {
|
||||
wl_list_for_each(fsout, &listener->shell->output_list, link) {
|
||||
if (fsout->surface) {
|
||||
weston_seat_set_keyboard_focus(seat, fsout->surface);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
seat_destroyed(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct pointer_focus_listener *listener;
|
||||
|
||||
listener = container_of(l, struct pointer_focus_listener,
|
||||
seat_destroyed);
|
||||
|
||||
free(listener);
|
||||
}
|
||||
|
||||
static void
|
||||
seat_created(struct wl_listener *l, void *data)
|
||||
{
|
||||
struct weston_seat *seat = data;
|
||||
struct pointer_focus_listener *listener;
|
||||
|
||||
listener = zalloc(sizeof *listener);
|
||||
if (!listener)
|
||||
return;
|
||||
|
||||
listener->shell = container_of(l, struct fullscreen_shell,
|
||||
seat_created_listener);
|
||||
listener->pointer_focus.notify = pointer_focus_changed;
|
||||
listener->seat_caps.notify = seat_caps_changed;
|
||||
listener->seat_destroyed.notify = seat_destroyed;
|
||||
|
||||
wl_signal_add(&seat->destroy_signal, &listener->seat_destroyed);
|
||||
wl_signal_add(&seat->updated_caps_signal, &listener->seat_caps);
|
||||
|
||||
seat_caps_changed(&listener->seat_caps, seat);
|
||||
}
|
||||
|
||||
static void
|
||||
black_surface_committed(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
}
|
||||
|
||||
static struct weston_curtain *
|
||||
create_curtain(struct weston_compositor *ec, struct fs_output *fsout,
|
||||
struct weston_coord_global pos, int w, int h)
|
||||
{
|
||||
struct weston_curtain_params curtain_params = {
|
||||
.r = 0.0, .g = 0.0, .b = 0.0, .a = 1.0,
|
||||
.pos = pos, .width = w, .height = h,
|
||||
.surface_committed = black_surface_committed,
|
||||
.get_label = NULL,
|
||||
.surface_private = fsout,
|
||||
.capture_input = true,
|
||||
};
|
||||
struct weston_curtain *curtain;
|
||||
|
||||
curtain = weston_shell_utils_curtain_create(ec, &curtain_params);
|
||||
if (!curtain) {
|
||||
weston_log("no memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return curtain;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_set_surface(struct fs_output *fsout, struct weston_surface *surface,
|
||||
enum zwp_fullscreen_shell_v1_present_method method,
|
||||
int32_t framerate, int presented_for_mode);
|
||||
static void
|
||||
fs_output_apply_pending(struct fs_output *fsout);
|
||||
static void
|
||||
fs_output_clear_pending(struct fs_output *fsout);
|
||||
|
||||
static void
|
||||
fs_output_destroy(struct fs_output *fsout)
|
||||
{
|
||||
fs_output_set_surface(fsout, NULL, 0, 0, 0);
|
||||
fs_output_clear_pending(fsout);
|
||||
|
||||
weston_shell_utils_curtain_destroy(fsout->curtain);
|
||||
wl_list_remove(&fsout->link);
|
||||
|
||||
if (fsout->output)
|
||||
wl_list_remove(&fsout->output_destroyed.link);
|
||||
free(fsout);
|
||||
}
|
||||
|
||||
static void
|
||||
output_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *output = container_of(listener,
|
||||
struct fs_output,
|
||||
output_destroyed);
|
||||
fs_output_destroy(output);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fsout = container_of(listener,
|
||||
struct fs_output,
|
||||
surface_destroyed);
|
||||
fsout->surface = NULL;
|
||||
fsout->view = NULL;
|
||||
wl_list_remove(&fsout->transform.link);
|
||||
wl_list_init(&fsout->transform.link);
|
||||
}
|
||||
|
||||
static void
|
||||
pending_surface_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fsout = container_of(listener,
|
||||
struct fs_output,
|
||||
pending.surface_destroyed);
|
||||
fsout->pending.surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
configure_presented_surface_internal(struct weston_surface *surface);
|
||||
|
||||
static struct fs_output *
|
||||
fs_output_create(struct fullscreen_shell *shell, struct weston_output *output)
|
||||
{
|
||||
struct weston_seat *seat;
|
||||
struct fs_output *fsout;
|
||||
struct fs_client_surface *surf;
|
||||
|
||||
fsout = zalloc(sizeof *fsout);
|
||||
if (!fsout)
|
||||
return NULL;
|
||||
|
||||
fsout->shell = shell;
|
||||
wl_list_insert(&shell->output_list, &fsout->link);
|
||||
wl_list_init(&fsout->transform.link);
|
||||
|
||||
fsout->output = output;
|
||||
fsout->output_destroyed.notify = output_destroyed;
|
||||
wl_signal_add(&output->destroy_signal, &fsout->output_destroyed);
|
||||
|
||||
fsout->surface_destroyed.notify = surface_destroyed;
|
||||
fsout->pending.surface_destroyed.notify = pending_surface_destroyed;
|
||||
fsout->curtain = create_curtain(shell->compositor, fsout,
|
||||
output->pos,
|
||||
output->width, output->height);
|
||||
weston_view_move_to_layer(fsout->curtain->view,
|
||||
&shell->layer.view_list);
|
||||
|
||||
if (!wl_list_empty(&shell->default_surface_list)) {
|
||||
surf = container_of(shell->default_surface_list.prev,
|
||||
struct fs_client_surface, link);
|
||||
|
||||
fs_output_set_surface(fsout, surf->surface, surf->method, 0, 0);
|
||||
configure_presented_surface_internal(surf->surface);
|
||||
|
||||
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
||||
struct weston_keyboard *keyboard =
|
||||
weston_seat_get_keyboard(seat);
|
||||
|
||||
if (keyboard && !keyboard->focus)
|
||||
weston_seat_set_keyboard_focus(seat, surf->surface);
|
||||
}
|
||||
}
|
||||
|
||||
return fsout;
|
||||
}
|
||||
|
||||
static struct fs_output *
|
||||
fs_output_for_output(struct weston_output *output)
|
||||
{
|
||||
struct wl_listener *listener;
|
||||
|
||||
if (!output)
|
||||
return NULL;
|
||||
|
||||
listener = wl_signal_get(&output->destroy_signal, output_destroyed);
|
||||
|
||||
return container_of(listener, struct fs_output, output_destroyed);
|
||||
}
|
||||
|
||||
static void
|
||||
restore_output_mode(struct weston_output *output)
|
||||
{
|
||||
if (output && output->original_mode)
|
||||
weston_output_mode_switch_to_native(output);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_scale_view(struct fs_output *fsout, float width, float height)
|
||||
{
|
||||
int32_t surf_x, surf_y, surf_width, surf_height;
|
||||
struct weston_matrix *matrix;
|
||||
struct weston_view *view = fsout->view;
|
||||
struct weston_output *output = fsout->output;
|
||||
struct weston_coord_global pos = fsout->output->pos;
|
||||
|
||||
weston_shell_utils_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y,
|
||||
&surf_width, &surf_height);
|
||||
|
||||
if (output->width == surf_width && output->height == surf_height) {
|
||||
pos.c.x -= surf_x;
|
||||
pos.c.y -= surf_y;
|
||||
weston_view_set_position(view, pos);
|
||||
weston_view_remove_transform(fsout->view, &fsout->transform);
|
||||
} else {
|
||||
matrix = &fsout->transform.matrix;
|
||||
weston_matrix_init(matrix);
|
||||
|
||||
weston_matrix_scale(matrix, width / surf_width,
|
||||
height / surf_height, 1);
|
||||
weston_view_add_transform(fsout->view,
|
||||
&fsout->view->geometry.transformation_list,
|
||||
&fsout->transform);
|
||||
|
||||
pos.c.x += (output->width - width) / 2 - surf_x;
|
||||
pos.c.y += (output->height - height) / 2 - surf_y;
|
||||
weston_view_set_position(view, pos);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_configure(struct fs_output *fsout, struct weston_surface *surface);
|
||||
|
||||
static void
|
||||
fs_output_configure_simple(struct fs_output *fsout,
|
||||
struct weston_surface *configured_surface)
|
||||
{
|
||||
struct weston_output *output = fsout->output;
|
||||
float output_aspect, surface_aspect;
|
||||
int32_t surf_x, surf_y, surf_width, surf_height;
|
||||
struct weston_coord_global pos;
|
||||
|
||||
if (fsout->pending.surface == configured_surface)
|
||||
fs_output_apply_pending(fsout);
|
||||
|
||||
assert(fsout->view);
|
||||
|
||||
restore_output_mode(fsout->output);
|
||||
|
||||
wl_list_remove(&fsout->transform.link);
|
||||
wl_list_init(&fsout->transform.link);
|
||||
|
||||
weston_shell_utils_subsurfaces_boundingbox(fsout->view->surface,
|
||||
&surf_x, &surf_y,
|
||||
&surf_width, &surf_height);
|
||||
|
||||
output_aspect = (float) output->width / (float) output->height;
|
||||
surface_aspect = (float) surf_width / (float) surf_height;
|
||||
|
||||
switch (fsout->method) {
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER:
|
||||
weston_shell_utils_center_on_output(fsout->view, fsout->output);
|
||||
break;
|
||||
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM:
|
||||
if (output_aspect < surface_aspect)
|
||||
fs_output_scale_view(fsout,
|
||||
output->width,
|
||||
output->width / surface_aspect);
|
||||
else
|
||||
fs_output_scale_view(fsout,
|
||||
output->height * surface_aspect,
|
||||
output->height);
|
||||
break;
|
||||
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM_CROP:
|
||||
if (output_aspect < surface_aspect)
|
||||
fs_output_scale_view(fsout,
|
||||
output->height * surface_aspect,
|
||||
output->height);
|
||||
else
|
||||
fs_output_scale_view(fsout,
|
||||
output->width,
|
||||
output->width / surface_aspect);
|
||||
break;
|
||||
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_STRETCH:
|
||||
fs_output_scale_view(fsout, output->width, output->height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
pos = fsout->output->pos;
|
||||
pos.c.x -= surf_x;
|
||||
pos.c.y -= surf_y;
|
||||
weston_view_set_position(fsout->curtain->view, pos);
|
||||
weston_surface_set_size(fsout->curtain->view->surface,
|
||||
fsout->output->width,
|
||||
fsout->output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_configure_for_mode(struct fs_output *fsout,
|
||||
struct weston_surface *configured_surface)
|
||||
{
|
||||
int32_t surf_x, surf_y, surf_width, surf_height;
|
||||
struct weston_mode mode;
|
||||
struct weston_coord_global pos;
|
||||
int ret;
|
||||
|
||||
if (fsout->pending.surface != configured_surface) {
|
||||
/* Nothing to really reconfigure. We'll just recenter the
|
||||
* view in case they played with subsurfaces */
|
||||
weston_shell_utils_center_on_output(fsout->view, fsout->output);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We have a pending surface */
|
||||
weston_shell_utils_subsurfaces_boundingbox(fsout->pending.surface,
|
||||
&surf_x, &surf_y,
|
||||
&surf_width, &surf_height);
|
||||
|
||||
/* The actual output mode is in physical units. We need to
|
||||
* transform the surface size to physical unit size by flipping and
|
||||
* possibly scaling it.
|
||||
*/
|
||||
switch (fsout->output->transform) {
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
mode.width = surf_height * fsout->output->native_scale;
|
||||
mode.height = surf_width * fsout->output->native_scale;
|
||||
break;
|
||||
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
default:
|
||||
mode.width = surf_width * fsout->output->native_scale;
|
||||
mode.height = surf_height * fsout->output->native_scale;
|
||||
}
|
||||
mode.flags = 0;
|
||||
mode.refresh = fsout->pending.framerate;
|
||||
|
||||
ret = weston_output_mode_switch_to_temporary(fsout->output, &mode,
|
||||
fsout->output->native_scale);
|
||||
|
||||
if (ret != 0) {
|
||||
/* The mode switch failed. Clear the pending and
|
||||
* reconfigure as per normal */
|
||||
if (fsout->pending.mode_feedback) {
|
||||
zwp_fullscreen_shell_mode_feedback_v1_send_mode_failed(
|
||||
fsout->pending.mode_feedback);
|
||||
wl_resource_destroy(fsout->pending.mode_feedback);
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
fs_output_clear_pending(fsout);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fsout->pending.mode_feedback) {
|
||||
zwp_fullscreen_shell_mode_feedback_v1_send_mode_successful(
|
||||
fsout->pending.mode_feedback);
|
||||
wl_resource_destroy(fsout->pending.mode_feedback);
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
fs_output_apply_pending(fsout);
|
||||
|
||||
pos = fsout->output->pos;
|
||||
pos.c.x -= surf_x;
|
||||
pos.c.y -= surf_y;
|
||||
weston_view_set_position(fsout->view, pos);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_configure(struct fs_output *fsout,
|
||||
struct weston_surface *surface)
|
||||
{
|
||||
if (fsout->pending.surface == surface) {
|
||||
if (fsout->pending.presented_for_mode)
|
||||
fs_output_configure_for_mode(fsout, surface);
|
||||
else
|
||||
fs_output_configure_simple(fsout, surface);
|
||||
} else {
|
||||
if (fsout->presented_for_mode)
|
||||
fs_output_configure_for_mode(fsout, surface);
|
||||
else
|
||||
fs_output_configure_simple(fsout, surface);
|
||||
}
|
||||
|
||||
weston_output_schedule_repaint(fsout->output);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_presented_surface(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
{
|
||||
configure_presented_surface_internal(surface);
|
||||
}
|
||||
|
||||
static void
|
||||
configure_presented_surface_internal(struct weston_surface *surface)
|
||||
{
|
||||
struct fullscreen_shell *shell = surface->committed_private;
|
||||
struct fs_output *fsout;
|
||||
|
||||
if (surface->committed != configure_presented_surface)
|
||||
return;
|
||||
|
||||
if (!weston_surface_has_content(surface))
|
||||
return;
|
||||
|
||||
if (!weston_surface_is_mapped(surface))
|
||||
weston_surface_map(surface);
|
||||
|
||||
wl_list_for_each(fsout, &shell->output_list, link)
|
||||
if (fsout->surface == surface ||
|
||||
fsout->pending.surface == surface)
|
||||
fs_output_configure(fsout, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_apply_pending(struct fs_output *fsout)
|
||||
{
|
||||
assert(fsout->pending.surface);
|
||||
|
||||
if (!weston_surface_is_mapped(fsout->pending.surface) &&
|
||||
!weston_surface_has_content(fsout->pending.surface))
|
||||
return;
|
||||
|
||||
if (fsout->surface && fsout->surface != fsout->pending.surface) {
|
||||
wl_list_remove(&fsout->surface_destroyed.link);
|
||||
|
||||
weston_view_destroy(fsout->view);
|
||||
fsout->view = NULL;
|
||||
|
||||
if (wl_list_empty(&fsout->surface->views)) {
|
||||
fsout->surface->committed = NULL;
|
||||
fsout->surface->committed_private = NULL;
|
||||
}
|
||||
|
||||
fsout->surface = NULL;
|
||||
}
|
||||
|
||||
fsout->method = fsout->pending.method;
|
||||
fsout->framerate = fsout->pending.framerate;
|
||||
fsout->presented_for_mode = fsout->pending.presented_for_mode;
|
||||
|
||||
if (fsout->surface != fsout->pending.surface) {
|
||||
fsout->surface = fsout->pending.surface;
|
||||
if (!weston_surface_is_mapped(fsout->surface))
|
||||
weston_surface_map(fsout->surface);
|
||||
|
||||
fsout->view = weston_view_create(fsout->surface);
|
||||
if (!fsout->view) {
|
||||
weston_log("no memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_add(&fsout->surface->destroy_signal,
|
||||
&fsout->surface_destroyed);
|
||||
weston_view_move_to_layer(fsout->view,
|
||||
&fsout->shell->layer.view_list);
|
||||
}
|
||||
|
||||
fs_output_clear_pending(fsout);
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_clear_pending(struct fs_output *fsout)
|
||||
{
|
||||
if (!fsout->pending.surface)
|
||||
return;
|
||||
|
||||
if (fsout->pending.mode_feedback) {
|
||||
zwp_fullscreen_shell_mode_feedback_v1_send_present_cancelled(
|
||||
fsout->pending.mode_feedback);
|
||||
wl_resource_destroy(fsout->pending.mode_feedback);
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&fsout->pending.surface_destroyed.link);
|
||||
fsout->pending.surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fs_output_set_surface(struct fs_output *fsout, struct weston_surface *surface,
|
||||
enum zwp_fullscreen_shell_v1_present_method method,
|
||||
int32_t framerate, int presented_for_mode)
|
||||
{
|
||||
fs_output_clear_pending(fsout);
|
||||
|
||||
if (surface) {
|
||||
if (!surface->committed) {
|
||||
surface->committed = configure_presented_surface;
|
||||
surface->committed_private = fsout->shell;
|
||||
}
|
||||
|
||||
fsout->pending.surface = surface;
|
||||
wl_signal_add(&fsout->pending.surface->destroy_signal,
|
||||
&fsout->pending.surface_destroyed);
|
||||
|
||||
fsout->pending.method = method;
|
||||
fsout->pending.framerate = framerate;
|
||||
fsout->pending.presented_for_mode = presented_for_mode;
|
||||
} else if (fsout->surface) {
|
||||
/* we clear immediately */
|
||||
wl_list_remove(&fsout->surface_destroyed.link);
|
||||
|
||||
weston_view_destroy(fsout->view);
|
||||
fsout->view = NULL;
|
||||
|
||||
if (wl_list_empty(&fsout->surface->views)) {
|
||||
fsout->surface->committed = NULL;
|
||||
fsout->surface->committed_private = NULL;
|
||||
}
|
||||
|
||||
fsout->surface = NULL;
|
||||
|
||||
weston_output_schedule_repaint(fsout->output);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_release(struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_present_surface(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *surface_res,
|
||||
uint32_t method,
|
||||
struct wl_resource *output_res)
|
||||
{
|
||||
struct fullscreen_shell *shell =
|
||||
wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface;
|
||||
struct weston_seat *seat;
|
||||
struct fs_output *fsout;
|
||||
|
||||
surface = surface_res ? wl_resource_get_user_data(surface_res) : NULL;
|
||||
|
||||
switch(method) {
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_DEFAULT:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_CENTER:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_ZOOM_CROP:
|
||||
case ZWP_FULLSCREEN_SHELL_V1_PRESENT_METHOD_STRETCH:
|
||||
break;
|
||||
default:
|
||||
wl_resource_post_error(resource,
|
||||
ZWP_FULLSCREEN_SHELL_V1_ERROR_INVALID_METHOD,
|
||||
"Invalid presentation method");
|
||||
}
|
||||
|
||||
if (output_res) {
|
||||
struct weston_head *head =
|
||||
weston_head_from_resource(output_res);
|
||||
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
fsout = fs_output_for_output(head->output);
|
||||
fs_output_set_surface(fsout, surface, method, 0, 0);
|
||||
} else {
|
||||
replace_default_surface(shell, surface, method);
|
||||
|
||||
wl_list_for_each(fsout, &shell->output_list, link)
|
||||
fs_output_set_surface(fsout, surface, method, 0, 0);
|
||||
}
|
||||
|
||||
if (surface) {
|
||||
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
||||
struct weston_keyboard *keyboard =
|
||||
weston_seat_get_keyboard(seat);
|
||||
|
||||
if (keyboard && !keyboard->focus)
|
||||
weston_seat_set_keyboard_focus(seat, surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mode_feedback_destroyed(struct wl_resource *resource)
|
||||
{
|
||||
struct fs_output *fsout = wl_resource_get_user_data(resource);
|
||||
|
||||
fsout->pending.mode_feedback = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_present_surface_for_mode(struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *surface_res,
|
||||
struct wl_resource *output_res,
|
||||
int32_t framerate,
|
||||
uint32_t feedback_id)
|
||||
{
|
||||
struct fullscreen_shell *shell =
|
||||
wl_resource_get_user_data(resource);
|
||||
struct weston_surface *surface;
|
||||
struct weston_seat *seat;
|
||||
struct fs_output *fsout;
|
||||
struct weston_head *head = weston_head_from_resource(output_res);
|
||||
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
fsout = fs_output_for_output(head->output);
|
||||
|
||||
if (surface_res == NULL) {
|
||||
fs_output_set_surface(fsout, NULL, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
surface = wl_resource_get_user_data(surface_res);
|
||||
fs_output_set_surface(fsout, surface, 0, framerate, 1);
|
||||
|
||||
fsout->pending.mode_feedback =
|
||||
wl_resource_create(client,
|
||||
&zwp_fullscreen_shell_mode_feedback_v1_interface,
|
||||
1, feedback_id);
|
||||
wl_resource_set_implementation(fsout->pending.mode_feedback, NULL,
|
||||
fsout, mode_feedback_destroyed);
|
||||
|
||||
wl_list_for_each(seat, &shell->compositor->seat_list, link) {
|
||||
struct weston_keyboard *keyboard =
|
||||
weston_seat_get_keyboard(seat);
|
||||
|
||||
if (keyboard && !keyboard->focus)
|
||||
weston_seat_set_keyboard_focus(seat, surface);
|
||||
}
|
||||
}
|
||||
|
||||
struct zwp_fullscreen_shell_v1_interface fullscreen_shell_implementation = {
|
||||
fullscreen_shell_release,
|
||||
fullscreen_shell_present_surface,
|
||||
fullscreen_shell_present_surface_for_mode,
|
||||
};
|
||||
|
||||
static void
|
||||
output_geometry_changed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fsout;
|
||||
|
||||
fsout = fs_output_for_output(data);
|
||||
if (fsout && fsout->surface)
|
||||
fs_output_configure(fsout, fsout->surface);
|
||||
}
|
||||
|
||||
static void
|
||||
output_created(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fullscreen_shell *shell;
|
||||
|
||||
shell = container_of(listener, struct fullscreen_shell,
|
||||
output_created_listener);
|
||||
|
||||
fs_output_create(shell, data);
|
||||
}
|
||||
|
||||
static void
|
||||
client_destroyed(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fullscreen_shell *shell = container_of(listener,
|
||||
struct fullscreen_shell,
|
||||
client_destroyed);
|
||||
shell->client = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
bind_fullscreen_shell(struct wl_client *client, void *data, uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct fullscreen_shell *shell = data;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (shell->client != NULL && shell->client != client)
|
||||
return;
|
||||
else if (shell->client == NULL) {
|
||||
shell->client = client;
|
||||
wl_client_add_destroy_listener(client, &shell->client_destroyed);
|
||||
}
|
||||
|
||||
resource = wl_resource_create(client,
|
||||
&zwp_fullscreen_shell_v1_interface,
|
||||
1, id);
|
||||
wl_resource_set_implementation(resource,
|
||||
&fullscreen_shell_implementation,
|
||||
shell, NULL);
|
||||
|
||||
if (shell->compositor->capabilities & WESTON_CAP_CURSOR_PLANE)
|
||||
zwp_fullscreen_shell_v1_send_capability(resource,
|
||||
ZWP_FULLSCREEN_SHELL_V1_CAPABILITY_CURSOR_PLANE);
|
||||
|
||||
if (shell->compositor->capabilities & WESTON_CAP_ARBITRARY_MODES)
|
||||
zwp_fullscreen_shell_v1_send_capability(resource,
|
||||
ZWP_FULLSCREEN_SHELL_V1_CAPABILITY_ARBITRARY_MODES);
|
||||
}
|
||||
|
||||
static void
|
||||
fullscreen_shell_destroy(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct fs_output *fs_output, *fs_output_next;
|
||||
struct fs_client_surface *surf;
|
||||
struct fullscreen_shell *shell =
|
||||
container_of(listener, struct fullscreen_shell, destroy_listener);
|
||||
|
||||
/* remove the curtain(s) */
|
||||
wl_list_for_each_safe(fs_output, fs_output_next, &shell->output_list, link)
|
||||
fs_output_destroy(fs_output);
|
||||
|
||||
wl_list_remove(&shell->output_created_listener.link);
|
||||
wl_list_remove(&shell->output_moved_listener.link);
|
||||
wl_list_remove(&shell->output_resized_listener.link);
|
||||
|
||||
if (!wl_list_empty(&shell->default_surface_list)) {
|
||||
surf = container_of(shell->default_surface_list.prev,
|
||||
struct fs_client_surface, link);
|
||||
remove_default_surface(surf);
|
||||
}
|
||||
|
||||
weston_layer_fini(&shell->layer);
|
||||
free(shell);
|
||||
}
|
||||
|
||||
WL_EXPORT int
|
||||
wet_shell_init(struct weston_compositor *compositor,
|
||||
int *argc, char *argv[])
|
||||
{
|
||||
struct fullscreen_shell *shell;
|
||||
struct weston_seat *seat;
|
||||
struct weston_output *output;
|
||||
|
||||
shell = zalloc(sizeof *shell);
|
||||
if (shell == NULL)
|
||||
return -1;
|
||||
|
||||
|
||||
shell->compositor = compositor;
|
||||
|
||||
if (!weston_compositor_add_destroy_listener_once(compositor,
|
||||
&shell->destroy_listener,
|
||||
fullscreen_shell_destroy)) {
|
||||
free(shell);
|
||||
return 0;
|
||||
}
|
||||
|
||||
wl_list_init(&shell->default_surface_list);
|
||||
|
||||
shell->client_destroyed.notify = client_destroyed;
|
||||
|
||||
weston_layer_init(&shell->layer, compositor);
|
||||
weston_layer_set_position(&shell->layer,
|
||||
WESTON_LAYER_POSITION_FULLSCREEN);
|
||||
|
||||
wl_list_init(&shell->output_list);
|
||||
shell->output_created_listener.notify = output_created;
|
||||
wl_signal_add(&compositor->output_created_signal,
|
||||
&shell->output_created_listener);
|
||||
wl_list_for_each(output, &compositor->output_list, link)
|
||||
fs_output_create(shell, output);
|
||||
|
||||
shell->output_resized_listener.notify = output_geometry_changed;
|
||||
wl_signal_add(&compositor->output_resized_signal,
|
||||
&shell->output_resized_listener);
|
||||
|
||||
shell->output_moved_listener.notify = output_geometry_changed;
|
||||
wl_signal_add(&compositor->output_moved_signal,
|
||||
&shell->output_moved_listener);
|
||||
|
||||
shell->seat_created_listener.notify = seat_created;
|
||||
wl_signal_add(&compositor->seat_created_signal,
|
||||
&shell->seat_created_listener);
|
||||
wl_list_for_each(seat, &compositor->seat_list, link)
|
||||
seat_created(&shell->seat_created_listener, seat);
|
||||
|
||||
wl_global_create(compositor->wl_display,
|
||||
&zwp_fullscreen_shell_v1_interface, 1, shell,
|
||||
bind_fullscreen_shell);
|
||||
|
||||
screenshooter_create(compositor);
|
||||
return 0;
|
||||
}
|
||||
20
fullscreen-shell/meson.build
Normal file
20
fullscreen-shell/meson.build
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
if get_option('shell-fullscreen')
|
||||
srcs_shell_fullscreen = [
|
||||
'fullscreen-shell.c',
|
||||
fullscreen_shell_unstable_v1_server_protocol_h,
|
||||
fullscreen_shell_unstable_v1_protocol_c,
|
||||
]
|
||||
deps_shell_fullscreen = [
|
||||
dep_libweston_public,
|
||||
dep_libexec_weston,
|
||||
]
|
||||
shared_library(
|
||||
'fullscreen-shell',
|
||||
srcs_shell_fullscreen,
|
||||
include_directories: common_inc,
|
||||
dependencies: deps_shell_fullscreen,
|
||||
name_prefix: '',
|
||||
install: true,
|
||||
install_dir: dir_module_weston
|
||||
)
|
||||
endif
|
||||
|
|
@ -258,14 +258,6 @@ struct weston_drm_backend_config {
|
|||
* rendering device.
|
||||
*/
|
||||
char *additional_devices;
|
||||
|
||||
/** Try to offload blend-to-output color transformation
|
||||
*
|
||||
* As KMS currently only supports to offload the transformation in a
|
||||
* LUT, this may result in precision issues. Also, this requires
|
||||
* "color-management" to be enabled.
|
||||
*/
|
||||
bool offload_blend_to_output;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -49,11 +49,6 @@ struct weston_headless_backend_config {
|
|||
* mHz to 1,000,000 mHz. 0 is a special value that triggers repaints
|
||||
* only on capture requests, not on damages. */
|
||||
int refresh;
|
||||
|
||||
/** Create a fake seat, some clients may complain without a wl_seat.
|
||||
* The default is not to create a wl_seat.
|
||||
*/
|
||||
bool fake_seat;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -54,20 +54,19 @@ struct weston_pipewire_output_api {
|
|||
const char *name,
|
||||
const struct pipewire_config *config);
|
||||
|
||||
/** Set the size and frame rate of a PipeWire output to the specified value.
|
||||
/** Set the size of a PipeWire output to the specified width and height.
|
||||
*
|
||||
* If the width or height or framerate are set to -1, the size or frame rate
|
||||
* of the underlying PipeWire head will be used.
|
||||
* If the width or height are set to -1, the size of the underlying
|
||||
* PipeWire head will be used.
|
||||
*
|
||||
* \param output The weston output for which the size shall be set
|
||||
* \param width Desired width of the output
|
||||
* \param height Desired height of the output
|
||||
* \param framerate Desired frame rate of the output
|
||||
*
|
||||
* Returns 0 on success, -1 on failure.
|
||||
*/
|
||||
int (*output_set_size)(struct weston_output *output,
|
||||
int width, int height, int framerate);
|
||||
int width, int height);
|
||||
|
||||
/** The pixel format to be used by the output.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -83,7 +83,6 @@ struct weston_rdp_backend_config {
|
|||
char *rdp_key;
|
||||
char *server_cert;
|
||||
char *server_key;
|
||||
int vmconnect;
|
||||
int env_socket;
|
||||
bool resizeable;
|
||||
int force_no_compression;
|
||||
|
|
@ -94,7 +93,6 @@ struct weston_rdp_backend_config {
|
|||
rdp_audio_in_teardown audio_in_teardown;
|
||||
rdp_audio_out_setup audio_out_setup;
|
||||
rdp_audio_out_teardown audio_out_teardown;
|
||||
char *nla_ntlm_db;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -1,314 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2008-2011 Kristian Høgsberg
|
||||
* Copyright © 2012-2025 Collabora, Ltd.
|
||||
* Copyright © 2017, 2018 General Electric Company
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <libweston/linalg-3.h>
|
||||
|
||||
struct weston_compositor;
|
||||
struct weston_color_profile_param_builder;
|
||||
struct weston_color_profile;
|
||||
struct weston_color_transform;
|
||||
|
||||
/** Colorimetry mode for outputs and heads
|
||||
*
|
||||
* A list of colorimetry modes for driving displays, defined by ANSI/CTA-861-H.
|
||||
*
|
||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||
* supported.
|
||||
*
|
||||
* On outputs, the mode to be used for driving the video sink.
|
||||
*
|
||||
* Default (RGB) colorimetry differs from all the others in that the signal
|
||||
* colorimetry is not defined here. It is defined by the video sink, and it
|
||||
* may be described in e.g. EDID.
|
||||
*/
|
||||
enum weston_colorimetry_mode {
|
||||
/** Invalid colorimetry mode, or none supported. */
|
||||
WESTON_COLORIMETRY_MODE_NONE = 0,
|
||||
|
||||
/** Default (RGB) colorimetry, video sink dependant */
|
||||
WESTON_COLORIMETRY_MODE_DEFAULT = 0x01,
|
||||
|
||||
/** Rec. ITU-R BT.2020 constant luminance YCbCr */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC = 0x02,
|
||||
|
||||
/** Rec. ITU-R BT.2020 non-constant luminance YCbCr */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_YCC = 0x04,
|
||||
|
||||
/** Rec. ITU-R BT.2020 RGB */
|
||||
WESTON_COLORIMETRY_MODE_BT2020_RGB = 0x08,
|
||||
|
||||
/** SMPTE ST 2113 DCI-P3 RGB D65 */
|
||||
WESTON_COLORIMETRY_MODE_P3D65 = 0x10,
|
||||
|
||||
/** SMPTE ST 2113 DCI-P3 RGB Theater */
|
||||
WESTON_COLORIMETRY_MODE_P3DCI = 0x20,
|
||||
|
||||
/** Rec. ITU-R BT.2100 ICtCp HDR (with PQ and/or HLG)*/
|
||||
WESTON_COLORIMETRY_MODE_ICTCP = 0x40,
|
||||
};
|
||||
|
||||
/** Bitmask of all defined colorimetry modes */
|
||||
#define WESTON_COLORIMETRY_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_COLORIMETRY_MODE_DEFAULT | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_CYCC | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_YCC | \
|
||||
WESTON_COLORIMETRY_MODE_BT2020_RGB | \
|
||||
WESTON_COLORIMETRY_MODE_P3D65 | \
|
||||
WESTON_COLORIMETRY_MODE_P3DCI | \
|
||||
WESTON_COLORIMETRY_MODE_ICTCP))
|
||||
|
||||
const char *
|
||||
weston_colorimetry_mode_to_str(enum weston_colorimetry_mode c);
|
||||
|
||||
/** EOTF mode for outputs and heads
|
||||
*
|
||||
* A list of EOTF modes for driving displays, defined by CTA-861-G for
|
||||
* Dynamic Range and Mastering InfoFrame.
|
||||
*
|
||||
* On heads, a bitmask of one or more entries shows which modes are claimed
|
||||
* supported.
|
||||
*
|
||||
* On outputs, the mode to be used for driving the video sink.
|
||||
*
|
||||
* For traditional non-HDR sRGB, use WESTON_EOTF_MODE_SDR.
|
||||
*/
|
||||
enum weston_eotf_mode {
|
||||
/** Invalid EOTF mode, or none supported. */
|
||||
WESTON_EOTF_MODE_NONE = 0,
|
||||
|
||||
/** Traditional gamma, SDR luminance range */
|
||||
WESTON_EOTF_MODE_SDR = 0x01,
|
||||
|
||||
/** Traditional gamma, HDR luminance range */
|
||||
WESTON_EOTF_MODE_TRADITIONAL_HDR = 0x02,
|
||||
|
||||
/** Preceptual quantizer, SMPTE ST 2084 */
|
||||
WESTON_EOTF_MODE_ST2084 = 0x04,
|
||||
|
||||
/** Hybrid log-gamma, ITU-R BT.2100 */
|
||||
WESTON_EOTF_MODE_HLG = 0x08,
|
||||
};
|
||||
|
||||
/** Bitmask of all defined EOTF modes */
|
||||
#define WESTON_EOTF_MODE_ALL_MASK \
|
||||
((uint32_t)(WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | \
|
||||
WESTON_EOTF_MODE_ST2084 | WESTON_EOTF_MODE_HLG))
|
||||
|
||||
const char *
|
||||
weston_eotf_mode_to_str(enum weston_eotf_mode e);
|
||||
|
||||
/** CIE 1931 xy chromaticity coordinates */
|
||||
struct weston_CIExy {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
/** Chromaticity coordinates and white point that defines the color gamut */
|
||||
struct weston_color_gamut {
|
||||
struct weston_CIExy primary[3]; /* RGB order */
|
||||
struct weston_CIExy white_point;
|
||||
};
|
||||
|
||||
void
|
||||
weston_color_gamut_from_protocol(struct weston_color_gamut *dst,
|
||||
int32_t r_x, int32_t r_y,
|
||||
int32_t g_x, int32_t g_y,
|
||||
int32_t b_x, int32_t b_y,
|
||||
int32_t w_x, int32_t w_y);
|
||||
|
||||
enum weston_npm_direction {
|
||||
WESTON_NPM_FORWARD,
|
||||
WESTON_NPM_INVERSE
|
||||
};
|
||||
|
||||
bool
|
||||
weston_normalized_primary_matrix_init(struct weston_mat3f *npm,
|
||||
const struct weston_color_gamut *gamut,
|
||||
enum weston_npm_direction dir);
|
||||
|
||||
struct weston_mat3f
|
||||
weston_bradford_adaptation(struct weston_CIExy from, struct weston_CIExy to);
|
||||
|
||||
/** Color primaries known by libweston */
|
||||
enum weston_color_primaries {
|
||||
WESTON_PRIMARIES_CICP_SRGB = 0,
|
||||
WESTON_PRIMARIES_CICP_PAL_M,
|
||||
WESTON_PRIMARIES_CICP_PAL,
|
||||
WESTON_PRIMARIES_CICP_NTSC,
|
||||
WESTON_PRIMARIES_CICP_GENERIC_FILM,
|
||||
WESTON_PRIMARIES_CICP_BT2020,
|
||||
WESTON_PRIMARIES_CICP_CIE1931_XYZ,
|
||||
WESTON_PRIMARIES_CICP_DCI_P3,
|
||||
WESTON_PRIMARIES_CICP_DISPLAY_P3,
|
||||
WESTON_PRIMARIES_ADOBE_RGB,
|
||||
};
|
||||
|
||||
/** Transfer functions known by libweston */
|
||||
enum weston_transfer_function {
|
||||
WESTON_TF_BT1886 = 0,
|
||||
WESTON_TF_GAMMA22,
|
||||
WESTON_TF_GAMMA28,
|
||||
WESTON_TF_SRGB,
|
||||
WESTON_TF_EXT_SRGB,
|
||||
WESTON_TF_ST240,
|
||||
WESTON_TF_ST428,
|
||||
WESTON_TF_ST2084_PQ,
|
||||
WESTON_TF_EXT_LINEAR,
|
||||
WESTON_TF_LOG_100,
|
||||
WESTON_TF_LOG_316,
|
||||
WESTON_TF_XVYCC,
|
||||
WESTON_TF_HLG,
|
||||
WESTON_TF_POWER,
|
||||
};
|
||||
|
||||
enum weston_alpha_mode {
|
||||
WESTON_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL = 0,
|
||||
WESTON_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
|
||||
WESTON_ALPHA_MODE_STRAIGHT,
|
||||
};
|
||||
|
||||
enum weston_color_matrix_coef {
|
||||
WESTON_COLOR_MATRIX_COEF_UNSET = 0,
|
||||
WESTON_COLOR_MATRIX_COEF_IDENTITY,
|
||||
WESTON_COLOR_MATRIX_COEF_BT601,
|
||||
WESTON_COLOR_MATRIX_COEF_BT709,
|
||||
WESTON_COLOR_MATRIX_COEF_BT2020,
|
||||
};
|
||||
|
||||
enum weston_color_quant_range {
|
||||
WESTON_COLOR_QUANT_RANGE_UNSET = 0,
|
||||
WESTON_COLOR_QUANT_RANGE_FULL,
|
||||
WESTON_COLOR_QUANT_RANGE_LIMITED,
|
||||
};
|
||||
|
||||
enum weston_ycbcr_chroma_location {
|
||||
WESTON_YCBCR_CHROMA_LOCATION_UNSET = 0,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_0,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_1,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_2,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_3,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_4,
|
||||
WESTON_YCBCR_CHROMA_LOCATION_TYPE_5,
|
||||
};
|
||||
|
||||
/** Error codes that the color profile parameters functions may return. */
|
||||
enum weston_color_profile_param_builder_error {
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES_NAMED,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CREATE_FAILED,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
|
||||
};
|
||||
|
||||
struct weston_color_profile_param_builder *
|
||||
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
|
||||
|
||||
void
|
||||
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_profile_param_builder_error *err,
|
||||
char **err_msg);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_primaries primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_transfer_function tf);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
|
||||
float power_exponent);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder,
|
||||
float ref_lum, float min_lum, float max_lum);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *target_primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_primaries target_primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
|
||||
float min_lum, float max_lum);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
|
||||
float maxFALL);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
|
||||
float maxCLL);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
|
||||
const char *name_part,
|
||||
enum weston_color_profile_param_builder_error *err,
|
||||
char **err_msg);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_color_profile_ref(struct weston_color_profile *cprof);
|
||||
|
||||
void
|
||||
weston_color_profile_unref(struct weston_color_profile *cprof);
|
||||
|
||||
const char *
|
||||
weston_color_profile_get_description(struct weston_color_profile *cprof);
|
||||
|
||||
char *
|
||||
weston_color_profile_get_details(struct weston_color_profile *cprof);
|
||||
|
||||
struct weston_color_profile *
|
||||
weston_compositor_load_icc_file(struct weston_compositor *compositor,
|
||||
const char *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -32,7 +32,6 @@ extern "C" {
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define WESTON_CONFIG_FILE_ENV_VAR "WESTON_CONFIG_FILE"
|
||||
|
||||
|
|
@ -108,20 +107,6 @@ int weston_config_next_section(struct weston_config *config,
|
|||
uint32_t
|
||||
weston_config_get_binding_modifier(struct weston_config *config, uint32_t default_mod);
|
||||
|
||||
/** Container for an array of strings. */
|
||||
struct weston_string_array {
|
||||
/** Length of \c array. */
|
||||
size_t len;
|
||||
/** Pointer to an array of strings. */
|
||||
char **array;
|
||||
};
|
||||
|
||||
void
|
||||
weston_string_array_fini(struct weston_string_array *strarr);
|
||||
|
||||
struct weston_string_array
|
||||
weston_parse_space_separated_list(const char *str);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -217,8 +217,6 @@ struct weston_size
|
|||
weston_desktop_surface_get_max_size(struct weston_desktop_surface *surface);
|
||||
struct weston_size
|
||||
weston_desktop_surface_get_min_size(struct weston_desktop_surface *surface);
|
||||
char *
|
||||
weston_desktop_surface_make_label(struct weston_desktop_surface *surface);
|
||||
struct weston_desktop_surface *
|
||||
weston_desktop_surface_get_parent(struct weston_desktop_surface *surface);
|
||||
void
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,259 +0,0 @@
|
|||
/*
|
||||
* Copyright 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libweston/linalg-types.h>
|
||||
|
||||
/* ================= 3-vectors and 3x3 matrices ============== */
|
||||
|
||||
/** Construct a column vector from elements */
|
||||
#define WESTON_VEC3F(x, y, z) ((struct weston_vec3f){ .el = { (x), (y), (z) }})
|
||||
|
||||
/** Construct the [0, 0, 0]^T vector */
|
||||
#define WESTON_VEC3F_ZERO ((struct weston_vec3f){ .el = {}})
|
||||
|
||||
/** Construct matrix from elements a{row}{column} */
|
||||
#define WESTON_MAT3F(a00, a01, a02, \
|
||||
a10, a11, a12, \
|
||||
a20, a21, a22) \
|
||||
((struct weston_mat3f){ .colmaj = { \
|
||||
a00, a10, a20, \
|
||||
a01, a11, a21, \
|
||||
a02, a12, a22, \
|
||||
}})
|
||||
|
||||
/** Construct the identity 3x3 matrix */
|
||||
#define WESTON_MAT3F_IDENTITY \
|
||||
((struct weston_mat3f){ .colmaj = { \
|
||||
1.0f, 0.0f, 0.0f, \
|
||||
0.0f, 1.0f, 0.0f, \
|
||||
0.0f, 0.0f, 1.0f, \
|
||||
}})
|
||||
|
||||
/** Construct a diagonal matrix */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_diag(struct weston_vec3f d)
|
||||
{
|
||||
return WESTON_MAT3F(
|
||||
d.x, 0.0f, 0.0f,
|
||||
0.0f, d.y, 0.0f,
|
||||
0.0f, 0.0f, d.z);
|
||||
}
|
||||
|
||||
/** Copy the top-left 3x3 from 4x4 */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_from_m4f_xyz(struct weston_mat4f M)
|
||||
{
|
||||
return WESTON_MAT3F(
|
||||
M.col[0].el[0], M.col[1].el[0], M.col[2].el[0],
|
||||
M.col[0].el[1], M.col[1].el[1], M.col[2].el[1],
|
||||
M.col[0].el[2], M.col[1].el[2], M.col[2].el[2]
|
||||
);
|
||||
}
|
||||
|
||||
/** Drop w from vec4f */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_from_v4f_xyz(struct weston_vec4f v)
|
||||
{
|
||||
return WESTON_VEC3F(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
/** 3-vector dot product */
|
||||
static inline float
|
||||
weston_v3f_dot_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of vec3f into planar format
|
||||
*
|
||||
* Takes an array of RGB triplets and converts it into a planar format where all R
|
||||
* values come first, then all G values, then all B values.
|
||||
*
|
||||
* \param planar The destination array for planar data, must have space for 3 * len floats
|
||||
* \param arr Array of RGB triplets as vec3f structs
|
||||
* \param len Number of RGB triplets in the array
|
||||
*/
|
||||
static inline void
|
||||
weston_v3f_array_to_planar(float *planar, const struct weston_vec3f *arr, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
planar[i ] = arr[i].r;
|
||||
planar[i + len] = arr[i].g;
|
||||
planar[i + 2 * len] = arr[i].b;
|
||||
}
|
||||
}
|
||||
|
||||
/** Clamp each element to the range [a, b], replacing NaN with a. */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_clamp(struct weston_vec3f v, float a, float b)
|
||||
{
|
||||
return WESTON_VEC3F(v.x >= a ? (v.x <= b ? v.x : b) : a,
|
||||
v.y >= a ? (v.y <= b ? v.y : b) : a,
|
||||
v.z >= a ? (v.z <= b ? v.z : b) : a);
|
||||
}
|
||||
|
||||
/** Element-wise vector subtraction a - b */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_sub_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return WESTON_VEC3F(a.x - b.x,
|
||||
a.y - b.y,
|
||||
a.z - b.z);
|
||||
}
|
||||
|
||||
/** Element-wise vector sum a + b */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_add_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return WESTON_VEC3F(a.x + b.x,
|
||||
a.y + b.y,
|
||||
a.z + b.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrix infinity-norm
|
||||
*
|
||||
* http://www.netlib.org/lapack/lug/node75.html
|
||||
*/
|
||||
static inline float
|
||||
weston_m3f_inf_norm(struct weston_mat3f M)
|
||||
{
|
||||
unsigned row;
|
||||
double infnorm = -1.0;
|
||||
|
||||
for (row = 0; row < 3; row++) {
|
||||
unsigned col;
|
||||
double sum = 0.0;
|
||||
|
||||
for (col = 0; col < 3; col++)
|
||||
sum += fabsf(M.col[col].el[row]);
|
||||
|
||||
if (infnorm < sum)
|
||||
infnorm = sum;
|
||||
}
|
||||
|
||||
return infnorm;
|
||||
}
|
||||
|
||||
/** Transpose 3x3 matrix */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_transpose(struct weston_mat3f M)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
R.col[j].el[i] = M.col[i].el[j];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
/** Matrix-vector multiplication A * b */
|
||||
static inline struct weston_vec3f
|
||||
weston_m3f_mul_v3f(struct weston_mat3f A, struct weston_vec3f b)
|
||||
{
|
||||
struct weston_vec3f result;
|
||||
unsigned r;
|
||||
|
||||
for (r = 0; r < 3; r++) {
|
||||
struct weston_vec3f row =
|
||||
WESTON_VEC3F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r]);
|
||||
result.el[r] = weston_v3f_dot_v3f(row, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Matrix multiplication A * B */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_mul_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||
{
|
||||
struct weston_mat3f result;
|
||||
unsigned c;
|
||||
|
||||
for (c = 0; c < 3; c++)
|
||||
result.col[c] = weston_m3f_mul_v3f(A, B.col[c]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Element-wise matrix addition A + B */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_add_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 3 * 3; i++)
|
||||
R.colmaj[i] = A.colmaj[i] + B.colmaj[i];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
/** Element-wise matrix subtraction A - B */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_sub_m3f(struct weston_mat3f A, struct weston_mat3f B)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 3 * 3; i++)
|
||||
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
/** Element-wise scalar multiplication */
|
||||
static inline struct weston_mat3f
|
||||
weston_m3f_mul_scalar(struct weston_mat3f M, float scalar)
|
||||
{
|
||||
struct weston_mat3f R;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 3 * 3; i++)
|
||||
R.colmaj[i] = scalar * M.colmaj[i];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
bool
|
||||
weston_m3f_invert(struct weston_mat3f *out, struct weston_mat3f M);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
* Copyright 2025 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libweston/linalg-types.h>
|
||||
|
||||
/* ================= 4-vectors and 4x4 matrices ============== */
|
||||
|
||||
/** Construct a column vector from elements */
|
||||
#define WESTON_VEC4F(x, y, z, w) ((struct weston_vec4f){ .el = { (x), (y), (z), (w) }})
|
||||
|
||||
/** Construct the [0, 0, 0, 0]^T vector */
|
||||
#define WESTON_VEC4F_ZERO ((struct weston_vec4f){ .el = {}})
|
||||
|
||||
/** Construct matrix from elements a{row}{column} */
|
||||
#define WESTON_MAT4F(a00, a01, a02, a03, \
|
||||
a10, a11, a12, a13, \
|
||||
a20, a21, a22, a23, \
|
||||
a30, a31, a32, a33) \
|
||||
((struct weston_mat4f){ .colmaj = { \
|
||||
a00, a10, a20, a30, \
|
||||
a01, a11, a21, a31, \
|
||||
a02, a12, a22, a32, \
|
||||
a03, a13, a23, a33, \
|
||||
}})
|
||||
|
||||
/** Construct the identity 4x4 matrix */
|
||||
#define WESTON_MAT4F_IDENTITY \
|
||||
((struct weston_mat4f){ .colmaj = { \
|
||||
1.0f, 0.0f, 0.0f, 0.0f, \
|
||||
0.0f, 1.0f, 0.0f, 0.0f, \
|
||||
0.0f, 0.0f, 1.0f, 0.0f, \
|
||||
0.0f, 0.0f, 0.0f, 1.0f, \
|
||||
}})
|
||||
|
||||
/** Construct a translation matrix */
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_translation(float tx, float ty, float tz)
|
||||
{
|
||||
return WESTON_MAT4F(
|
||||
1.0f, 0.0f, 0.0f, tx,
|
||||
0.0f, 1.0f, 0.0f, ty,
|
||||
0.0f, 0.0f, 1.0f, tz,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/** Construct a scaling matrix */
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_scaling(float sx, float sy, float sz)
|
||||
{
|
||||
return WESTON_MAT4F(
|
||||
sx, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, sy, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, sz, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
/** Construct a 2D x-y rotation matrix
|
||||
*
|
||||
* \param cos_th Cosine of the counter-clockwise angle.
|
||||
* \param sin_th Sine of the counter-clockwise angle.
|
||||
*/
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_rotation_xy(float cos_th, float sin_th)
|
||||
{
|
||||
return WESTON_MAT4F(
|
||||
cos_th, -sin_th, 0.0f, 0.0f,
|
||||
sin_th, cos_th, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_from_m3f_v3f(struct weston_mat3f R, struct weston_vec3f t)
|
||||
{
|
||||
return WESTON_MAT4F(
|
||||
R.col[0].el[0], R.col[1].el[0], R.col[2].el[0], t.el[0],
|
||||
R.col[0].el[1], R.col[1].el[1], R.col[2].el[1], t.el[1],
|
||||
R.col[0].el[2], R.col[1].el[2], R.col[2].el[2], t.el[2],
|
||||
0.0f, 0.0f, 0.0f, 1.0f
|
||||
);
|
||||
}
|
||||
|
||||
/** 4-vector dot product */
|
||||
static inline float
|
||||
weston_v4f_dot_v4f(struct weston_vec4f a, struct weston_vec4f b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrix infinity-norm
|
||||
*
|
||||
* http://www.netlib.org/lapack/lug/node75.html
|
||||
*/
|
||||
static inline float
|
||||
weston_m4f_inf_norm(struct weston_mat4f M)
|
||||
{
|
||||
unsigned row;
|
||||
double infnorm = -1.0;
|
||||
|
||||
for (row = 0; row < 4; row++) {
|
||||
unsigned col;
|
||||
double sum = 0.0;
|
||||
|
||||
for (col = 0; col < 4; col++)
|
||||
sum += fabsf(M.col[col].el[row]);
|
||||
|
||||
if (infnorm < sum)
|
||||
infnorm = sum;
|
||||
}
|
||||
|
||||
return infnorm;
|
||||
}
|
||||
|
||||
/** Transpose 4x4 matrix */
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_transpose(struct weston_mat4f M)
|
||||
{
|
||||
struct weston_mat4f R;
|
||||
unsigned i, j;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
for (j = 0; j < 4; j++)
|
||||
R.col[j].el[i] = M.col[i].el[j];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
/** Matrix-vector multiplication A * b */
|
||||
static inline struct weston_vec4f
|
||||
weston_m4f_mul_v4f(struct weston_mat4f A, struct weston_vec4f b)
|
||||
{
|
||||
struct weston_vec4f result;
|
||||
unsigned r;
|
||||
|
||||
for (r = 0; r < 4; r++) {
|
||||
struct weston_vec4f row =
|
||||
WESTON_VEC4F(A.col[0].el[r], A.col[1].el[r], A.col[2].el[r], A.col[3].el[r]);
|
||||
result.el[r] = weston_v4f_dot_v4f(row, b);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Matrix multiplication A * B */
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_mul_m4f(struct weston_mat4f A, struct weston_mat4f B)
|
||||
{
|
||||
struct weston_mat4f result;
|
||||
unsigned c;
|
||||
|
||||
for (c = 0; c < 4; c++)
|
||||
result.col[c] = weston_m4f_mul_v4f(A, B.col[c]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Element-wise matrix subtraction A - B */
|
||||
static inline struct weston_mat4f
|
||||
weston_m4f_sub_m4f(struct weston_mat4f A, struct weston_mat4f B)
|
||||
{
|
||||
struct weston_mat4f R;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 4 * 4; i++)
|
||||
R.colmaj[i] = A.colmaj[i] - B.colmaj[i];
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
bool
|
||||
weston_m4f_invert(struct weston_mat4f *out, struct weston_mat4f M);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
#include <stdbool.h>
|
||||
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <libweston/linalg-types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
@ -45,12 +44,12 @@ enum weston_matrix_transform_type {
|
|||
};
|
||||
|
||||
struct weston_matrix {
|
||||
struct weston_mat4f M;
|
||||
float d[16];
|
||||
unsigned int type;
|
||||
};
|
||||
|
||||
struct weston_vector {
|
||||
struct weston_vec4f v;
|
||||
float f[4];
|
||||
};
|
||||
|
||||
/** Arbitrary coordinates in any space */
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
install_headers(
|
||||
'colorimetry.h',
|
||||
'config-parser.h',
|
||||
'libweston.h',
|
||||
'linalg.h',
|
||||
'linalg-3.h',
|
||||
'linalg-4.h',
|
||||
'linalg-types.h',
|
||||
'desktop.h',
|
||||
'matrix.h',
|
||||
'plugin-registry.h',
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ extern "C" {
|
|||
|
||||
/* parameter for weston_curtain_create() */
|
||||
struct weston_curtain_params {
|
||||
char *label;
|
||||
int (*get_label)(struct weston_surface *es, char *buf, size_t len);
|
||||
void (*surface_committed)(struct weston_surface *es,
|
||||
struct weston_coord_surface new_origin);
|
||||
void *surface_private;
|
||||
|
|
@ -61,6 +61,10 @@ weston_shell_utils_subsurfaces_boundingbox(struct weston_surface *surface,
|
|||
int32_t *x, int32_t *y,
|
||||
int32_t *w, int32_t *h);
|
||||
|
||||
int
|
||||
weston_shell_utils_surface_get_label(struct weston_surface *surface,
|
||||
char *buf, size_t len);
|
||||
|
||||
/* helper to create a view w/ a color */
|
||||
struct weston_curtain *
|
||||
weston_shell_utils_curtain_create(struct weston_compositor *compositor,
|
||||
|
|
@ -71,13 +75,6 @@ weston_shell_utils_curtain_destroy(struct weston_curtain *curtain);
|
|||
enum weston_layer_position
|
||||
weston_shell_utils_view_get_layer_position(struct weston_view *view);
|
||||
|
||||
void
|
||||
weston_output_set_shell_private(struct weston_output *output,
|
||||
void *private_data);
|
||||
|
||||
void *
|
||||
weston_output_get_shell_private(struct weston_output *output);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -88,9 +88,6 @@ void
|
|||
weston_log_scope_write(struct weston_log_scope *scope,
|
||||
const char *data, size_t len);
|
||||
|
||||
FILE *
|
||||
weston_log_scope_stream(struct weston_log_scope *scope);
|
||||
|
||||
int
|
||||
weston_log_scope_vprintf(struct weston_log_scope *scope,
|
||||
const char *fmt, va_list ap);
|
||||
|
|
@ -99,14 +96,6 @@ int
|
|||
weston_log_scope_printf(struct weston_log_scope *scope,
|
||||
const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 2, 3)));
|
||||
|
||||
void
|
||||
weston_log_scope_puts(struct weston_log_scope *scope, const char *str);
|
||||
|
||||
void
|
||||
weston_log_subscription_write(struct weston_log_subscription *sub,
|
||||
const char *data, size_t len);
|
||||
|
||||
void
|
||||
weston_log_subscription_printf(struct weston_log_subscription *sub,
|
||||
const char *fmt, ...)
|
||||
|
|
@ -157,12 +146,6 @@ struct weston_log_scope *
|
|||
weston_log_scopes_iterate(struct weston_log_context *log_ctx,
|
||||
struct weston_log_scope *nscope);
|
||||
|
||||
void
|
||||
weston_add_scope_to_advertised_list(struct weston_log_context *ctx,
|
||||
const char *name);
|
||||
bool
|
||||
weston_log_scope_to_be_advertised(struct weston_log_context *ctx, const char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -103,9 +103,8 @@ weston_windowed_output_get_api(struct weston_compositor *compositor,
|
|||
if (type >= ARRAY_LENGTH(api_names))
|
||||
return NULL;
|
||||
|
||||
return (const struct weston_windowed_output_api *)
|
||||
weston_plugin_api_get(compositor, api_names[type],
|
||||
sizeof(struct weston_windowed_output_api));
|
||||
return weston_plugin_api_get(compositor, api_names[type],
|
||||
sizeof(struct weston_windowed_output_api));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -1455,8 +1455,6 @@ ivi_hmi_controller_UI_ready(struct wl_client *client,
|
|||
hmi_ctrl->interface->commit_changes();
|
||||
|
||||
ivi_hmi_controller_add_launchers(hmi_ctrl, 256);
|
||||
|
||||
hmi_ctrl->interface->screen_ready(hmi_ctrl->workspace_background_output);
|
||||
hmi_ctrl->is_initialized = 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -219,17 +219,6 @@ struct ivi_layout_interface {
|
|||
*/
|
||||
void (*add_listener_configure_desktop_surface)(struct wl_listener *listener);
|
||||
|
||||
/**
|
||||
* \brief add a listener for desktop_surface ping timeout notification
|
||||
*
|
||||
* When a desktop_client fails to respond to compositor pings within
|
||||
* the configured timeout period, this signal is emitted to registered
|
||||
* listeners. The void* data argument will contain a pointer to the
|
||||
* weston_desktop_client associated with the unresponsive surface.
|
||||
*/
|
||||
|
||||
void (*add_listener_desktop_surface_ping_timeout)(struct wl_listener *listener);
|
||||
|
||||
/**
|
||||
* \brief Get all ivi_surfaces which are currently registered and managed
|
||||
* by the services
|
||||
|
|
@ -647,12 +636,6 @@ struct ivi_layout_interface {
|
|||
* See add_listener_show_input_panel for more details.
|
||||
*/
|
||||
void (*add_listener_update_input_panel)(struct wl_listener *listener);
|
||||
|
||||
/**
|
||||
* \brief Set weston_output ready to be painted
|
||||
*/
|
||||
void (*screen_ready)(struct weston_output *output);
|
||||
|
||||
};
|
||||
|
||||
static inline const struct ivi_layout_interface *
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ struct ivi_layout {
|
|||
struct wl_signal removed;
|
||||
struct wl_signal configure_changed;
|
||||
struct wl_signal configure_desktop_changed;
|
||||
struct wl_signal ping_timeout;
|
||||
} surface_notification;
|
||||
|
||||
struct {
|
||||
|
|
|
|||
|
|
@ -46,9 +46,6 @@ void
|
|||
ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
|
||||
int32_t width, int32_t height);
|
||||
|
||||
void
|
||||
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client);
|
||||
|
||||
struct ivi_layout_surface*
|
||||
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
||||
struct weston_desktop_surface *surface);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,6 @@
|
|||
|
||||
#include "frontend/weston.h"
|
||||
#include <libweston/libweston.h>
|
||||
#include <libweston/shell-utils.h>
|
||||
#include "ivi-shell.h"
|
||||
#include "ivi-layout-export.h"
|
||||
#include "ivi-layout-private.h"
|
||||
|
|
@ -285,7 +284,7 @@ destroy_screen(struct ivi_layout_screen *iviscrn)
|
|||
}
|
||||
|
||||
static void
|
||||
output_destroy_iviscreen(struct wl_listener *listener, void *data)
|
||||
output_destroyed_event(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_output *destroyed_output = data;
|
||||
struct ivi_layout_screen *iviscrn;
|
||||
|
|
@ -296,8 +295,8 @@ output_destroy_iviscreen(struct wl_listener *listener, void *data)
|
|||
|
||||
}
|
||||
|
||||
static struct ivi_layout_screen *
|
||||
create_screen(struct weston_output *output)
|
||||
static void
|
||||
add_screen(struct weston_output *output)
|
||||
{
|
||||
struct ivi_layout *layout = get_instance();
|
||||
struct ivi_layout_screen *iviscrn = NULL;
|
||||
|
|
@ -310,24 +309,26 @@ create_screen(struct weston_output *output)
|
|||
wl_list_init(&iviscrn->pending.layer_list);
|
||||
wl_list_init(&iviscrn->order.layer_list);
|
||||
wl_list_insert(&layout->screen_list, &iviscrn->link);
|
||||
|
||||
return iviscrn;
|
||||
}
|
||||
|
||||
static void
|
||||
create_ivi_screen(struct ivi_layout *layout, struct weston_output *output)
|
||||
output_created_event(struct wl_listener *listener, void *data)
|
||||
{
|
||||
create_screen(output);
|
||||
struct weston_output *created_output = data;
|
||||
add_screen(created_output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal API to initialize ivi_screens found from output_list of weston_compositor.
|
||||
* Called by ivi_layout_init.
|
||||
*/
|
||||
static void
|
||||
output_create_iviscreen(struct wl_listener *listener, void *data)
|
||||
create_screen(struct weston_compositor *ec)
|
||||
{
|
||||
struct ivi_layout *layout =
|
||||
container_of(listener, struct ivi_layout, output_created);
|
||||
struct weston_output *output = data;
|
||||
struct weston_output *output = NULL;
|
||||
|
||||
create_ivi_screen(layout, output);
|
||||
wl_list_for_each(output, &ec->output_list, link)
|
||||
add_screen(output);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -462,33 +463,33 @@ calc_inverse_matrix_transform(const struct weston_matrix *matrix,
|
|||
}
|
||||
|
||||
/* The vectors and matrices involved will always produce f[3] == 1.0. */
|
||||
top_left.v.el[0] = rect_input->x;
|
||||
top_left.v.el[1] = rect_input->y;
|
||||
top_left.v.el[2] = 0.0f;
|
||||
top_left.v.el[3] = 1.0f;
|
||||
top_left.f[0] = rect_input->x;
|
||||
top_left.f[1] = rect_input->y;
|
||||
top_left.f[2] = 0.0f;
|
||||
top_left.f[3] = 1.0f;
|
||||
|
||||
bottom_right.v.el[0] = rect_input->x + rect_input->width;
|
||||
bottom_right.v.el[1] = rect_input->y + rect_input->height;
|
||||
bottom_right.v.el[2] = 0.0f;
|
||||
bottom_right.v.el[3] = 1.0f;
|
||||
bottom_right.f[0] = rect_input->x + rect_input->width;
|
||||
bottom_right.f[1] = rect_input->y + rect_input->height;
|
||||
bottom_right.f[2] = 0.0f;
|
||||
bottom_right.f[3] = 1.0f;
|
||||
|
||||
weston_matrix_transform(&m, &top_left);
|
||||
weston_matrix_transform(&m, &bottom_right);
|
||||
|
||||
if (top_left.v.el[0] < bottom_right.v.el[0]) {
|
||||
rect_output->x = floor(top_left.v.el[0]);
|
||||
rect_output->width = ceil(bottom_right.v.el[0] - rect_output->x);
|
||||
if (top_left.f[0] < bottom_right.f[0]) {
|
||||
rect_output->x = floorf(top_left.f[0]);
|
||||
rect_output->width = ceilf(bottom_right.f[0] - rect_output->x);
|
||||
} else {
|
||||
rect_output->x = floor(bottom_right.v.el[0]);
|
||||
rect_output->width = ceil(top_left.v.el[0] - rect_output->x);
|
||||
rect_output->x = floorf(bottom_right.f[0]);
|
||||
rect_output->width = ceilf(top_left.f[0] - rect_output->x);
|
||||
}
|
||||
|
||||
if (top_left.v.el[1] < bottom_right.v.el[1]) {
|
||||
rect_output->y = floor(top_left.v.el[1]);
|
||||
rect_output->height = ceil(bottom_right.v.el[1] - rect_output->y);
|
||||
if (top_left.f[1] < bottom_right.f[1]) {
|
||||
rect_output->y = floorf(top_left.f[1]);
|
||||
rect_output->height = ceilf(bottom_right.f[1] - rect_output->y);
|
||||
} else {
|
||||
rect_output->y = floor(bottom_right.v.el[1]);
|
||||
rect_output->height = ceil(top_left.v.el[1] - rect_output->y);
|
||||
rect_output->y = floorf(bottom_right.f[1]);
|
||||
rect_output->height = ceilf(top_left.f[1] - rect_output->y);
|
||||
}
|
||||
|
||||
ivi_rectangle_intersect(rect_output, boundingbox, rect_output);
|
||||
|
|
@ -987,16 +988,6 @@ ivi_layout_add_listener_configure_desktop_surface(struct wl_listener *listener)
|
|||
wl_signal_add(&layout->surface_notification.configure_desktop_changed, listener);
|
||||
}
|
||||
|
||||
static void
|
||||
ivi_layout_add_listener_desktop_surface_ping_timeout(struct wl_listener *listener)
|
||||
{
|
||||
struct ivi_layout *layout = get_instance();
|
||||
|
||||
assert(listener);
|
||||
|
||||
wl_signal_add(&layout->surface_notification.ping_timeout, listener);
|
||||
}
|
||||
|
||||
static int32_t
|
||||
ivi_layout_shell_add_destroy_listener_once(struct wl_listener *listener, wl_notify_func_t destroy_handler)
|
||||
{
|
||||
|
|
@ -1573,12 +1564,6 @@ ivi_layout_screen_set_render_order(struct weston_output *output,
|
|||
iviscrn->order.dirty = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ivi_layout_set_screen_ready(struct weston_output *output)
|
||||
{
|
||||
weston_output_set_ready(output);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used by the additional ivi-module because of dumping ivi_surface sceenshot.
|
||||
* The ivi-module, e.g. ivi-controller.so, is in wayland-ivi-extension of Genivi's Layer Management.
|
||||
|
|
@ -1927,14 +1912,6 @@ ivi_layout_desktop_surface_configure(struct ivi_layout_surface *ivisurf,
|
|||
ivisurf);
|
||||
}
|
||||
|
||||
void
|
||||
ivi_layout_desktop_surface_ping_timeout(struct weston_desktop_client *client)
|
||||
{
|
||||
struct ivi_layout *layout = get_instance();
|
||||
|
||||
wl_signal_emit_mutable(&layout->surface_notification.ping_timeout, client);
|
||||
}
|
||||
|
||||
struct ivi_layout_surface*
|
||||
ivi_layout_desktop_surface_create(struct weston_surface *wl_surface,
|
||||
struct weston_desktop_surface *surface)
|
||||
|
|
@ -2121,7 +2098,6 @@ void
|
|||
ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
||||
{
|
||||
struct ivi_layout *layout = get_instance();
|
||||
struct weston_output *output;
|
||||
|
||||
layout->shell = shell;
|
||||
|
||||
|
|
@ -2137,7 +2113,6 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
|||
wl_signal_init(&layout->surface_notification.removed);
|
||||
wl_signal_init(&layout->surface_notification.configure_changed);
|
||||
wl_signal_init(&layout->surface_notification.configure_desktop_changed);
|
||||
wl_signal_init(&layout->surface_notification.ping_timeout);
|
||||
|
||||
wl_signal_init(&layout->input_panel_notification.configure_changed);
|
||||
wl_signal_init(&layout->input_panel_notification.show);
|
||||
|
|
@ -2151,13 +2126,12 @@ ivi_layout_init(struct weston_compositor *ec, struct ivi_shell *shell)
|
|||
weston_layer_set_position(&layout->layout_layer,
|
||||
WESTON_LAYER_POSITION_NORMAL);
|
||||
|
||||
layout->output_created.notify = output_create_iviscreen;
|
||||
create_screen(ec);
|
||||
|
||||
layout->output_created.notify = output_created_event;
|
||||
wl_signal_add(&ec->output_created_signal, &layout->output_created);
|
||||
|
||||
wl_list_for_each(output, &ec->output_list, link)
|
||||
create_ivi_screen(layout, output);
|
||||
|
||||
layout->output_destroyed.notify = output_destroy_iviscreen;
|
||||
layout->output_destroyed.notify = output_destroyed_event;
|
||||
wl_signal_add(&ec->output_destroyed_signal, &layout->output_destroyed);
|
||||
|
||||
layout->transitions = ivi_layout_transition_set_create(ec);
|
||||
|
|
@ -2172,10 +2146,6 @@ void
|
|||
ivi_layout_fini(void)
|
||||
{
|
||||
struct ivi_layout *layout = get_instance();
|
||||
struct ivi_layout_screen *iviscrn, *iviscrn_tmp;
|
||||
|
||||
wl_list_for_each_safe(iviscrn, iviscrn_tmp, &layout->screen_list, link)
|
||||
destroy_screen(iviscrn);
|
||||
|
||||
weston_layer_fini(&layout->layout_layer);
|
||||
|
||||
|
|
@ -2194,33 +2164,32 @@ static struct ivi_layout_interface ivi_layout_interface = {
|
|||
/**
|
||||
* surface controller interfaces
|
||||
*/
|
||||
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
|
||||
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
|
||||
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
|
||||
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
|
||||
.add_listener_desktop_surface_ping_timeout = ivi_layout_add_listener_desktop_surface_ping_timeout,
|
||||
.get_surface = shell_get_ivi_layout_surface,
|
||||
.get_surfaces = ivi_layout_get_surfaces,
|
||||
.get_id_of_surface = ivi_layout_get_id_of_surface,
|
||||
.get_surface_from_id = ivi_layout_get_surface_from_id,
|
||||
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
|
||||
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
|
||||
.surface_set_visibility = ivi_layout_surface_set_visibility,
|
||||
.surface_set_opacity = ivi_layout_surface_set_opacity,
|
||||
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
|
||||
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
|
||||
.surface_add_listener = ivi_layout_surface_add_listener,
|
||||
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
|
||||
.surface_set_transition = ivi_layout_surface_set_transition,
|
||||
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
|
||||
.surface_set_id = ivi_layout_surface_set_id,
|
||||
.surface_activate = ivi_layout_surface_activate,
|
||||
.surface_is_active = ivi_layout_surface_is_active,
|
||||
.add_listener_create_surface = ivi_layout_add_listener_create_surface,
|
||||
.add_listener_remove_surface = ivi_layout_add_listener_remove_surface,
|
||||
.add_listener_configure_surface = ivi_layout_add_listener_configure_surface,
|
||||
.add_listener_configure_desktop_surface = ivi_layout_add_listener_configure_desktop_surface,
|
||||
.get_surface = shell_get_ivi_layout_surface,
|
||||
.get_surfaces = ivi_layout_get_surfaces,
|
||||
.get_id_of_surface = ivi_layout_get_id_of_surface,
|
||||
.get_surface_from_id = ivi_layout_get_surface_from_id,
|
||||
.get_properties_of_surface = ivi_layout_get_properties_of_surface,
|
||||
.get_surfaces_on_layer = ivi_layout_get_surfaces_on_layer,
|
||||
.surface_set_visibility = ivi_layout_surface_set_visibility,
|
||||
.surface_set_opacity = ivi_layout_surface_set_opacity,
|
||||
.surface_set_source_rectangle = ivi_layout_surface_set_source_rectangle,
|
||||
.surface_set_destination_rectangle = ivi_layout_surface_set_destination_rectangle,
|
||||
.surface_add_listener = ivi_layout_surface_add_listener,
|
||||
.surface_get_weston_surface = ivi_layout_surface_get_weston_surface,
|
||||
.surface_set_transition = ivi_layout_surface_set_transition,
|
||||
.surface_set_transition_duration = ivi_layout_surface_set_transition_duration,
|
||||
.surface_set_id = ivi_layout_surface_set_id,
|
||||
.surface_activate = ivi_layout_surface_activate,
|
||||
.surface_is_active = ivi_layout_surface_is_active,
|
||||
|
||||
/**
|
||||
* layer controller interfaces
|
||||
*/
|
||||
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
|
||||
.add_listener_create_layer = ivi_layout_add_listener_create_layer,
|
||||
.add_listener_remove_layer = ivi_layout_add_listener_remove_layer,
|
||||
.layer_create_with_dimension = ivi_layout_layer_create_with_dimension,
|
||||
.layer_destroy = ivi_layout_layer_destroy,
|
||||
|
|
@ -2247,7 +2216,6 @@ static struct ivi_layout_interface ivi_layout_interface = {
|
|||
.screen_add_layer = ivi_layout_screen_add_layer,
|
||||
.screen_remove_layer = ivi_layout_screen_remove_layer,
|
||||
.screen_set_render_order = ivi_layout_screen_set_render_order,
|
||||
.screen_ready = ivi_layout_set_screen_ready,
|
||||
|
||||
/**
|
||||
* animation
|
||||
|
|
|
|||
|
|
@ -49,10 +49,8 @@
|
|||
#include "ivi-layout-shell.h"
|
||||
#include "libweston/libweston.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/string-helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include "frontend/weston.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
|
||||
/* Representation of ivi_surface protocol object. */
|
||||
struct ivi_shell_surface
|
||||
|
|
@ -73,8 +71,6 @@ struct ivi_shell_surface
|
|||
struct wl_list children_link;
|
||||
|
||||
struct wl_list link;
|
||||
|
||||
struct wl_listener surface_label_update;
|
||||
};
|
||||
|
||||
struct ivi_input_panel_surface
|
||||
|
|
@ -211,6 +207,16 @@ ivi_shell_surface_committed(struct weston_surface *surface,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ivi_shell_surface_get_label(struct weston_surface *surface,
|
||||
char *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct ivi_shell_surface *shell_surf = get_ivi_shell_surface(surface);
|
||||
|
||||
return snprintf(buf, len, "ivi-surface %#x", shell_surf->id_surface);
|
||||
}
|
||||
|
||||
static void
|
||||
layout_surface_cleanup(struct ivi_shell_surface *ivisurf)
|
||||
{
|
||||
|
|
@ -232,7 +238,7 @@ layout_surface_cleanup(struct ivi_shell_surface *ivisurf)
|
|||
|
||||
ivisurf->surface->committed = NULL;
|
||||
ivisurf->surface->committed_private = NULL;
|
||||
weston_surface_set_label(ivisurf->surface, NULL);
|
||||
weston_surface_set_label_func(ivisurf->surface, NULL);
|
||||
ivisurf->surface = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +323,6 @@ application_surface_create(struct wl_client *client,
|
|||
struct weston_surface *weston_surface =
|
||||
wl_resource_get_user_data(surface_resource);
|
||||
struct wl_resource *res;
|
||||
char *label;
|
||||
|
||||
if (weston_surface_set_role(weston_surface, "ivi_surface",
|
||||
resource, IVI_APPLICATION_ERROR_ROLE) < 0)
|
||||
|
|
@ -338,7 +343,7 @@ application_surface_create(struct wl_client *client,
|
|||
|
||||
ivisurf = xzalloc(sizeof *ivisurf);
|
||||
|
||||
wl_list_init(&ivisurf->surface_label_update.link);
|
||||
wl_list_init(&ivisurf->link);
|
||||
wl_list_insert(&shell->ivi_surface_list, &ivisurf->link);
|
||||
|
||||
ivisurf->shell = shell;
|
||||
|
|
@ -367,9 +372,8 @@ application_surface_create(struct wl_client *client,
|
|||
|
||||
weston_surface->committed = ivi_shell_surface_committed;
|
||||
weston_surface->committed_private = ivisurf;
|
||||
|
||||
str_printf(&label, "ivi-surface %u", ivisurf->id_surface);
|
||||
weston_surface_set_label(weston_surface, label);
|
||||
weston_surface_set_label_func(weston_surface,
|
||||
ivi_shell_surface_get_label);
|
||||
|
||||
res = wl_resource_create(client, &ivi_surface_interface, 1, id);
|
||||
if (res == NULL) {
|
||||
|
|
@ -618,7 +622,7 @@ static void
|
|||
desktop_surface_ping_timeout(struct weston_desktop_client *client,
|
||||
void *user_data)
|
||||
{
|
||||
ivi_layout_desktop_surface_ping_timeout(client);
|
||||
/* Not supported */
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -628,18 +632,6 @@ desktop_surface_pong(struct weston_desktop_client *client,
|
|||
/* Not supported */
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_update_label(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface = data;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_added(struct weston_desktop_surface *surface,
|
||||
void *user_data)
|
||||
|
|
@ -672,10 +664,6 @@ desktop_surface_added(struct weston_desktop_surface *surface,
|
|||
wl_list_init(&ivisurf->children_link);
|
||||
|
||||
weston_desktop_surface_set_user_data(surface, ivisurf);
|
||||
|
||||
ivisurf->surface_label_update.notify = desktop_surface_update_label;
|
||||
weston_desktop_surface_add_metadata_listener(surface, &ivisurf->surface_label_update);
|
||||
desktop_surface_update_label(&ivisurf->surface_label_update, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -688,7 +676,6 @@ desktop_surface_removed(struct weston_desktop_surface *surface,
|
|||
|
||||
assert(ivisurf != NULL);
|
||||
|
||||
wl_list_remove(&ivisurf->surface_label_update.link);
|
||||
weston_desktop_surface_set_user_data(surface, NULL);
|
||||
|
||||
wl_list_for_each_safe(ivisurf_child, tmp, &ivisurf->children_list,
|
||||
|
|
@ -889,6 +876,12 @@ update_input_panels(struct wl_listener *listener, void *data)
|
|||
ivi_layout_update_text_input_cursor(data);
|
||||
}
|
||||
|
||||
static int
|
||||
input_panel_get_label(struct weston_surface *surface, char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "input panel");
|
||||
}
|
||||
|
||||
static void
|
||||
input_panel_committed(struct weston_surface *surface,
|
||||
struct weston_coord_surface new_origin)
|
||||
|
|
@ -950,7 +943,7 @@ create_input_panel_surface(struct ivi_shell *shell,
|
|||
|
||||
surface->committed = input_panel_committed;
|
||||
surface->committed_private = ipsurf;
|
||||
weston_surface_set_label_static(surface, "input panel");
|
||||
weston_surface_set_label_func(surface, input_panel_get_label);
|
||||
|
||||
wl_list_init(&ipsurf->link);
|
||||
wl_list_insert(&shell->input_panel.surfaces, &ipsurf->link);
|
||||
|
|
@ -1023,7 +1016,7 @@ destroy_input_panel_surface_resource(struct wl_resource *resource)
|
|||
|
||||
ipsurf->surface->committed = NULL;
|
||||
ipsurf->surface->committed_private = NULL;
|
||||
weston_surface_set_label(ipsurf->surface, NULL);
|
||||
weston_surface_set_label_func(ipsurf->surface, NULL);
|
||||
ipsurf->surface = NULL;
|
||||
|
||||
wl_list_remove(&ipsurf->surface_destroy_listener.link);
|
||||
|
|
|
|||
|
|
@ -96,9 +96,3 @@ workspace-id=3
|
|||
icon-id=4010
|
||||
icon=@westondatadir@/icon_ivi_smoke.png
|
||||
path=@bindir@/weston-smoke
|
||||
|
||||
[ivi-launcher]
|
||||
workspace-id=3
|
||||
icon-id=4011
|
||||
icon=@westondatadir@/icon_ivi_simple-egl-vertical.png
|
||||
command=@bindir@/weston-simple-egl -v
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <linux/input.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -36,7 +34,6 @@
|
|||
#include "frontend/weston.h"
|
||||
#include "libweston/libweston.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/xalloc.h"
|
||||
#include <libweston/shell-utils.h>
|
||||
|
||||
#include <libweston/xwayland-api.h>
|
||||
|
|
@ -140,7 +137,7 @@ xwayland_get_xwayland_name(struct kiosk_shell_surface *shsurf, enum window_atom_
|
|||
|
||||
static void
|
||||
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_output *shoutput);
|
||||
struct weston_output *output);
|
||||
static void
|
||||
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_surface *parent);
|
||||
|
|
@ -150,6 +147,9 @@ kiosk_shell_output_set_active_surface_tree(struct kiosk_shell_output *shoutput,
|
|||
static void
|
||||
kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
|
||||
struct kiosk_shell_surface *shroot);
|
||||
static struct kiosk_shell_output *
|
||||
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
|
||||
struct weston_output *output);
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_notify_parent_destroy(struct wl_listener *listener, void *data)
|
||||
|
|
@ -183,7 +183,7 @@ kiosk_shell_surface_get_parent_root(struct kiosk_shell_surface *shsurf)
|
|||
static bool
|
||||
kiosk_shell_output_has_app_id(char *config_app_ids, const char *app_id);
|
||||
|
||||
static struct kiosk_shell_output *
|
||||
static struct weston_output *
|
||||
kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput;
|
||||
|
|
@ -208,7 +208,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
|
||||
if (found_wm_name && found_wm_class) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_name_app_ids,
|
||||
wm_name)) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,7 +229,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
if (kiosk_shell_output_has_app_id(shoutput->x11_wm_class_app_ids,
|
||||
wm_class)) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -237,7 +237,7 @@ kiosk_shell_surface_find_best_output_for_xwayland(struct kiosk_shell_surface *sh
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct kiosk_shell_output *
|
||||
static struct weston_output *
|
||||
kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct weston_output *output;
|
||||
|
|
@ -255,14 +255,14 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
|||
wl_list_for_each(shoutput, &shsurf->shell->output_list, link) {
|
||||
if (kiosk_shell_output_has_app_id(shoutput->app_ids, app_id)) {
|
||||
shsurf->appid_output_assigned = true;
|
||||
return shoutput;
|
||||
return shoutput->output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
shoutput = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
|
||||
if (shoutput)
|
||||
return shoutput;
|
||||
output = kiosk_shell_surface_find_best_output_for_xwayland(shsurf);
|
||||
if (output)
|
||||
return output;
|
||||
|
||||
/* Group all related windows in the same output. */
|
||||
root = kiosk_shell_surface_get_parent_root(shsurf);
|
||||
|
|
@ -271,20 +271,20 @@ kiosk_shell_surface_find_best_output(struct kiosk_shell_surface *shsurf)
|
|||
|
||||
output = weston_shell_utils_get_focused_output(shsurf->shell->compositor);
|
||||
if (output)
|
||||
return weston_output_get_shell_private(output);
|
||||
return output;
|
||||
|
||||
output = weston_shell_utils_get_default_output(shsurf->shell->compositor);
|
||||
if (output)
|
||||
return weston_output_get_shell_private(output);
|
||||
return output;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_output *shoutput)
|
||||
struct weston_output *output)
|
||||
{
|
||||
shsurf->output = shoutput;
|
||||
shsurf->output = output;
|
||||
|
||||
if (shsurf->output_destroy_listener.notify) {
|
||||
wl_list_remove(&shsurf->output_destroy_listener.link);
|
||||
|
|
@ -296,39 +296,39 @@ kiosk_shell_surface_set_output(struct kiosk_shell_surface *shsurf,
|
|||
|
||||
shsurf->output_destroy_listener.notify =
|
||||
kiosk_shell_surface_notify_output_destroy;
|
||||
wl_signal_add(&shsurf->output->output->destroy_signal,
|
||||
wl_signal_add(&shsurf->output->destroy_signal,
|
||||
&shsurf->output_destroy_listener);
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_set_fullscreen(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_output *shoutput)
|
||||
struct weston_output *output)
|
||||
{
|
||||
if (!shoutput)
|
||||
shoutput = kiosk_shell_surface_find_best_output(shsurf);
|
||||
if (!output)
|
||||
output = kiosk_shell_surface_find_best_output(shsurf);
|
||||
|
||||
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_output(shsurf, output);
|
||||
|
||||
weston_desktop_surface_set_fullscreen(shsurf->desktop_surface, true);
|
||||
if (shsurf->output)
|
||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||
shsurf->output->output->width,
|
||||
shsurf->output->output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_set_maximized(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput =
|
||||
struct weston_output *output =
|
||||
kiosk_shell_surface_find_best_output(shsurf);
|
||||
|
||||
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_output(shsurf, output);
|
||||
|
||||
weston_desktop_surface_set_maximized(shsurf->desktop_surface, true);
|
||||
if (shsurf->output)
|
||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||
shsurf->output->output->width,
|
||||
shsurf->output->output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -382,7 +382,9 @@ static void
|
|||
kiosk_shell_surface_set_parent(struct kiosk_shell_surface *shsurf,
|
||||
struct kiosk_shell_surface *parent)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
kiosk_shell_find_shell_output(shsurf->shell,
|
||||
shsurf->output);
|
||||
struct kiosk_shell_surface *shroot = parent ?
|
||||
kiosk_shell_surface_get_parent_root(parent) :
|
||||
kiosk_shell_surface_get_parent_root(shsurf);
|
||||
|
|
@ -434,37 +436,23 @@ static void
|
|||
kiosk_shell_surface_reconfigure_for_output(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface;
|
||||
struct weston_output *w_output;
|
||||
|
||||
if (!shsurf->output)
|
||||
return;
|
||||
|
||||
w_output = shsurf->output->output;
|
||||
desktop_surface = shsurf->desktop_surface;
|
||||
|
||||
if (weston_desktop_surface_get_maximized(desktop_surface) ||
|
||||
weston_desktop_surface_get_fullscreen(desktop_surface)) {
|
||||
weston_desktop_surface_set_size(desktop_surface,
|
||||
w_output->width,
|
||||
w_output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
}
|
||||
|
||||
weston_shell_utils_center_on_output(shsurf->view, w_output);
|
||||
weston_shell_utils_center_on_output(shsurf->view, shsurf->output);
|
||||
weston_view_update_transform(shsurf->view);
|
||||
}
|
||||
|
||||
static void
|
||||
desktop_surface_update_label(struct wl_listener *listener, void *data)
|
||||
{
|
||||
struct weston_desktop_surface *desktop_surface = data;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
char *label;
|
||||
|
||||
label = weston_desktop_surface_make_label(desktop_surface);
|
||||
weston_surface_set_label(surface, label);
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_surface_destroy(struct kiosk_shell_surface *shsurf)
|
||||
{
|
||||
|
|
@ -489,8 +477,6 @@ kiosk_shell_surface_destroy(struct kiosk_shell_surface *shsurf)
|
|||
shsurf->parent = NULL;
|
||||
}
|
||||
|
||||
wl_list_remove(&shsurf->surface_label_update.link);
|
||||
|
||||
free(shsurf);
|
||||
}
|
||||
|
||||
|
|
@ -528,10 +514,6 @@ kiosk_shell_surface_create(struct kiosk_shell *shell,
|
|||
wl_signal_init(&shsurf->destroy_signal);
|
||||
wl_signal_init(&shsurf->parent_destroy_signal);
|
||||
|
||||
shsurf->surface_label_update.notify = desktop_surface_update_label;
|
||||
weston_desktop_surface_add_metadata_listener(desktop_surface, &shsurf->surface_label_update);
|
||||
desktop_surface_update_label(&shsurf->surface_label_update, desktop_surface);
|
||||
|
||||
/* start life inserting itself as root of its own surface tree list */
|
||||
wl_list_init(&shsurf->surface_tree_list);
|
||||
wl_list_init(&shsurf->surface_tree_link);
|
||||
|
|
@ -548,7 +530,8 @@ kiosk_shell_surface_activate(struct kiosk_shell_surface *shsurf,
|
|||
struct weston_desktop_surface *dsurface = shsurf->desktop_surface;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(dsurface);
|
||||
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
|
||||
|
||||
/* keyboard focus */
|
||||
weston_view_activate_input(shsurf->view, kiosk_seat->seat, activate_flags);
|
||||
|
|
@ -693,6 +676,13 @@ kiosk_shell_output_raise_surface_subtree(struct kiosk_shell_output *shoutput,
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
kiosk_shell_background_surface_get_label(struct weston_surface *surface,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return snprintf(buf, len, "kiosk shell background surface");
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_output_recreate_background(struct kiosk_shell_output *shoutput)
|
||||
{
|
||||
|
|
@ -726,7 +716,7 @@ kiosk_shell_output_recreate_background(struct kiosk_shell_output *shoutput)
|
|||
|
||||
curtain_params.capture_input = true;
|
||||
|
||||
curtain_params.label = xstrdup("kiosk shell background surface");
|
||||
curtain_params.get_label = kiosk_shell_background_surface_get_label;
|
||||
curtain_params.surface_committed = NULL;
|
||||
curtain_params.surface_private = NULL;
|
||||
|
||||
|
|
@ -834,11 +824,8 @@ kiosk_shell_output_create(struct kiosk_shell *shell, struct weston_output *outpu
|
|||
|
||||
wl_list_insert(shell->output_list.prev, &shoutput->link);
|
||||
|
||||
weston_output_set_shell_private(output, shoutput);
|
||||
|
||||
kiosk_shell_output_recreate_background(shoutput);
|
||||
kiosk_shell_output_configure(shoutput);
|
||||
weston_output_set_ready(output);
|
||||
|
||||
return shoutput;
|
||||
}
|
||||
|
|
@ -853,11 +840,14 @@ desktop_surface_added(struct weston_desktop_surface *desktop_surface,
|
|||
{
|
||||
struct kiosk_shell *shell = data;
|
||||
struct kiosk_shell_surface *shsurf;
|
||||
struct weston_surface *surface =
|
||||
weston_desktop_surface_get_surface(desktop_surface);
|
||||
|
||||
shsurf = kiosk_shell_surface_create(shell, desktop_surface);
|
||||
if (!shsurf)
|
||||
return;
|
||||
|
||||
weston_surface_set_label_func(surface, weston_shell_utils_surface_get_label);
|
||||
kiosk_shell_surface_set_fullscreen(shsurf, NULL);
|
||||
}
|
||||
|
||||
|
|
@ -880,9 +870,6 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
|
|||
struct weston_layer *layer;
|
||||
struct weston_view *view;
|
||||
|
||||
if (!shsurf->output)
|
||||
return NULL;
|
||||
|
||||
wl_list_for_each(layer, layers, link) {
|
||||
struct kiosk_shell *shell = shsurf->shell;
|
||||
|
||||
|
|
@ -898,7 +885,7 @@ find_focus_successor(struct kiosk_shell_surface *shsurf,
|
|||
continue;
|
||||
|
||||
/* pick views only on the same output */
|
||||
if (view->output != shsurf->output->output)
|
||||
if (view->output != shsurf->output)
|
||||
continue;
|
||||
|
||||
view_shsurf = get_kiosk_shell_surface(view->surface);
|
||||
|
|
@ -960,7 +947,7 @@ desktop_surface_removed(struct weston_desktop_surface *desktop_surface,
|
|||
|
||||
successor = find_focus_successor(shsurf,
|
||||
kiosk_seat->focused_surface);
|
||||
shoutput = shsurf->output;
|
||||
shoutput = kiosk_shell_find_shell_output(shsurf->shell, shsurf->output);
|
||||
if (shoutput && successor) {
|
||||
enum weston_layer_position succesor_view_layer_pos;
|
||||
|
||||
|
|
@ -1004,17 +991,17 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
return;
|
||||
|
||||
if (!shsurf->appid_output_assigned && app_id) {
|
||||
struct kiosk_shell_output *shoutput = NULL;
|
||||
struct weston_output *output = NULL;
|
||||
|
||||
/* reset previous output being set in _added() as the output is
|
||||
* being cached */
|
||||
shsurf->output = NULL;
|
||||
shoutput = kiosk_shell_surface_find_best_output(shsurf);
|
||||
output = kiosk_shell_surface_find_best_output(shsurf);
|
||||
|
||||
kiosk_shell_surface_set_output(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_output(shsurf, output);
|
||||
weston_desktop_surface_set_size(shsurf->desktop_surface,
|
||||
shoutput->output->width,
|
||||
shoutput->output->height);
|
||||
shsurf->output->width,
|
||||
shsurf->output->height);
|
||||
/* even if we couldn't find an appid set for a particular
|
||||
* output still flag the shsurf as to a avoid changing the
|
||||
* output every time */
|
||||
|
|
@ -1034,7 +1021,7 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
if (!weston_surface_is_mapped(surface) || (is_resized && is_fullscreen)) {
|
||||
if (is_fullscreen || !shsurf->xwayland.is_set) {
|
||||
weston_shell_utils_center_on_output(shsurf->view,
|
||||
shsurf->output->output);
|
||||
shsurf->output);
|
||||
} else {
|
||||
struct weston_coord_surface offset;
|
||||
struct weston_geometry geometry =
|
||||
|
|
@ -1053,7 +1040,9 @@ desktop_surface_committed(struct weston_desktop_surface *desktop_surface,
|
|||
if (!weston_surface_is_mapped(surface)) {
|
||||
struct weston_seat *seat =
|
||||
get_kiosk_shell_first_seat(shsurf->shell);
|
||||
struct kiosk_shell_output *shoutput = shsurf->output;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
kiosk_shell_find_shell_output(shsurf->shell,
|
||||
shsurf->output);
|
||||
struct kiosk_shell_seat *kiosk_seat;
|
||||
|
||||
weston_surface_map(surface);
|
||||
|
|
@ -1145,10 +1134,6 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
|
|||
{
|
||||
struct kiosk_shell_surface *shsurf =
|
||||
weston_desktop_surface_get_user_data(desktop_surface);
|
||||
struct kiosk_shell_output *shoutput = NULL;
|
||||
|
||||
if (output)
|
||||
shoutput = weston_output_get_shell_private(output);
|
||||
|
||||
/* We should normally be able to ignore fullscreen requests for
|
||||
* top-level surfaces, since we set them as fullscreen at creation
|
||||
|
|
@ -1163,7 +1148,7 @@ desktop_surface_fullscreen_requested(struct weston_desktop_surface *desktop_surf
|
|||
*/
|
||||
|
||||
if (!shsurf->parent || fullscreen)
|
||||
kiosk_shell_surface_set_fullscreen(shsurf, shoutput);
|
||||
kiosk_shell_surface_set_fullscreen(shsurf, output);
|
||||
else
|
||||
kiosk_shell_surface_set_normal(shsurf);
|
||||
}
|
||||
|
|
@ -1247,6 +1232,20 @@ static const struct weston_desktop_api kiosk_shell_desktop_api = {
|
|||
* kiosk_shell
|
||||
*/
|
||||
|
||||
static struct kiosk_shell_output *
|
||||
kiosk_shell_find_shell_output(struct kiosk_shell *shell,
|
||||
struct weston_output *output)
|
||||
{
|
||||
struct kiosk_shell_output *shoutput;
|
||||
|
||||
wl_list_for_each(shoutput, &shell->output_list, link) {
|
||||
if (shoutput->output == output)
|
||||
return shoutput;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
kiosk_shell_activate_view(struct kiosk_shell *shell,
|
||||
struct weston_view *view,
|
||||
|
|
@ -1335,7 +1334,7 @@ kiosk_shell_handle_output_resized(struct wl_listener *listener, void *data)
|
|||
container_of(listener, struct kiosk_shell, output_resized_listener);
|
||||
struct weston_output *output = data;
|
||||
struct kiosk_shell_output *shoutput =
|
||||
weston_output_get_shell_private(output);
|
||||
kiosk_shell_find_shell_output(shell, output);
|
||||
struct weston_view *view;
|
||||
|
||||
kiosk_shell_output_recreate_background(shoutput);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ struct kiosk_shell_surface {
|
|||
|
||||
struct kiosk_shell *shell;
|
||||
|
||||
struct kiosk_shell_output *output;
|
||||
struct weston_output *output;
|
||||
struct wl_listener output_destroy_listener;
|
||||
|
||||
struct wl_signal destroy_signal;
|
||||
|
|
@ -80,8 +80,6 @@ struct kiosk_shell_surface {
|
|||
} xwayland;
|
||||
|
||||
bool appid_output_assigned;
|
||||
|
||||
struct wl_listener surface_label_update;
|
||||
};
|
||||
|
||||
struct kiosk_shell_seat {
|
||||
|
|
|
|||
|
|
@ -199,19 +199,7 @@ weston_view_animation_frame(struct weston_animation *base,
|
|||
struct weston_compositor *compositor =
|
||||
animation->view->surface->compositor;
|
||||
|
||||
/* Animations are created with timestamp 0, so we need to set a
|
||||
* real time base on the first repaint.
|
||||
*
|
||||
* In some cases, such as when the repaint loop has just started
|
||||
* for a new display, the time we're given could be 0 for our
|
||||
* second call - but this is ok because weston_spring_update() will
|
||||
* do nothing as long as spring.timestamp == time.
|
||||
*
|
||||
* We can safely just keep updating the timestamp until we get
|
||||
* something non-zero, and the spring will start updating after
|
||||
* that.
|
||||
*/
|
||||
if (!timespec_to_msec(&animation->spring.timestamp))
|
||||
if (base->frame_counter <= 1)
|
||||
animation->spring.timestamp = *time;
|
||||
|
||||
weston_spring_update(&animation->spring, time);
|
||||
|
|
@ -287,6 +275,7 @@ weston_view_animation_run(struct weston_view_animation *animation)
|
|||
{
|
||||
struct timespec zero_time = { 0 };
|
||||
|
||||
animation->animation.frame_counter = 0;
|
||||
weston_view_animation_frame(&animation->animation, NULL, &zero_time);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,12 +40,26 @@
|
|||
#include "pixman-renderer.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "renderer-vulkan/vulkan-renderer.h"
|
||||
#include "shared/weston-assert.h"
|
||||
#include "shared/weston-egl-ext.h"
|
||||
#include "linux-dmabuf.h"
|
||||
#include "linux-explicit-synchronization.h"
|
||||
#include "shared/xalloc.h"
|
||||
|
||||
static struct gbm_device *
|
||||
create_gbm_device(int fd)
|
||||
{
|
||||
struct gbm_device *gbm;
|
||||
|
||||
/* GBM will load a dri driver, but even though they need symbols from
|
||||
* libglapi, in some version of Mesa they are not linked to it. Since
|
||||
* only the gl-renderer module links to it, the call above won't make
|
||||
* these symbols globally available, and loading the DRI driver fails.
|
||||
* Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
|
||||
dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
|
||||
|
||||
gbm = gbm_create_device(fd);
|
||||
|
||||
return gbm;
|
||||
}
|
||||
|
||||
/* When initializing EGL, if the preferred buffer format isn't available
|
||||
* we may be able to substitute an ARGB format for an XRGB one.
|
||||
|
|
@ -85,32 +99,12 @@ drm_backend_create_gl_renderer(struct drm_backend *b)
|
|||
&options.base);
|
||||
}
|
||||
|
||||
static int
|
||||
drm_backend_create_vulkan_renderer(struct drm_backend *b)
|
||||
{
|
||||
const struct pixel_format_info *format[3] = {
|
||||
b->format,
|
||||
fallback_format_for(b->format),
|
||||
};
|
||||
struct vulkan_renderer_display_options options = {
|
||||
.formats = format,
|
||||
.formats_count = 1,
|
||||
};
|
||||
|
||||
if (format[1])
|
||||
options.formats_count = 2;
|
||||
|
||||
return weston_compositor_init_renderer(b->compositor,
|
||||
WESTON_RENDERER_VULKAN,
|
||||
&options.base);
|
||||
}
|
||||
|
||||
int
|
||||
init_egl(struct drm_backend *b)
|
||||
{
|
||||
struct drm_device *device = b->drm;
|
||||
|
||||
b->gbm = gbm_create_device(device->kms_device->fd);
|
||||
b->gbm = create_gbm_device(device->drm.fd);
|
||||
if (!b->gbm)
|
||||
return -1;
|
||||
|
||||
|
|
@ -123,24 +117,6 @@ init_egl(struct drm_backend *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
init_vulkan(struct drm_backend *b)
|
||||
{
|
||||
struct drm_device *device = b->drm;
|
||||
|
||||
b->gbm = gbm_create_device(device->kms_device->fd);
|
||||
if (!b->gbm)
|
||||
return -1;
|
||||
|
||||
if (drm_backend_create_vulkan_renderer(b) < 0) {
|
||||
gbm_device_destroy(b->gbm);
|
||||
b->gbm = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drm_output_fini_cursor_egl(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
|
@ -154,19 +130,6 @@ static void drm_output_fini_cursor_egl(struct drm_output *output)
|
|||
}
|
||||
}
|
||||
|
||||
static void drm_output_fini_cursor_vulkan(struct drm_output *output)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
/* This cursor does not have a GBM device */
|
||||
if (output->gbm_cursor_fb[i] && !output->gbm_cursor_fb[i]->bo)
|
||||
output->gbm_cursor_fb[i]->type = BUFFER_PIXMAN_DUMB;
|
||||
drm_fb_unref(output->gbm_cursor_fb[i]);
|
||||
output->gbm_cursor_fb[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
|
|
@ -174,13 +137,13 @@ drm_output_init_cursor_egl(struct drm_output *output, struct drm_backend *b)
|
|||
unsigned int i;
|
||||
|
||||
/* No point creating cursors if we don't have a plane for them. */
|
||||
if (!output->cursor_handle)
|
||||
if (!output->cursor_plane)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
struct gbm_bo *bo;
|
||||
|
||||
if (gbm_device_get_fd(b->gbm) != output->device->kms_device->fd) {
|
||||
if (gbm_device_get_fd(b->gbm) != output->device->drm.fd) {
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_create_dumb(output->device,
|
||||
device->cursor_width,
|
||||
|
|
@ -216,60 +179,11 @@ err:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_output_init_cursor_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
struct drm_device *device = output->device;
|
||||
unsigned int i;
|
||||
|
||||
/* No point creating cursors if we don't have a plane for them. */
|
||||
if (!output->cursor_handle)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(output->gbm_cursor_fb); i++) {
|
||||
struct gbm_bo *bo;
|
||||
|
||||
if (gbm_device_get_fd(b->gbm) != output->device->kms_device->fd) {
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_create_dumb(output->device,
|
||||
device->cursor_width,
|
||||
device->cursor_height,
|
||||
DRM_FORMAT_ARGB8888);
|
||||
/* Override buffer type, since we know it is a cursor */
|
||||
output->gbm_cursor_fb[i]->type = BUFFER_CURSOR;
|
||||
output->gbm_cursor_handle[i] =
|
||||
output->gbm_cursor_fb[i]->handles[0];
|
||||
} else {
|
||||
bo = gbm_bo_create(b->gbm, device->cursor_width, device->cursor_height,
|
||||
GBM_FORMAT_ARGB8888,
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
if (!bo)
|
||||
goto err;
|
||||
|
||||
output->gbm_cursor_fb[i] =
|
||||
drm_fb_get_from_bo(bo, device, false, BUFFER_CURSOR);
|
||||
if (!output->gbm_cursor_fb[i]) {
|
||||
gbm_bo_destroy(bo);
|
||||
goto err;
|
||||
}
|
||||
output->gbm_cursor_handle[i] = gbm_bo_get_handle(bo).s32;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
weston_log("cursor buffers unavailable, using vulkan cursors\n");
|
||||
device->cursors_are_broken = true;
|
||||
drm_output_fini_cursor_vulkan(output);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
||||
{
|
||||
struct weston_mode *mode = output->base.current_mode;
|
||||
struct drm_plane *plane = output->scanout_handle->plane;
|
||||
struct drm_plane *plane = output->scanout_plane;
|
||||
struct weston_drm_format *fmt;
|
||||
const uint64_t *modifiers;
|
||||
unsigned int num_modifiers;
|
||||
|
|
@ -298,7 +212,7 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
|||
* on a different GPU), we have to use linear buffers to make sure that
|
||||
* the allocated GBM surface is correctly displayed on the KMS device.
|
||||
*/
|
||||
if (gbm_device_get_fd(gbm) != output->device->kms_device->fd)
|
||||
if (gbm_device_get_fd(gbm) != output->device->drm.fd)
|
||||
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
|
||||
|
||||
/* We may allocate with no modifiers in the following situations:
|
||||
|
|
@ -315,215 +229,26 @@ create_gbm_surface(struct gbm_device *gbm, struct drm_output *output)
|
|||
output->gbm_bo_flags);
|
||||
}
|
||||
|
||||
enum format_alpha_required {
|
||||
FORMAT_ALPHA_REQUIRED = true,
|
||||
FORMAT_ALPHA_NOT_REQUIRED = false,
|
||||
};
|
||||
|
||||
enum format_component_type {
|
||||
FORMAT_COMPONENT_TYPE_ANY,
|
||||
FORMAT_COMPONENT_TYPE_FLOAT_ONLY,
|
||||
};
|
||||
|
||||
static const struct pixel_format_info *
|
||||
find_compatible_format(struct weston_compositor *compositor,
|
||||
struct wl_array *formats, int min_bpc,
|
||||
enum format_component_type component_type,
|
||||
enum format_alpha_required alpha_required)
|
||||
{
|
||||
const struct pixel_format_info **tmp, *p;
|
||||
const struct pixel_format_info *candidate = NULL;
|
||||
|
||||
/**
|
||||
* Given a format array, this looks for a format respecting a few
|
||||
* criteria. First of all, this ignores formats that do not contain an
|
||||
* alpha channel when alpha_required == FORMAT_ALPHA_REQUIRED. Similar
|
||||
* for formats that are not floating point when component_type ==
|
||||
* FORMAT_COMPONENT_TYPE_FLOAT_ONLY. Also, it ignores formats that do
|
||||
* not have bits per color channel (bpc) bigger or equal to min_bpc.
|
||||
*
|
||||
* When we have multiple formats matching these criteria, we use the
|
||||
* following to choose:
|
||||
*
|
||||
* 1. a format with lower bytes per pixel (bpp) is favored.
|
||||
*
|
||||
* 2. if FORMAT_ALPHA_REQUIRED:
|
||||
* we prefer the format with more bits on the alpha channel
|
||||
* else
|
||||
* we prefer the format with more bits on the color channels
|
||||
*/
|
||||
wl_array_for_each(tmp, formats) {
|
||||
p = *tmp;
|
||||
|
||||
/* Skip candidates that do not match minimum criteria. */
|
||||
if (component_type == FORMAT_COMPONENT_TYPE_FLOAT_ONLY &&
|
||||
p->component_type != PIXEL_COMPONENT_TYPE_FLOAT)
|
||||
continue;
|
||||
if (alpha_required == FORMAT_ALPHA_REQUIRED && p->bits.a == 0)
|
||||
continue;
|
||||
if (p->bits.r < min_bpc || p->bits.g < min_bpc || p->bits.b < min_bpc)
|
||||
continue;
|
||||
|
||||
/* No other good candidate so far, so pick this one. */
|
||||
if (!candidate) {
|
||||
candidate = p;
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* New candidate, let's compare with old and untie.
|
||||
*/
|
||||
|
||||
if (p->bpp > candidate->bpp)
|
||||
continue;
|
||||
|
||||
if (alpha_required == FORMAT_ALPHA_REQUIRED) {
|
||||
if (p->bits.a <= candidate->bits.a)
|
||||
continue;
|
||||
} else {
|
||||
if (p->bits.r + p->bits.g + p->bits.b <=
|
||||
candidate->bits.r + candidate->bits.g + candidate->bits.b)
|
||||
continue;
|
||||
}
|
||||
|
||||
candidate = p;
|
||||
}
|
||||
|
||||
return candidate;
|
||||
}
|
||||
|
||||
static bool
|
||||
drm_output_pick_format_egl(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_backend *b = device->backend;
|
||||
struct weston_compositor *compositor = b->compositor;
|
||||
const struct weston_renderer *renderer = compositor->renderer;
|
||||
const struct pixel_format_info **renderer_formats;
|
||||
const struct pixel_format_info **f;
|
||||
unsigned int renderer_formats_count;
|
||||
struct wl_array supported_formats;
|
||||
enum format_component_type component_type;
|
||||
uint32_t min_bpc;
|
||||
unsigned int i;
|
||||
bool ret = true;
|
||||
bool found;
|
||||
|
||||
wl_array_init(&supported_formats);
|
||||
|
||||
/**
|
||||
* This computes the intersection between renderer formats supported by
|
||||
* EGL and the output scanout plane supported formats. We need that as
|
||||
* we want to select a format supported by both.
|
||||
*/
|
||||
renderer_formats =
|
||||
renderer->gl->get_supported_rendering_formats(b->compositor,
|
||||
&renderer_formats_count);
|
||||
for (i = 0; i < renderer_formats_count; i++) {
|
||||
struct drm_plane *scanout_plane = output->scanout_handle->plane;
|
||||
|
||||
if (!weston_drm_format_array_find_format(&scanout_plane->formats,
|
||||
renderer_formats[i]->format))
|
||||
continue;
|
||||
|
||||
f = wl_array_add(&supported_formats, sizeof(*f));
|
||||
*f = renderer_formats[i];
|
||||
}
|
||||
|
||||
if (output->base.from_blend_to_output_by_backend) {
|
||||
component_type = FORMAT_COMPONENT_TYPE_FLOAT_ONLY;
|
||||
min_bpc = 16;
|
||||
} else if (output->base.eotf_mode != WESTON_EOTF_MODE_SDR) {
|
||||
component_type = FORMAT_COMPONENT_TYPE_ANY;
|
||||
min_bpc = 10;
|
||||
} else {
|
||||
/**
|
||||
* If no requirements, we simply use b->format instead of
|
||||
* looking for a format with bpc >= min_bpc.
|
||||
*/
|
||||
min_bpc = 0;
|
||||
}
|
||||
|
||||
if (min_bpc != 0) {
|
||||
if (output->has_underlay) {
|
||||
output->format =
|
||||
find_compatible_format(compositor, &supported_formats,
|
||||
min_bpc, component_type,
|
||||
FORMAT_ALPHA_REQUIRED);
|
||||
if (output->format)
|
||||
goto done;
|
||||
|
||||
weston_log("Disabling underlay planes: EGL GBM or the primary plane for output '%s'\n" \
|
||||
"does not support format with min bpc %u and alpha channel.\n",
|
||||
output->base.name, min_bpc);
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
output->format =
|
||||
find_compatible_format(compositor, &supported_formats,
|
||||
min_bpc, component_type,
|
||||
FORMAT_ALPHA_NOT_REQUIRED);
|
||||
if (output->format)
|
||||
goto done;
|
||||
|
||||
weston_log("Error: EGL GBM or the primary plane for output '%s' does not support format\n" \
|
||||
"with min bpc %u.\n", output->base.name, min_bpc);
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
found = false;
|
||||
wl_array_for_each(f, &supported_formats) {
|
||||
if ((*f)->format == b->format->format) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
weston_log("Error: format %s unsupported by EGL GBM or the primary plane for output '%s'.\n",
|
||||
b->format->drm_format_name, output->base.name);
|
||||
ret = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (output->has_underlay && (b->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: b->format %s does not have alpha channel,\n"
|
||||
"which is required to support underlay planes.\n",
|
||||
b->format->drm_format_name);
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
output->format = b->format;
|
||||
|
||||
done:
|
||||
wl_array_release(&supported_formats);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Init output state that depends on gl or gbm */
|
||||
int
|
||||
drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
const struct weston_mode *mode = output->base.current_mode;
|
||||
const struct pixel_format_info *format[2] = { 0 };
|
||||
struct gl_renderer_output_options options;
|
||||
|
||||
if (!output->format && !drm_output_pick_format_egl(output))
|
||||
return -1;
|
||||
|
||||
format[0] = output->format;
|
||||
if (!output->has_underlay)
|
||||
format[1] = fallback_format_for(output->format);
|
||||
|
||||
options.formats = format;
|
||||
options.formats_count = format[1] ? 2 : 1;
|
||||
options.area.x = 0;
|
||||
options.area.y = 0;
|
||||
options.area.width = mode->width;
|
||||
options.area.height = mode->height;
|
||||
options.fb_size.width = mode->width;
|
||||
options.fb_size.height = mode->height;
|
||||
const struct pixel_format_info *format[2] = {
|
||||
output->format,
|
||||
fallback_format_for(output->format),
|
||||
};
|
||||
struct gl_renderer_output_options options = {
|
||||
.formats = format,
|
||||
.formats_count = 1,
|
||||
.area.x = 0,
|
||||
.area.y = 0,
|
||||
.area.width = mode->width,
|
||||
.area.height = mode->height,
|
||||
.fb_size.width = mode->width,
|
||||
.fb_size.height = mode->height,
|
||||
};
|
||||
|
||||
assert(output->gbm_surface == NULL);
|
||||
create_gbm_surface(b->gbm, output);
|
||||
|
|
@ -532,6 +257,8 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (options.formats[1])
|
||||
options.formats_count = 2;
|
||||
options.window_for_legacy = (EGLNativeWindowType) output->gbm_surface;
|
||||
options.window_for_platform = output->gbm_surface;
|
||||
if (renderer->gl->output_window_create(&output->base, &options) < 0) {
|
||||
|
|
@ -546,208 +273,6 @@ drm_output_init_egl(struct drm_output *output, struct drm_backend *b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct gbm_bo *
|
||||
drm_gbm_create_bo(struct gbm_device *gbm, struct drm_output *output)
|
||||
{
|
||||
struct weston_mode *mode = output->base.current_mode;
|
||||
struct drm_plane *plane = output->scanout_handle->plane;
|
||||
struct weston_drm_format *fmt;
|
||||
const uint64_t *modifiers;
|
||||
unsigned int num_modifiers;
|
||||
struct gbm_bo *bo = NULL;
|
||||
|
||||
/*
|
||||
* TODO: Currently, this method allocates a buffer based on the list
|
||||
* of acceptable modifiers received from the DRM backend but does not
|
||||
* check it against formats renderable by the renderer.
|
||||
* To support cases where the renderer may not support the same
|
||||
* modifiers (e.g. Vulkan software renderer) it should match against
|
||||
* renderer modifiers.
|
||||
*/
|
||||
|
||||
fmt = weston_drm_format_array_find_format(&plane->formats,
|
||||
output->format->format);
|
||||
if (!fmt) {
|
||||
weston_log("format %s not supported by output %s\n",
|
||||
output->format->drm_format_name,
|
||||
output->base.name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!weston_drm_format_has_modifier(fmt, DRM_FORMAT_MOD_INVALID)) {
|
||||
modifiers = weston_drm_format_get_modifiers(fmt, &num_modifiers);
|
||||
bo = gbm_bo_create_with_modifiers(gbm, mode->width, mode->height,
|
||||
output->format->format,
|
||||
modifiers, num_modifiers);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we cannot use modifiers to allocate the GBM surface and
|
||||
* the GBM device differs from the KMS display device, try to
|
||||
* use linear buffers and hope that the allocated GBM surface
|
||||
* is correctly displayed on the KMS device.
|
||||
*/
|
||||
if (gbm_device_get_fd(gbm) != output->device->kms_device->fd)
|
||||
output->gbm_bo_flags |= GBM_BO_USE_LINEAR;
|
||||
|
||||
if (!bo) {
|
||||
bo = gbm_bo_create(gbm, mode->width, mode->height,
|
||||
output->format->format, output->gbm_bo_flags);
|
||||
}
|
||||
|
||||
return bo;
|
||||
}
|
||||
|
||||
struct drm_gbm_dmabuf {
|
||||
struct linux_dmabuf_memory base;
|
||||
struct gbm_bo *bo;
|
||||
};
|
||||
|
||||
static void
|
||||
drm_gbm_dmabuf_destroy(struct linux_dmabuf_memory *dmabuf)
|
||||
{
|
||||
struct dmabuf_attributes *attributes;
|
||||
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||
struct gbm_bo *bo;
|
||||
|
||||
drm_gbm_dmabuf = container_of(dmabuf, struct drm_gbm_dmabuf, base);
|
||||
bo = drm_gbm_dmabuf->bo;
|
||||
assert(bo);
|
||||
|
||||
gbm_bo_destroy(bo);
|
||||
|
||||
attributes = dmabuf->attributes;
|
||||
for (int i = 0; i < attributes->n_planes; ++i)
|
||||
close(attributes->fd[i]);
|
||||
free(dmabuf->attributes);
|
||||
|
||||
free(drm_gbm_dmabuf);
|
||||
}
|
||||
|
||||
static struct drm_gbm_dmabuf *
|
||||
drm_gbm_bo_get_dmabuf(struct gbm_device *gbm, struct drm_output *output, struct gbm_bo *bo)
|
||||
{
|
||||
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||
struct dmabuf_attributes *attributes;
|
||||
|
||||
attributes = xzalloc(sizeof(*attributes));
|
||||
attributes->width = gbm_bo_get_width(bo);
|
||||
attributes->height = gbm_bo_get_height(bo);
|
||||
attributes->format = gbm_bo_get_format(bo);
|
||||
attributes->n_planes = gbm_bo_get_plane_count(bo);
|
||||
for (int i = 0; i < attributes->n_planes; ++i) {
|
||||
attributes->fd[i] = gbm_bo_get_fd(bo);
|
||||
attributes->stride[i] = gbm_bo_get_stride_for_plane(bo, i);
|
||||
attributes->offset[i] = gbm_bo_get_offset(bo, i);
|
||||
}
|
||||
attributes->modifier = gbm_bo_get_modifier(bo);
|
||||
|
||||
drm_gbm_dmabuf = xzalloc(sizeof(*drm_gbm_dmabuf));
|
||||
drm_gbm_dmabuf->base.attributes = attributes;
|
||||
drm_gbm_dmabuf->base.destroy = drm_gbm_dmabuf_destroy;
|
||||
drm_gbm_dmabuf->bo = bo;
|
||||
|
||||
return drm_gbm_dmabuf;
|
||||
}
|
||||
|
||||
static void
|
||||
create_renderbuffers(struct gbm_device *gbm, struct drm_output *output, unsigned int n)
|
||||
{
|
||||
struct weston_renderer *renderer = output->base.compositor->renderer;
|
||||
|
||||
for (unsigned int i = 0; i < n; i++) {
|
||||
struct drm_gbm_dmabuf *drm_gbm_dmabuf;
|
||||
struct gbm_bo *bo;
|
||||
|
||||
bo = drm_gbm_create_bo(gbm, output);
|
||||
if (!bo) {
|
||||
weston_log("failed to allocate bo\n");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_gbm_dmabuf = drm_gbm_bo_get_dmabuf(gbm, output, bo);
|
||||
if (!drm_gbm_dmabuf) {
|
||||
weston_log("failed to allocate dmabuf\n");
|
||||
return;
|
||||
}
|
||||
|
||||
output->renderbuffer[i] =
|
||||
renderer->create_renderbuffer_dmabuf(&output->base,
|
||||
&drm_gbm_dmabuf->base,
|
||||
NULL, NULL);
|
||||
if (!output->renderbuffer[i]) {
|
||||
weston_log("failed to allocate renderbuffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
output->linux_dmabuf_memory[i] = &drm_gbm_dmabuf->base;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
drm_output_pick_format_vulkan(struct drm_output *output)
|
||||
{
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_backend *b = device->backend;
|
||||
|
||||
/* Any other value of eotf_mode requires color-management, which is not
|
||||
* yet supported by vulkan-renderer. */
|
||||
assert(output->base.eotf_mode == WESTON_EOTF_MODE_SDR);
|
||||
|
||||
if (!b->format->vulkan_format) {
|
||||
weston_log("Error: failed to pick format for output '%s', format %s unsupported by vulkan-renderer.\n",
|
||||
output->base.name, b->format->drm_format_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(b->format);
|
||||
output->format = b->format;
|
||||
|
||||
if (output->has_underlay && (output->format->bits.a == 0)) {
|
||||
weston_log("Disabling underlay planes: output '%s' with format %s does not have alpha channel,\n"
|
||||
"which is required to support underlay planes.\n",
|
||||
output->base.name, output->format->drm_format_name);
|
||||
output->has_underlay = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Init output state that depends on vulkan */
|
||||
int
|
||||
drm_output_init_vulkan(struct drm_output *output, struct drm_backend *b)
|
||||
{
|
||||
const struct weston_mode *mode = output->base.current_mode;
|
||||
struct weston_renderer *renderer = b->compositor->renderer;
|
||||
|
||||
if (!output->format && !drm_output_pick_format_vulkan(output))
|
||||
return -1;
|
||||
|
||||
const struct vulkan_renderer_surfaceless_options options = {
|
||||
.area.x = 0,
|
||||
.area.y = 0,
|
||||
.area.width = mode->width,
|
||||
.area.height = mode->height,
|
||||
.fb_size.width = mode->width,
|
||||
.fb_size.height = mode->height,
|
||||
};
|
||||
|
||||
if (renderer->vulkan->output_surfaceless_create(&output->base, &options) < 0) {
|
||||
weston_log("failed to create vulkan renderer output state\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
create_renderbuffers(b->gbm, output, ARRAY_LENGTH(output->renderbuffer));
|
||||
if (!output->linux_dmabuf_memory[0]) {
|
||||
weston_log("failed to create dmabufs\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
drm_output_init_cursor_vulkan(output, b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
drm_output_fini_egl(struct drm_output *output)
|
||||
{
|
||||
|
|
@ -755,8 +280,12 @@ drm_output_fini_egl(struct drm_output *output)
|
|||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
|
||||
/* Destroying the GBM surface will destroy all our GBM buffers,
|
||||
* regardless of refcount. */
|
||||
weston_assert_ptr_null(b->compositor, output->scanout_handle);
|
||||
* regardless of refcount. Ensure we destroy them here. */
|
||||
if (!b->compositor->shutting_down &&
|
||||
output->scanout_plane->state_cur->fb &&
|
||||
output->scanout_plane->state_cur->fb->type == BUFFER_GBM_SURFACE) {
|
||||
drm_plane_reset_state(output->scanout_plane);
|
||||
}
|
||||
|
||||
renderer->gl->output_destroy(&output->base);
|
||||
gbm_surface_destroy(output->gbm_surface);
|
||||
|
|
@ -764,22 +293,6 @@ drm_output_fini_egl(struct drm_output *output)
|
|||
drm_output_fini_cursor_egl(output);
|
||||
}
|
||||
|
||||
void
|
||||
drm_output_fini_vulkan(struct drm_output *output)
|
||||
{
|
||||
struct drm_backend *b = output->backend;
|
||||
const struct weston_renderer *renderer = b->compositor->renderer;
|
||||
|
||||
weston_assert_ptr_null(b->compositor, output->scanout_handle);
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_LENGTH(output->renderbuffer); i++)
|
||||
renderer->destroy_renderbuffer(output->renderbuffer[i]);
|
||||
|
||||
renderer->vulkan->output_destroy(&output->base);
|
||||
|
||||
drm_output_fini_cursor_vulkan(output);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_output_render_gl(struct drm_output_state *state, pixman_region32_t *damage)
|
||||
{
|
||||
|
|
@ -811,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,12 +78,6 @@
|
|||
#define DRM_PLANE_ALPHA_OPAQUE 0xffffUL
|
||||
#endif
|
||||
|
||||
#ifndef MAX_DMABUF_PLANES
|
||||
#define MAX_DMABUF_PLANES 4
|
||||
#endif
|
||||
|
||||
#define DRM_MAX_REUSE_FAILURES 10
|
||||
|
||||
/**
|
||||
* A small wrapper to print information into the 'drm-backend' debug scope.
|
||||
*
|
||||
|
|
@ -117,15 +111,8 @@
|
|||
* system. To avoid confusing side effects, we explicitly cast to the widest
|
||||
* possible type and use a matching format specifier.
|
||||
*/
|
||||
#define DO_DRM_DEBUG_COMPLEX(scope, ...) \
|
||||
weston_log_scope_printf(scope, __VA_ARGS__)
|
||||
|
||||
#define DO_DRM_DEBUG(scope, string) \
|
||||
weston_log_scope_puts(scope, string)
|
||||
|
||||
#define drm_debug(b, format, ...) \
|
||||
DO_DRM_DEBUG ## __VA_OPT__(_COMPLEX) \
|
||||
((b)->debug, format __VA_OPT__(,) __VA_ARGS__)
|
||||
#define drm_debug(b, ...) \
|
||||
weston_log_scope_printf((b)->debug, __VA_ARGS__)
|
||||
|
||||
#define MAX_CLONED_CONNECTORS 4
|
||||
|
||||
|
|
@ -162,6 +149,28 @@ 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_TOO_BIG = 1 << 9,
|
||||
FAILURE_REASONS_BUFFER_TYPE = 1 << 10,
|
||||
FAILURE_REASONS_GLOBAL_ALPHA = 1 << 11,
|
||||
FAILURE_REASONS_NO_GBM = 1 << 12,
|
||||
FAILURE_REASONS_GBM_BO_IMPORT_FAILED = 1 << 13,
|
||||
FAILURE_REASONS_GBM_BO_GET_HANDLE_FAILED = 1 << 14,
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
|
|
@ -172,35 +181,15 @@ enum actions_needed_dmabuf_feedback {
|
|||
ACTION_NEEDED_REMOVE_SCANOUT_TRANCHE = (1 << 1),
|
||||
};
|
||||
|
||||
enum drm_plane_subtype {
|
||||
PLANE_SUBTYPE_OVERLAY_ONLY = 0,
|
||||
PLANE_SUBTYPE_UNDERLAY_ONLY = 1,
|
||||
PLANE_SUBTYPE_BOTH = 2,
|
||||
};
|
||||
|
||||
enum drm_recovery_status {
|
||||
DRM_RECOVERY_UNNECESSARY = 0,
|
||||
DRM_RECOVERY_WAIT_FOR_IDLE = 1,
|
||||
DRM_RECOVERY_SCHEDULED = 2,
|
||||
DRM_RECOVERY_APPLIED = 3,
|
||||
};
|
||||
|
||||
struct drm_kms_device {
|
||||
int id;
|
||||
char *filename;
|
||||
dev_t devnum;
|
||||
struct udev_device *udev_device;
|
||||
|
||||
int fd;
|
||||
struct weston_launcher *fd_owner;
|
||||
};
|
||||
|
||||
struct drm_device {
|
||||
struct drm_backend *backend;
|
||||
|
||||
/* owned */
|
||||
struct drm_kms_device *kms_device;
|
||||
struct wl_event_source *drm_event_source;
|
||||
struct {
|
||||
int id;
|
||||
int fd;
|
||||
char *filename;
|
||||
dev_t devnum;
|
||||
} drm;
|
||||
|
||||
/* Track the GEM handles if the device does not have a gbm device, which
|
||||
* tracks the handles for us.
|
||||
|
|
@ -217,9 +206,7 @@ struct drm_device {
|
|||
|
||||
bool will_repaint;
|
||||
|
||||
enum drm_recovery_status recovery_status;
|
||||
|
||||
int32_t atomic_completes_pending;
|
||||
bool state_invalid;
|
||||
|
||||
bool atomic_modeset;
|
||||
|
||||
|
|
@ -231,7 +218,7 @@ struct drm_device {
|
|||
int32_t cursor_height;
|
||||
|
||||
bool cursors_are_broken;
|
||||
bool disable_client_buffer_scanout;
|
||||
bool sprites_are_broken;
|
||||
|
||||
void *repaint_data;
|
||||
|
||||
|
|
@ -246,11 +233,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;
|
||||
|
||||
int reused_state_failures;
|
||||
};
|
||||
|
||||
struct drm_backend {
|
||||
|
|
@ -258,6 +240,7 @@ struct drm_backend {
|
|||
struct weston_compositor *compositor;
|
||||
|
||||
struct udev *udev;
|
||||
struct wl_event_source *drm_source;
|
||||
|
||||
struct udev_monitor *udev_monitor;
|
||||
struct wl_event_source *udev_drm_source;
|
||||
|
|
@ -271,22 +254,14 @@ struct drm_backend {
|
|||
|
||||
bool use_pixman_shadow;
|
||||
|
||||
bool offload_blend_to_output;
|
||||
|
||||
struct udev_input input;
|
||||
|
||||
uint32_t pageflip_timeout;
|
||||
|
||||
/* True, if underlay planes exist. */
|
||||
bool has_underlay;
|
||||
|
||||
struct weston_log_scope *debug;
|
||||
|
||||
struct {
|
||||
uint32_t frame_counter_interval;
|
||||
struct wl_event_source *pageflip_timer_counter;
|
||||
bool timer_armed;
|
||||
} perf_page_flips_stats;
|
||||
|
||||
/* True if we need a workaround for some very old kernels */
|
||||
bool stale_timestamp_workaround;
|
||||
};
|
||||
|
||||
struct drm_mode {
|
||||
|
|
@ -299,7 +274,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 */
|
||||
|
|
@ -314,9 +288,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;
|
||||
|
|
@ -329,12 +303,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;
|
||||
};
|
||||
|
|
@ -362,15 +330,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
|
||||
|
|
@ -384,13 +343,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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -402,7 +359,7 @@ struct drm_output_state {
|
|||
*/
|
||||
struct drm_plane_state {
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane_handle *handle;
|
||||
struct drm_output *output;
|
||||
struct drm_output_state *output_state;
|
||||
|
||||
struct drm_fb *fb;
|
||||
|
|
@ -411,7 +368,7 @@ struct drm_plane_state {
|
|||
struct weston_buffer_release_reference release;
|
||||
} fb_ref;
|
||||
|
||||
struct weston_paint_node *paint_node; /**< maintained for drm_assign_planes only */
|
||||
struct weston_view *ev; /**< maintained for drm_assign_planes only */
|
||||
|
||||
int32_t src_x, src_y;
|
||||
uint32_t src_w, src_h;
|
||||
|
|
@ -423,9 +380,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 */
|
||||
|
|
@ -464,6 +418,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;
|
||||
|
|
@ -479,16 +435,6 @@ struct drm_plane {
|
|||
struct weston_drm_format_array formats;
|
||||
};
|
||||
|
||||
struct drm_plane_handle {
|
||||
struct drm_output *output;
|
||||
struct drm_plane *plane;
|
||||
|
||||
/* Whether this plane supports overlay, underlay, or both */
|
||||
enum drm_plane_subtype subtype;
|
||||
|
||||
struct wl_list link; /* drm_output::plane_handle_list */
|
||||
};
|
||||
|
||||
struct drm_connector {
|
||||
struct drm_device *device;
|
||||
|
||||
|
|
@ -548,19 +494,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;
|
||||
|
|
@ -591,15 +524,6 @@ struct drm_crtc {
|
|||
|
||||
/* Holds the properties for the CRTC */
|
||||
struct drm_property_info props_crtc[WDRM_CRTC__COUNT];
|
||||
|
||||
/* CRTC prop WDRM_CRTC_GAMMA_LUT_SIZE */
|
||||
uint32_t lut_size;
|
||||
|
||||
/* CRTC prop WDRM_CRTC_BACKGROUND_COLOR */
|
||||
uint64_t background_color;
|
||||
|
||||
/* Union of formats of all compatible writeback connectors */
|
||||
struct weston_drm_format_array writeback_formats;
|
||||
};
|
||||
|
||||
struct drm_output {
|
||||
|
|
@ -618,20 +542,14 @@ struct drm_output {
|
|||
bool dpms_off_pending;
|
||||
bool mode_switch_pending;
|
||||
|
||||
/* List of hardware planes this output can use, excluding the special
|
||||
* cursor and scanout planes. */
|
||||
struct wl_list plane_handle_list;
|
||||
|
||||
/* True, if underlay planes exist. */
|
||||
bool has_underlay;
|
||||
|
||||
uint32_t gbm_cursor_handle[2];
|
||||
struct drm_fb *gbm_cursor_fb[2];
|
||||
struct drm_plane_handle *cursor_handle;
|
||||
struct drm_plane *cursor_plane;
|
||||
struct weston_view *cursor_view;
|
||||
struct wl_listener cursor_view_destroy_listener;
|
||||
int current_cursor;
|
||||
|
||||
struct gbm_surface *gbm_surface;
|
||||
struct linux_dmabuf_memory *linux_dmabuf_memory[2];
|
||||
const struct pixel_format_info *format;
|
||||
uint32_t gbm_bo_flags;
|
||||
|
||||
|
|
@ -641,12 +559,11 @@ struct drm_output {
|
|||
unsigned max_bpc;
|
||||
enum wdrm_colorspace connector_colorspace;
|
||||
|
||||
bool deprecated_gamma_is_set;
|
||||
bool legacy_gamma_not_supported;
|
||||
uint16_t legacy_gamma_size;
|
||||
struct drm_colorop_3x1d_lut *blend_to_output_xform;
|
||||
|
||||
/* Plane being displayed directly on the CRTC */
|
||||
struct drm_plane_handle *scanout_handle;
|
||||
struct drm_plane *scanout_plane;
|
||||
|
||||
/* The last state submitted to the kernel for this CRTC. */
|
||||
struct drm_output_state *state_cur;
|
||||
|
|
@ -658,26 +575,20 @@ struct drm_output {
|
|||
struct drm_writeback_state *wb_state;
|
||||
|
||||
struct drm_fb *dumb[2];
|
||||
weston_renderbuffer_t renderbuffer[2];
|
||||
struct weston_renderbuffer *renderbuffer[2];
|
||||
int current_image;
|
||||
|
||||
struct vaapi_recorder *recorder;
|
||||
struct wl_listener recorder_frame_listener;
|
||||
|
||||
struct wl_event_source *pageflip_timer;
|
||||
|
||||
/* how many page flips */
|
||||
uint32_t page_flips_counted;
|
||||
|
||||
/* how many page flips / interval */
|
||||
float page_flips_per_timer_interval;
|
||||
|
||||
bool is_virtual;
|
||||
void (*virtual_destroy)(struct weston_output *base);
|
||||
|
||||
submit_frame_cb virtual_submit_frame;
|
||||
|
||||
enum wdrm_content_type content_type;
|
||||
|
||||
bool reused_state;
|
||||
bool force_rebuild_state;
|
||||
};
|
||||
|
||||
void
|
||||
|
|
@ -691,20 +602,11 @@ to_drm_head(struct weston_head *base)
|
|||
return container_of(base, struct drm_head, base);
|
||||
}
|
||||
|
||||
void
|
||||
drm_device_recovery_schedule(struct drm_device *device);
|
||||
|
||||
void
|
||||
drm_device_recovery_required(struct drm_device *device);
|
||||
|
||||
void
|
||||
drm_device_recovery_complete(struct drm_device *device);
|
||||
|
||||
void
|
||||
drm_writeback_reference_planes(struct drm_writeback_state *state,
|
||||
struct wl_list *plane_state_list);
|
||||
bool
|
||||
drm_writeback_try_complete(struct drm_writeback_state *state);
|
||||
drm_writeback_should_wait_completion(struct drm_writeback_state *state);
|
||||
void
|
||||
drm_writeback_fail_screenshot(struct drm_writeback_state *state,
|
||||
const char *err_msg);
|
||||
|
|
@ -748,55 +650,24 @@ to_drm_mode(struct weston_mode *base)
|
|||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_plane_type_name_internal(struct drm_plane *p, struct drm_plane_handle *h)
|
||||
drm_output_get_plane_type_name(struct drm_plane *p)
|
||||
{
|
||||
assert(!p || !h);
|
||||
|
||||
if (h)
|
||||
p = h->plane;
|
||||
|
||||
switch (p->type) {
|
||||
case WDRM_PLANE_TYPE_PRIMARY:
|
||||
return "primary";
|
||||
case WDRM_PLANE_TYPE_CURSOR:
|
||||
return "cursor";
|
||||
case WDRM_PLANE_TYPE_OVERLAY:
|
||||
if (!h)
|
||||
return "overlay(no subtype)";
|
||||
|
||||
switch (h->subtype) {
|
||||
case PLANE_SUBTYPE_OVERLAY_ONLY:
|
||||
return "overlay";
|
||||
case PLANE_SUBTYPE_UNDERLAY_ONLY:
|
||||
return "underlay";
|
||||
case PLANE_SUBTYPE_BOTH:
|
||||
return "over/underlay";
|
||||
}
|
||||
// fall through
|
||||
return p->is_underlay ? "underlay" : "overlay";
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_plane_type_name(struct drm_plane *p)
|
||||
{
|
||||
return drm_output_get_plane_type_name_internal(p, NULL);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
drm_output_get_handle_type_name(struct drm_plane_handle *h)
|
||||
{
|
||||
return drm_output_get_plane_type_name_internal(NULL, h);
|
||||
}
|
||||
|
||||
struct drm_crtc *
|
||||
drm_crtc_find(struct drm_device *device, uint32_t crtc_id);
|
||||
|
||||
bool
|
||||
drm_crtc_supports_background_color(struct drm_crtc *crtc);
|
||||
|
||||
struct drm_head *
|
||||
drm_head_find_by_connector(struct drm_backend *backend, struct drm_device *device, uint32_t connector_id);
|
||||
|
||||
|
|
@ -879,6 +750,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
|
||||
|
|
@ -895,15 +770,13 @@ drm_fb_unref(struct drm_fb *fb);
|
|||
struct drm_fb *
|
||||
drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
||||
uint32_t format);
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
uint32_t *try_view_on_plane_failure_reasons);
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
||||
bool is_opaque, enum drm_fb_type type);
|
||||
|
||||
void
|
||||
drm_output_set_cursor_view(struct drm_output *output, struct weston_view *ev);
|
||||
|
||||
int
|
||||
drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output);
|
||||
|
||||
|
|
@ -913,23 +786,15 @@ wdrm_colorspace_from_output(struct weston_output *output);
|
|||
#ifdef BUILD_DRM_GBM
|
||||
extern struct drm_fb *
|
||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
uint32_t *try_view_on_plane_failure_reasons);
|
||||
struct weston_paint_node *pnode);
|
||||
|
||||
extern bool
|
||||
drm_can_scanout_dmabuf(struct weston_backend *backend,
|
||||
struct linux_dmabuf_buffer *dmabuf);
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
bool direct_display, bool is_internal,
|
||||
uint32_t *try_view_on_plane_failure_reasons);
|
||||
#else
|
||||
static inline struct drm_fb *
|
||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
struct weston_paint_node *pnode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -986,7 +851,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);
|
||||
|
|
@ -999,14 +864,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);
|
||||
|
||||
|
|
@ -1014,12 +871,6 @@ int
|
|||
parse_gbm_format(const char *s, const struct pixel_format_info *default_format,
|
||||
const struct pixel_format_info **format);
|
||||
|
||||
struct drm_plane_handle *
|
||||
drm_plane_create_handle(struct drm_plane *plane, struct drm_output *output);
|
||||
|
||||
void
|
||||
drm_plane_destroy_handle(struct drm_plane_handle *plane);
|
||||
|
||||
#ifdef BUILD_DRM_VIRTUAL
|
||||
extern int
|
||||
drm_backend_init_virtual_output_api(struct weston_compositor *compositor);
|
||||
|
|
@ -1044,18 +895,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)
|
||||
|
|
@ -1080,29 +919,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
|
||||
};
|
||||
|
||||
|
|
@ -197,6 +173,5 @@ enum wdrm_crtc_property {
|
|||
WDRM_CRTC_GAMMA_LUT,
|
||||
WDRM_CRTC_GAMMA_LUT_SIZE,
|
||||
WDRM_CRTC_VRR_ENABLED,
|
||||
WDRM_CRTC_BACKGROUND_COLOR,
|
||||
WDRM_CRTC__COUNT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@
|
|||
#include "drm-internal.h"
|
||||
#include "pixel-formats.h"
|
||||
#include "renderer-gl/gl-renderer.h"
|
||||
#include "shared/weston-assert.h"
|
||||
|
||||
#define POISON_PTR ((void *)8)
|
||||
|
||||
|
|
@ -105,7 +104,7 @@ get_drm_plane_index_maximum(struct drm_device *device)
|
|||
* @param device DRM device
|
||||
* @param output Output to create internal plane for
|
||||
*/
|
||||
static struct drm_plane_handle *
|
||||
static struct drm_plane *
|
||||
drm_virtual_plane_create(struct drm_device *device, struct drm_output *output)
|
||||
{
|
||||
struct drm_backend *b = device->backend;
|
||||
|
|
@ -146,7 +145,7 @@ drm_virtual_plane_create(struct drm_device *device, struct drm_output *output)
|
|||
plane->plane_idx = get_drm_plane_index_maximum(device) + 1;
|
||||
wl_list_insert(&device->plane_list, &plane->link);
|
||||
|
||||
return drm_plane_create_handle(plane, output);
|
||||
return plane;
|
||||
|
||||
err:
|
||||
drm_plane_state_free(plane->state_cur, true);
|
||||
|
|
@ -158,15 +157,11 @@ err:
|
|||
/**
|
||||
* Destroy one DRM plane
|
||||
*
|
||||
* @param handle Plane handle to deallocate (will be freed along with the plane)
|
||||
* @param plane Plane to deallocate (will be freed)
|
||||
*/
|
||||
static void
|
||||
drm_virtual_plane_destroy(struct drm_plane_handle *handle)
|
||||
drm_virtual_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
struct drm_plane *plane = handle->plane;
|
||||
|
||||
drm_plane_destroy_handle(handle);
|
||||
|
||||
drm_plane_state_free(plane->state_cur, true);
|
||||
weston_plane_release(&plane->base);
|
||||
wl_list_remove(&plane->link);
|
||||
|
|
@ -210,9 +205,8 @@ static int
|
|||
drm_virtual_output_repaint(struct weston_output *output_base)
|
||||
{
|
||||
struct drm_output_state *state = NULL;
|
||||
struct weston_compositor *compositor = output_base->compositor;
|
||||
struct drm_output *output = to_drm_output(output_base);
|
||||
struct drm_plane *scanout_plane = output->scanout_handle->plane;
|
||||
struct drm_plane *scanout_plane = output->scanout_plane;
|
||||
struct drm_plane_state *scanout_state;
|
||||
struct drm_pending_state *pending_state;
|
||||
struct drm_device *device;
|
||||
|
|
@ -233,10 +227,14 @@ drm_virtual_output_repaint(struct weston_output *output_base)
|
|||
|
||||
assert(!output->state_last);
|
||||
|
||||
/* assign_planes() is always called before a repaint, so we must have a
|
||||
* valid output state here. */
|
||||
/* If planes have been disabled in the core, we might not have
|
||||
* hit assign_planes at all, so might not have valid output state
|
||||
* here. */
|
||||
state = drm_pending_state_get_output(pending_state, output);
|
||||
weston_assert_ptr_not_null(compositor, state);
|
||||
if (!state)
|
||||
state = drm_output_state_duplicate(output->state_cur,
|
||||
pending_state,
|
||||
DRM_OUTPUT_STATE_CLEAR_PLANES);
|
||||
|
||||
drm_output_render(state);
|
||||
scanout_state = drm_output_state_get_plane(state, scanout_plane);
|
||||
|
|
@ -260,7 +258,7 @@ drm_virtual_output_deinit(struct weston_output *base)
|
|||
|
||||
drm_output_fini_egl(output);
|
||||
|
||||
drm_virtual_plane_destroy(output->scanout_handle);
|
||||
drm_virtual_plane_destroy(output->scanout_plane);
|
||||
drm_virtual_crtc_destroy(output->crtc);
|
||||
}
|
||||
|
||||
|
|
@ -303,8 +301,8 @@ drm_virtual_output_enable(struct weston_output *output_base)
|
|||
goto err;
|
||||
}
|
||||
|
||||
output->scanout_handle = drm_virtual_plane_create(device, output);
|
||||
if (!output->scanout_handle) {
|
||||
output->scanout_plane = drm_virtual_plane_create(device, output);
|
||||
if (!output->scanout_plane) {
|
||||
weston_log("Failed to find primary plane for output %s\n",
|
||||
output->base.name);
|
||||
return -1;
|
||||
|
|
@ -320,6 +318,12 @@ drm_virtual_output_enable(struct weston_output *output_base)
|
|||
output->base.assign_planes = drm_assign_planes;
|
||||
output->base.set_dpms = NULL;
|
||||
output->base.switch_mode = NULL;
|
||||
output->base.gamma_size = 0;
|
||||
output->base.set_gamma = NULL;
|
||||
|
||||
weston_compositor_stack_plane(b->compositor,
|
||||
&output->scanout_plane->base,
|
||||
&output->base.primary_plane);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
|
@ -440,6 +444,11 @@ drm_virtual_output_finish_frame(struct weston_output *output_base,
|
|||
output->state_last = NULL;
|
||||
|
||||
weston_output_finish_frame(&output->base, stamp, presented_flags);
|
||||
|
||||
/* We can't call this from frame_notify, because the output's
|
||||
* repaint needed flag is cleared just after that */
|
||||
if (output->recorder)
|
||||
weston_output_schedule_repaint(&output->base);
|
||||
}
|
||||
|
||||
static const struct weston_drm_virtual_output_api virt_api = {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -41,7 +41,6 @@
|
|||
#include "shared/hash.h"
|
||||
#include "shared/helpers.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/weston-assert.h"
|
||||
#include "drm-internal.h"
|
||||
#include "linux-dmabuf.h"
|
||||
|
||||
|
|
@ -100,7 +99,7 @@ static void gem_handle_put(struct drm_device *device, int handle)
|
|||
ref_count = hash_table_lookup(device->gem_handle_refcnt, handle);
|
||||
if (!ref_count) {
|
||||
weston_log("failed to find GEM handle %d for device %s\n",
|
||||
handle, device->kms_device->filename);
|
||||
handle, device->drm.filename);
|
||||
return;
|
||||
}
|
||||
(*ref_count)--;
|
||||
|
|
@ -108,28 +107,20 @@ static void gem_handle_put(struct drm_device *device, int handle)
|
|||
if (*ref_count == 0) {
|
||||
hash_table_remove(device->gem_handle_refcnt, handle);
|
||||
free(ref_count);
|
||||
drmCloseBufferHandle(device->kms_device->fd, handle);
|
||||
drmCloseBufferHandle(device->drm.fd, handle);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
||||
{
|
||||
int bo_fd = -1;
|
||||
int bo_fd;
|
||||
uint32_t handle;
|
||||
int ret;
|
||||
|
||||
/* neither a BO nor a direct-display means we shouldn't be calling this */
|
||||
assert(!!fb->bo ^ fb->direct_display);
|
||||
|
||||
if (fb->bo) {
|
||||
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
|
||||
if (bo_fd < 0)
|
||||
return bo_fd;
|
||||
}
|
||||
|
||||
if (fb->direct_display)
|
||||
bo_fd = fb->fds[plane];
|
||||
bo_fd = gbm_bo_get_fd_for_plane(fb->bo, plane);
|
||||
if (bo_fd < 0)
|
||||
return bo_fd;
|
||||
|
||||
/*
|
||||
* drmPrimeFDToHandle is dangerous, because the GEM handles are
|
||||
|
|
@ -156,10 +147,7 @@ drm_fb_import_plane(struct drm_device *device, struct drm_fb *fb, int plane)
|
|||
fb->handles[plane] = gem_handle_get(device, handle);
|
||||
|
||||
out:
|
||||
/* on the direct-display path the dup'ed fds will be closed by
|
||||
* drm_fb_destroy_dmabuf */
|
||||
if (fb->bo)
|
||||
close(bo_fd);
|
||||
close(bo_fd);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -183,35 +171,23 @@ drm_fb_maybe_import(struct drm_device *device, struct drm_fb *fb)
|
|||
struct gbm_device *gbm_device;
|
||||
int ret = 0;
|
||||
int plane;
|
||||
int num_planes;
|
||||
|
||||
/* No import possible, if there is no gbm bo or fb is not using
|
||||
* direct-display */
|
||||
if (!fb->bo && !fb->direct_display)
|
||||
/* No import possible, if there is no gbm bo */
|
||||
if (!fb->bo)
|
||||
return 0;
|
||||
|
||||
if (fb->bo) {
|
||||
weston_assert_false(device->backend->compositor, fb->direct_display);
|
||||
/* No import necessary, if the gbm bo and the fb use the same device */
|
||||
gbm_device = gbm_bo_get_device(fb->bo);
|
||||
if (gbm_device_get_fd(gbm_device) == fb->fd)
|
||||
return 0;
|
||||
|
||||
/* No import necessary, if the gbm bo and the fb use the same device */
|
||||
gbm_device = gbm_bo_get_device(fb->bo);
|
||||
if (gbm_device_get_fd(gbm_device) == fb->fd)
|
||||
return 0;
|
||||
|
||||
if (fb->fd != device->kms_device->fd) {
|
||||
weston_log("fb was not allocated for scanout device %s\n",
|
||||
device->kms_device->filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_planes = gbm_bo_get_plane_count(fb->bo);
|
||||
} else {
|
||||
weston_assert_true(device->backend->compositor, fb->direct_display);
|
||||
|
||||
num_planes = fb->num_planes;
|
||||
if (fb->fd != device->drm.fd) {
|
||||
weston_log("fb was not allocated for scanout device %s\n",
|
||||
device->drm.filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (plane = 0; plane < num_planes; plane++) {
|
||||
for (plane = 0; plane < gbm_bo_get_plane_count(fb->bo); plane++) {
|
||||
ret = drm_fb_import_plane(device, fb, plane);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
|
@ -313,7 +289,7 @@ drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
|||
create_arg.width = width;
|
||||
create_arg.height = height;
|
||||
|
||||
ret = drmIoctl(device->kms_device->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
|
||||
ret = drmIoctl(device->drm.fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_arg);
|
||||
if (ret)
|
||||
goto err_fb;
|
||||
|
||||
|
|
@ -325,7 +301,7 @@ drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
|||
fb->size = create_arg.size;
|
||||
fb->width = width;
|
||||
fb->height = height;
|
||||
fb->fd = device->kms_device->fd;
|
||||
fb->fd = device->drm.fd;
|
||||
|
||||
if (drm_fb_addfb(device, fb) != 0) {
|
||||
weston_log("failed to create kms fb: %s\n", strerror(errno));
|
||||
|
|
@ -339,18 +315,18 @@ drm_fb_create_dumb(struct drm_device *device, int width, int height,
|
|||
goto err_add_fb;
|
||||
|
||||
fb->map = mmap(NULL, fb->size, PROT_WRITE,
|
||||
MAP_SHARED, device->kms_device->fd, map_arg.offset);
|
||||
MAP_SHARED, device->drm.fd, map_arg.offset);
|
||||
if (fb->map == MAP_FAILED)
|
||||
goto err_add_fb;
|
||||
|
||||
return fb;
|
||||
|
||||
err_add_fb:
|
||||
drmModeRmFB(device->kms_device->fd, fb->fb_id);
|
||||
drmModeRmFB(device->drm.fd, fb->fb_id);
|
||||
err_bo:
|
||||
memset(&destroy_arg, 0, sizeof(destroy_arg));
|
||||
destroy_arg.handle = create_arg.handle;
|
||||
drmIoctl(device->kms_device->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
|
||||
drmIoctl(device->drm.fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_arg);
|
||||
err_fb:
|
||||
free(fb);
|
||||
return NULL;
|
||||
|
|
@ -388,35 +364,27 @@ drm_fb_destroy_dmabuf(struct drm_fb *fb)
|
|||
* If we imported the dmabuf into a scanout device, we are responsible
|
||||
* for closing the GEM handle.
|
||||
*/
|
||||
for (i = 0; i < MAX_DMABUF_PLANES; i++) {
|
||||
if (fb->scanout_device && fb->handles[i] != 0) {
|
||||
for (i = 0; i < 4; i++)
|
||||
if (fb->scanout_device && fb->handles[i] != 0)
|
||||
gem_handle_put(fb->scanout_device, fb->handles[i]);
|
||||
fb->handles[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < fb->num_duped_fds; i++)
|
||||
close(fb->fds[i]);
|
||||
|
||||
drm_fb_destroy(fb);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
bool direct_display, bool is_internal,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
static struct drm_fb *
|
||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
{
|
||||
struct drm_backend *backend = device->backend;
|
||||
struct drm_fb *fb;
|
||||
int i;
|
||||
struct gbm_import_fd_modifier_data import_mod = {
|
||||
.width = attributes->width,
|
||||
.height = attributes->height,
|
||||
.format = attributes->format,
|
||||
.num_fds = attributes->n_planes,
|
||||
.modifier = attributes->modifier,
|
||||
.width = dmabuf->attributes.width,
|
||||
.height = dmabuf->attributes.height,
|
||||
.format = dmabuf->attributes.format,
|
||||
.num_fds = dmabuf->attributes.n_planes,
|
||||
.modifier = dmabuf->attributes.modifier,
|
||||
};
|
||||
|
||||
/* We should not import to KMS a buffer that has been allocated using no
|
||||
|
|
@ -426,7 +394,7 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
* KMS driver can't know. So giving the buffer to KMS is not safe, as
|
||||
* not knowing its layout can result in garbage being displayed. In
|
||||
* short, importing a buffer to KMS requires explicit modifiers. */
|
||||
if (attributes->modifier == DRM_FORMAT_MOD_INVALID) {
|
||||
if (dmabuf->attributes.modifier == DRM_FORMAT_MOD_INVALID) {
|
||||
if (try_view_on_plane_failure_reasons)
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
FAILURE_REASONS_DMABUF_MODIFIER_INVALID;
|
||||
|
|
@ -442,7 +410,7 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
* these types of buffers should be handled through buffer
|
||||
* transforms and not as spot-checks requiring specific
|
||||
* knowledge. */
|
||||
if (attributes->flags)
|
||||
if (dmabuf->attributes.flags)
|
||||
return NULL;
|
||||
|
||||
fb = zalloc(sizeof *fb);
|
||||
|
|
@ -450,30 +418,12 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
return NULL;
|
||||
|
||||
fb->refcnt = 1;
|
||||
fb->type = is_internal ? BUFFER_DMABUF_BACKEND : BUFFER_DMABUF;
|
||||
fb->type = BUFFER_DMABUF;
|
||||
fb->backend = device->backend;
|
||||
|
||||
ARRAY_COPY(import_mod.fds, attributes->fd);
|
||||
ARRAY_COPY(import_mod.strides, attributes->stride);
|
||||
ARRAY_COPY(import_mod.offsets, attributes->offset);
|
||||
|
||||
/* skip bo import if dmabuf is using direct-display extension */
|
||||
if (direct_display) {
|
||||
fb->direct_display = true;
|
||||
/* we're making a dup of the fds from attributes->fd as
|
||||
* opposed to just copying the fds with ARRAY_COPY() */
|
||||
for (i = 0; i < attributes->n_planes; i++) {
|
||||
fb->fds[i] = dup(attributes->fd[i]);
|
||||
if (fb->fds[i] == -1) {
|
||||
weston_log("failed to dup dmabuf attribute fd: %s\n",
|
||||
strerror(errno));
|
||||
goto err_free;
|
||||
}
|
||||
fb->num_duped_fds++;
|
||||
}
|
||||
|
||||
goto bo_import_skip;
|
||||
}
|
||||
ARRAY_COPY(import_mod.fds, dmabuf->attributes.fd);
|
||||
ARRAY_COPY(import_mod.strides, dmabuf->attributes.stride);
|
||||
ARRAY_COPY(import_mod.offsets, dmabuf->attributes.offset);
|
||||
|
||||
fb->bo = gbm_bo_import(backend->gbm, GBM_BO_IMPORT_FD_MODIFIER,
|
||||
&import_mod, GBM_BO_USE_SCANOUT);
|
||||
|
|
@ -484,20 +434,19 @@ drm_fb_get_from_dmabuf_attributes(struct dmabuf_attributes *attributes,
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
bo_import_skip:
|
||||
fb->width = attributes->width;
|
||||
fb->height = attributes->height;
|
||||
fb->modifier = attributes->modifier;
|
||||
fb->width = dmabuf->attributes.width;
|
||||
fb->height = dmabuf->attributes.height;
|
||||
fb->modifier = dmabuf->attributes.modifier;
|
||||
fb->size = 0;
|
||||
fb->fd = device->kms_device->fd;
|
||||
fb->fd = device->drm.fd;
|
||||
|
||||
ARRAY_COPY(fb->strides, attributes->stride);
|
||||
ARRAY_COPY(fb->offsets, attributes->offset);
|
||||
ARRAY_COPY(fb->strides, dmabuf->attributes.stride);
|
||||
ARRAY_COPY(fb->offsets, dmabuf->attributes.offset);
|
||||
|
||||
fb->format = pixel_format_get_info(attributes->format);
|
||||
fb->format = pixel_format_get_info(dmabuf->attributes.format);
|
||||
if (!fb->format) {
|
||||
weston_log("couldn't look up format info for 0x%lx\n",
|
||||
(unsigned long) attributes->format);
|
||||
(unsigned long) dmabuf->attributes.format);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
|
|
@ -512,8 +461,8 @@ bo_import_skip:
|
|||
goto err_free;
|
||||
}
|
||||
|
||||
fb->num_planes = attributes->n_planes;
|
||||
for (i = 0; fb->bo && i < attributes->n_planes; i++) {
|
||||
fb->num_planes = dmabuf->attributes.n_planes;
|
||||
for (i = 0; i < dmabuf->attributes.n_planes; i++) {
|
||||
union gbm_bo_handle handle;
|
||||
|
||||
handle = gbm_bo_get_handle_for_plane(fb->bo, i);
|
||||
|
|
@ -539,18 +488,6 @@ err_free:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_dmabuf(struct linux_dmabuf_buffer *dmabuf,
|
||||
struct drm_device *device, bool is_opaque,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
{
|
||||
return drm_fb_get_from_dmabuf_attributes(&dmabuf->attributes,
|
||||
device, is_opaque,
|
||||
dmabuf->direct_display,
|
||||
false,
|
||||
try_view_on_plane_failure_reasons);
|
||||
}
|
||||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
||||
bool is_opaque, enum drm_fb_type type)
|
||||
|
|
@ -571,7 +508,7 @@ drm_fb_get_from_bo(struct gbm_bo *bo, struct drm_device *device,
|
|||
fb->refcnt = 1;
|
||||
fb->backend = device->backend;
|
||||
fb->bo = bo;
|
||||
fb->fd = device->kms_device->fd;
|
||||
fb->fd = device->drm.fd;
|
||||
|
||||
fb->width = gbm_bo_get_width(bo);
|
||||
fb->height = gbm_bo_get_height(bo);
|
||||
|
|
@ -645,7 +582,6 @@ drm_fb_unref(struct drm_fb *fb)
|
|||
gbm_surface_release_buffer(fb->gbm_surface, fb->bo);
|
||||
break;
|
||||
case BUFFER_DMABUF:
|
||||
case BUFFER_DMABUF_BACKEND:
|
||||
drm_fb_destroy_dmabuf(fb);
|
||||
break;
|
||||
#endif
|
||||
|
|
@ -678,7 +614,7 @@ drm_can_scanout_dmabuf(struct weston_backend *backend,
|
|||
|
||||
static bool
|
||||
drm_fb_compatible_with_plane(struct drm_fb *fb, struct drm_plane *plane,
|
||||
struct weston_paint_node *pnode)
|
||||
struct weston_view *view)
|
||||
{
|
||||
struct drm_device *device = plane->device;
|
||||
struct drm_backend *b = device->backend;
|
||||
|
|
@ -702,11 +638,10 @@ drm_fb_compatible_with_plane(struct drm_fb *fb, struct drm_plane *plane,
|
|||
return true;
|
||||
}
|
||||
|
||||
drm_debug(b, "\t\t\t\t[%s] not assigning paint node %s on %s, "
|
||||
drm_debug(b, "\t\t\t\t[%s] not assigning view %p on %s, "
|
||||
"plane %d (format %s (0x%lx) with modifier 0x%llx) not supported\n",
|
||||
drm_output_get_plane_type_name(plane),
|
||||
pnode->internal_name,
|
||||
drm_output_get_plane_type_name(plane),
|
||||
view, drm_output_get_plane_type_name(plane),
|
||||
plane->plane_id, fb->format->drm_format_name,
|
||||
(unsigned long) fb->format->format,
|
||||
(unsigned long long) fb->modifier);
|
||||
|
|
@ -739,29 +674,28 @@ drm_fb_handle_buffer_destroy(struct wl_listener *listener, void *data)
|
|||
|
||||
struct drm_fb *
|
||||
drm_fb_get_from_paint_node(struct drm_output_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
uint32_t *try_view_on_plane_failure_reasons)
|
||||
struct weston_paint_node *pnode)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct drm_backend *b = output->backend;
|
||||
struct drm_device *device = output->device;
|
||||
struct weston_surface *surface = pnode->surface;
|
||||
struct weston_buffer *buffer = surface->buffer_ref.buffer;
|
||||
struct weston_view *ev = pnode->view;
|
||||
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
||||
struct drm_fb_private *private;
|
||||
struct drm_buffer_fb *buf_fb;
|
||||
bool is_opaque = pnode->is_fully_opaque;
|
||||
bool is_opaque = weston_view_is_opaque(ev, &ev->transform.boundingbox);
|
||||
struct drm_fb *fb;
|
||||
struct drm_plane *plane;
|
||||
|
||||
if (surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
||||
surface->desired_protection > output->base.current_protection) {
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
if (ev->surface->protection_mode == WESTON_SURFACE_PROTECTION_MODE_ENFORCED &&
|
||||
ev->surface->desired_protection > output->base.current_protection) {
|
||||
pnode->try_view_on_plane_failure_reasons |=
|
||||
FAILURE_REASONS_INADEQUATE_CONTENT_PROTECTION;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!buffer) {
|
||||
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
|
||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_BUFFER;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -777,7 +711,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
wl_list_for_each(buf_fb, &private->buffer_fb_list, link) {
|
||||
if (buf_fb->device == device) {
|
||||
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
return buf_fb->fb ? drm_fb_ref(buf_fb->fb) : NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -788,7 +722,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
/* GBM is used for dmabuf import as well as from client wl_buffer. */
|
||||
if (!b->gbm) {
|
||||
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
|
||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_NO_GBM;
|
||||
goto unsuitable;
|
||||
}
|
||||
|
||||
|
|
@ -807,13 +741,13 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
|
||||
fb = drm_fb_get_from_bo(bo, device, is_opaque, BUFFER_CLIENT);
|
||||
if (!fb) {
|
||||
*try_view_on_plane_failure_reasons |=
|
||||
pnode->try_view_on_plane_failure_reasons |=
|
||||
FAILURE_REASONS_ADD_FB_FAILED;
|
||||
gbm_bo_destroy(bo);
|
||||
goto unsuitable;
|
||||
}
|
||||
} else {
|
||||
*try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
|
||||
pnode->try_view_on_plane_failure_reasons |= FAILURE_REASONS_BUFFER_TYPE;
|
||||
goto unsuitable;
|
||||
}
|
||||
|
||||
|
|
@ -824,7 +758,7 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
if (plane->type == WDRM_PLANE_TYPE_CURSOR)
|
||||
continue;
|
||||
|
||||
if (drm_fb_compatible_with_plane(fb, plane, pnode))
|
||||
if (drm_fb_compatible_with_plane(fb, plane, pnode->view))
|
||||
fb->plane_mask |= 1 << (plane->plane_idx);
|
||||
}
|
||||
if (fb->plane_mask == 0) {
|
||||
|
|
@ -837,12 +771,12 @@ drm_fb_get_from_paint_node(struct drm_output_state *state,
|
|||
* drm_fb we take an additional ref for the weston_buffer's cache. */
|
||||
buf_fb->fb = drm_fb_ref(fb);
|
||||
|
||||
drm_debug(b, "\t\t\t[paint node] paint node %s format: %s\n",
|
||||
pnode->internal_name, fb->format->drm_format_name);
|
||||
drm_debug(b, "\t\t\t[view] view %p format: %s\n",
|
||||
ev, fb->format->drm_format_name);
|
||||
return fb;
|
||||
|
||||
unsuitable:
|
||||
*try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
pnode->try_view_on_plane_failure_reasons |= buf_fb->failure_reasons;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ret = drmModeCreatePropertyBlob(device->kms_device->fd,
|
||||
ret = drmModeCreatePropertyBlob(device->drm.fd,
|
||||
&meta, sizeof meta, &blob_id);
|
||||
if (ret != 0) {
|
||||
weston_log("Error: failed to create KMS blob for HDR metadata on output '%s': %s\n",
|
||||
|
|
@ -168,7 +168,7 @@ drm_output_ensure_hdr_output_metadata_blob(struct drm_output *output)
|
|||
return -1;
|
||||
}
|
||||
|
||||
drmModeDestroyPropertyBlob(device->kms_device->fd,
|
||||
drmModeDestroyPropertyBlob(device->drm.fd,
|
||||
output->hdr_output_metadata_blob_id);
|
||||
|
||||
output->hdr_output_metadata_blob_id = blob_id;
|
||||
|
|
|
|||
|
|
@ -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[] = {
|
||||
|
|
@ -263,7 +229,6 @@ const struct drm_property_info crtc_props[] = {
|
|||
[WDRM_CRTC_GAMMA_LUT] = { .name = "GAMMA_LUT", },
|
||||
[WDRM_CRTC_GAMMA_LUT_SIZE] = { .name = "GAMMA_LUT_SIZE", },
|
||||
[WDRM_CRTC_VRR_ENABLED] = { .name = "VRR_ENABLED", },
|
||||
[WDRM_CRTC_BACKGROUND_COLOR] = { .name = "BACKGROUND_COLOR", },
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -430,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
|
||||
*
|
||||
|
|
@ -505,7 +459,7 @@ drm_property_info_populate(struct drm_device *device,
|
|||
for (i = 0; i < props->count_props; i++) {
|
||||
unsigned int k;
|
||||
|
||||
prop = drmModeGetProperty(device->kms_device->fd, props->props[i]);
|
||||
prop = drmModeGetProperty(device->drm.fd, props->props[i]);
|
||||
if (!prop)
|
||||
continue;
|
||||
|
||||
|
|
@ -632,7 +586,7 @@ drm_plane_populate_formats(struct drm_plane *plane, const drmModePlane *kplane,
|
|||
if (blob_id == 0)
|
||||
goto fallback;
|
||||
|
||||
blob = drmModeGetPropertyBlob(device->kms_device->fd, blob_id);
|
||||
blob = drmModeGetPropertyBlob(device->drm.fd, blob_id);
|
||||
if (!blob)
|
||||
goto fallback;
|
||||
|
||||
|
|
@ -672,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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -737,7 +681,6 @@ drm_output_assign_state(struct drm_output_state *state,
|
|||
drm_debug(b, "\t[CRTC:%u] setting pending flip\n",
|
||||
output->crtc->crtc_id);
|
||||
output->atomic_complete_pending = true;
|
||||
device->atomic_completes_pending++;
|
||||
}
|
||||
|
||||
if (device->atomic_modeset &&
|
||||
|
|
@ -777,32 +720,28 @@ drm_output_set_cursor(struct drm_output_state *output_state)
|
|||
struct drm_output *output = output_state->output;
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_crtc *crtc = output->crtc;
|
||||
struct drm_plane_handle *plane_handle = output->cursor_handle;
|
||||
struct drm_plane *plane;
|
||||
struct drm_plane *plane = output->cursor_plane;
|
||||
struct drm_plane_state *state;
|
||||
uint32_t handle;
|
||||
|
||||
if (!plane_handle)
|
||||
if (!plane)
|
||||
return;
|
||||
|
||||
plane = plane_handle->plane;
|
||||
|
||||
state = drm_output_state_get_existing_plane(output_state, plane);
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
if (!state->fb) {
|
||||
drmModeSetCursor(device->kms_device->fd, crtc->crtc_id, 0, 0, 0);
|
||||
drmModeSetCursor(device->drm.fd, crtc->crtc_id, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(state->fb == output->gbm_cursor_fb[output->current_cursor]);
|
||||
assert(!plane->state_cur->handle ||
|
||||
plane->state_cur->handle->output == output);
|
||||
assert(!plane->state_cur->output || plane->state_cur->output == output);
|
||||
|
||||
handle = output->gbm_cursor_handle[output->current_cursor];
|
||||
if (plane->state_cur->fb != state->fb) {
|
||||
if (drmModeSetCursor(device->kms_device->fd, crtc->crtc_id, handle,
|
||||
if (drmModeSetCursor(device->drm.fd, crtc->crtc_id, handle,
|
||||
device->cursor_width, device->cursor_height)) {
|
||||
weston_log("failed to set cursor: %s\n",
|
||||
strerror(errno));
|
||||
|
|
@ -810,7 +749,7 @@ drm_output_set_cursor(struct drm_output_state *output_state)
|
|||
}
|
||||
}
|
||||
|
||||
if (drmModeMoveCursor(device->kms_device->fd, crtc->crtc_id,
|
||||
if (drmModeMoveCursor(device->drm.fd, crtc->crtc_id,
|
||||
state->dest_x, state->dest_y)) {
|
||||
weston_log("failed to move cursor: %s\n", strerror(errno));
|
||||
goto err;
|
||||
|
|
@ -820,13 +759,13 @@ drm_output_set_cursor(struct drm_output_state *output_state)
|
|||
|
||||
err:
|
||||
device->cursors_are_broken = true;
|
||||
drmModeSetCursor(device->kms_device->fd, crtc->crtc_id, 0, 0, 0);
|
||||
drmModeSetCursor(device->drm.fd, crtc->crtc_id, 0, 0, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -845,7 +784,7 @@ drm_output_reset_legacy_gamma(struct drm_output *output)
|
|||
for (i = 0; i < len; i++)
|
||||
lut[i] = 0xffff * i / (len - 1);
|
||||
|
||||
ret = drmModeCrtcSetGamma(output->device->kms_device->fd,
|
||||
ret = drmModeCrtcSetGamma(output->device->drm.fd,
|
||||
output->crtc->crtc_id,
|
||||
len, lut, lut, lut);
|
||||
if (ret == -EOPNOTSUPP || ret == -ENOSYS)
|
||||
|
|
@ -864,7 +803,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
struct drm_output *output = state->output;
|
||||
struct drm_device *device = output->device;
|
||||
struct drm_backend *backend = device->backend;
|
||||
struct drm_plane *scanout_plane = output->scanout_handle->plane;
|
||||
struct drm_plane *scanout_plane = output->scanout_plane;
|
||||
struct drm_crtc *crtc = output->crtc;
|
||||
struct drm_property_info *dpms_prop;
|
||||
struct drm_plane_state *scanout_state;
|
||||
|
|
@ -881,16 +820,28 @@ 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_handle) {
|
||||
ret = drmModeSetCursor(device->kms_device->fd, crtc->crtc_id,
|
||||
if (output->cursor_plane) {
|
||||
ret = drmModeSetCursor(device->drm.fd, crtc->crtc_id,
|
||||
0, 0, 0);
|
||||
if (ret)
|
||||
weston_log("drmModeSetCursor failed disable: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
ret = drmModeSetCrtc(device->kms_device->fd, crtc->crtc_id, 0, 0, 0,
|
||||
ret = drmModeSetCrtc(device->drm.fd, crtc->crtc_id, 0, 0, 0,
|
||||
NULL, 0, NULL);
|
||||
if (ret)
|
||||
weston_log("drmModeSetCrtc failed disabling: %s\n",
|
||||
|
|
@ -924,12 +875,12 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
assert(scanout_state->in_fence_fd == -1);
|
||||
|
||||
mode = to_drm_mode(output->base.current_mode);
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED ||
|
||||
if (device->state_invalid ||
|
||||
!scanout_plane->state_cur->fb ||
|
||||
scanout_plane->state_cur->fb->strides[0] !=
|
||||
scanout_state->fb->strides[0]) {
|
||||
|
||||
ret = drmModeSetCrtc(device->kms_device->fd, crtc->crtc_id,
|
||||
ret = drmModeSetCrtc(device->drm.fd, crtc->crtc_id,
|
||||
scanout_state->fb->fb_id,
|
||||
0, 0,
|
||||
connectors, n_conn,
|
||||
|
|
@ -939,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;
|
||||
|
|
@ -947,7 +899,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
crtc->crtc_id, scanout_state->plane->plane_id,
|
||||
pinfo ? pinfo->drm_format_name : "UNKNOWN");
|
||||
|
||||
if (drmModePageFlip(device->kms_device->fd, crtc->crtc_id,
|
||||
if (drmModePageFlip(device->drm.fd, crtc->crtc_id,
|
||||
scanout_state->fb->fb_id,
|
||||
DRM_MODE_PAGE_FLIP_EVENT, output) < 0) {
|
||||
weston_log("queueing pageflip failed: %s\n", strerror(errno));
|
||||
|
|
@ -968,7 +920,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
if (dpms_prop->prop_id == 0)
|
||||
continue;
|
||||
|
||||
ret = drmModeConnectorSetProperty(device->kms_device->fd,
|
||||
ret = drmModeConnectorSetProperty(device->drm.fd,
|
||||
head->connector.connector_id,
|
||||
dpms_prop->prop_id,
|
||||
state->dpms);
|
||||
|
|
@ -984,6 +936,7 @@ drm_output_apply_state_legacy(struct drm_output_state *state)
|
|||
return 0;
|
||||
|
||||
err:
|
||||
drm_output_set_cursor_view(output, NULL);
|
||||
drm_output_state_free(state);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1040,15 +993,6 @@ crtc_add_prop_zero_ok(drmModeAtomicReq *req, struct drm_crtc *crtc,
|
|||
return crtc_add_prop(req, crtc, prop, val);
|
||||
}
|
||||
|
||||
bool
|
||||
drm_crtc_supports_background_color(struct drm_crtc *crtc)
|
||||
{
|
||||
if (crtc->props_crtc[WDRM_CRTC_BACKGROUND_COLOR].prop_id != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
connector_add_prop(drmModeAtomicReq *req, struct drm_connector *connector,
|
||||
enum wdrm_connector_property prop, uint64_t val)
|
||||
|
|
@ -1253,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,
|
||||
|
|
@ -1335,22 +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_BACKGROUND_COLOR,
|
||||
crtc->background_color);
|
||||
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. */
|
||||
|
|
@ -1370,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;
|
||||
}
|
||||
|
|
@ -1392,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);
|
||||
}
|
||||
|
|
@ -1485,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;
|
||||
|
|
@ -1545,10 +1426,12 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
break;
|
||||
}
|
||||
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED) {
|
||||
if (device->state_invalid) {
|
||||
struct weston_head *head_base;
|
||||
struct drm_head *head;
|
||||
struct drm_crtc *crtc;
|
||||
uint32_t connector_id;
|
||||
int err;
|
||||
|
||||
drm_debug(b, "\t\t[atomic] previous state invalid; "
|
||||
"starting with fresh state\n");
|
||||
|
|
@ -1558,6 +1441,7 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
* disable all the CRTCs and connectors we aren't using. */
|
||||
wl_list_for_each(head_base,
|
||||
&b->compositor->head_list, compositor_link) {
|
||||
struct drm_property_info *info;
|
||||
head = to_drm_head(head_base);
|
||||
if (!head)
|
||||
continue;
|
||||
|
|
@ -1565,13 +1449,22 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
if (weston_head_is_enabled(head_base))
|
||||
continue;
|
||||
|
||||
connector_id = head->connector.connector_id;
|
||||
if (head->connector.device != device)
|
||||
continue;
|
||||
|
||||
drm_debug(b, "\t\t[atomic] disabling inactive head %s\n",
|
||||
head_base->name);
|
||||
ret |= connector_add_prop(req, &head->connector,
|
||||
WDRM_CONNECTOR_CRTC_ID, 0);
|
||||
|
||||
info = &head->connector.props[WDRM_CONNECTOR_CRTC_ID];
|
||||
err = drmModeAtomicAddProperty(req, connector_id,
|
||||
info->prop_id, 0);
|
||||
drm_debug(b, "\t\t\t[CONN:%lu] %lu (%s) -> 0\n",
|
||||
(unsigned long) connector_id,
|
||||
(unsigned long) info->prop_id,
|
||||
info->name);
|
||||
if (err <= 0)
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
wl_list_for_each(crtc, &device->crtc_list, link) {
|
||||
|
|
@ -1587,7 +1480,7 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
* off, as the kernel will refuse to generate an event
|
||||
* for an off->off state and fail the commit.
|
||||
*/
|
||||
props = drmModeObjectGetProperties(device->kms_device->fd,
|
||||
props = drmModeObjectGetProperties(device->drm.fd,
|
||||
crtc->crtc_id,
|
||||
DRM_MODE_OBJECT_CRTC);
|
||||
if (!props) {
|
||||
|
|
@ -1631,15 +1524,12 @@ 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;
|
||||
|
||||
ret = drmModeAtomicCommit(device->kms_device->fd, req, flags | tear_flag,
|
||||
ret = drmModeAtomicCommit(device->drm.fd, req, flags | tear_flag,
|
||||
device);
|
||||
drm_debug(b, "[atomic] drmModeAtomicCommit\n");
|
||||
if (ret != 0 && may_tear && mode == DRM_STATE_TEST_ONLY) {
|
||||
|
|
@ -1648,12 +1538,16 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
* out of our state in case we were testing for a later commit.
|
||||
*/
|
||||
drm_debug(b, "[atomic] drmModeAtomicCommit (no tear fallback)\n");
|
||||
ret = drmModeAtomicCommit(device->kms_device->fd, req, flags, device);
|
||||
ret = drmModeAtomicCommit(device->drm.fd, req, flags, device);
|
||||
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)
|
||||
|
|
@ -1669,20 +1563,13 @@ drm_pending_state_apply_atomic(struct drm_pending_state *pending_state,
|
|||
link)
|
||||
drm_output_assign_state(output_state, mode);
|
||||
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED) {
|
||||
device->recovery_status = DRM_RECOVERY_APPLIED;
|
||||
if (mode == DRM_STATE_APPLY_SYNC)
|
||||
drm_device_recovery_complete(device);
|
||||
}
|
||||
device->state_invalid = false;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1701,8 +1588,8 @@ out_test_only:
|
|||
* claim it will work.
|
||||
*
|
||||
* Unlike drm_pending_state_apply() and drm_pending_state_apply_sync(), this
|
||||
* function does _not_ take ownership of pending_state, nor does it complete
|
||||
* a state recovery.
|
||||
* function does _not_ take ownership of pending_state, nor does it clear
|
||||
* state_invalid.
|
||||
*/
|
||||
int
|
||||
drm_pending_state_test(struct drm_pending_state *pending_state)
|
||||
|
|
@ -1723,8 +1610,7 @@ drm_pending_state_test(struct drm_pending_state *pending_state)
|
|||
* applying KMS state to a device. Updates the state for all outputs in the
|
||||
* pending_state, as well as disabling any unclaimed outputs.
|
||||
*
|
||||
* Unconditionally takes ownership of pending_state, and moves along any
|
||||
* scheduled state recovery.
|
||||
* Unconditionally takes ownership of pending_state, and clears state_invalid.
|
||||
*/
|
||||
int
|
||||
drm_pending_state_apply(struct drm_pending_state *pending_state)
|
||||
|
|
@ -1733,7 +1619,6 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
|||
struct drm_backend *b = device->backend;
|
||||
struct drm_output_state *output_state, *tmp;
|
||||
struct drm_crtc *crtc;
|
||||
bool failed = false;
|
||||
|
||||
if (wl_list_empty(&pending_state->output_list)) {
|
||||
drm_pending_state_free(pending_state);
|
||||
|
|
@ -1744,7 +1629,7 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
|||
return drm_pending_state_apply_atomic(pending_state,
|
||||
DRM_STATE_APPLY_ASYNC);
|
||||
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED) {
|
||||
if (device->state_invalid) {
|
||||
/* If we need to reset all our state (e.g. because we've
|
||||
* just started, or just been VT-switched in), explicitly
|
||||
* disable all the CRTCs we aren't using. This also disables
|
||||
|
|
@ -1753,7 +1638,7 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
|||
wl_list_for_each(crtc, &device->crtc_list, link) {
|
||||
if (crtc->output)
|
||||
continue;
|
||||
drmModeSetCrtc(device->kms_device->fd, crtc->crtc_id, 0, 0, 0,
|
||||
drmModeSetCrtc(device->drm.fd, crtc->crtc_id, 0, 0, 0,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -1776,23 +1661,15 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
|||
weston_output_repaint_failed(&output->base);
|
||||
drm_output_state_free(output->state_cur);
|
||||
output->state_cur = drm_output_state_alloc(output);
|
||||
failed = true;
|
||||
device->state_invalid = true;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED) {
|
||||
device->recovery_status = DRM_RECOVERY_APPLIED;
|
||||
drm_device_recovery_complete(device);
|
||||
}
|
||||
if (failed)
|
||||
drm_device_recovery_required(device);
|
||||
device->state_invalid = false;
|
||||
|
||||
assert(wl_list_empty(&pending_state->output_list));
|
||||
|
||||
|
|
@ -1806,8 +1683,7 @@ drm_pending_state_apply(struct drm_pending_state *pending_state)
|
|||
* disable outputs. Does so synchronously: the request is guaranteed to have
|
||||
* completed on return, and the output will not be touched afterwards.
|
||||
*
|
||||
* Unconditionally takes ownership of pending_state, and moves along any
|
||||
* scheduled state recovery.
|
||||
* Unconditionally takes ownership of pending_state, and clears state_invalid.
|
||||
*/
|
||||
int
|
||||
drm_pending_state_apply_sync(struct drm_pending_state *pending_state)
|
||||
|
|
@ -1815,13 +1691,12 @@ drm_pending_state_apply_sync(struct drm_pending_state *pending_state)
|
|||
struct drm_device *device = pending_state->device;
|
||||
struct drm_output_state *output_state, *tmp;
|
||||
struct drm_crtc *crtc;
|
||||
bool failed;
|
||||
|
||||
if (device->atomic_modeset)
|
||||
return drm_pending_state_apply_atomic(pending_state,
|
||||
DRM_STATE_APPLY_SYNC);
|
||||
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED) {
|
||||
if (device->state_invalid) {
|
||||
/* If we need to reset all our state (e.g. because we've
|
||||
* just started, or just been VT-switched in), explicitly
|
||||
* disable all the CRTCs we aren't using. This also disables
|
||||
|
|
@ -1830,7 +1705,7 @@ drm_pending_state_apply_sync(struct drm_pending_state *pending_state)
|
|||
wl_list_for_each(crtc, &device->crtc_list, link) {
|
||||
if (crtc->output)
|
||||
continue;
|
||||
drmModeSetCrtc(device->kms_device->fd, crtc->crtc_id, 0, 0, 0,
|
||||
drmModeSetCrtc(device->drm.fd, crtc->crtc_id, 0, 0, 0,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
|
@ -1844,16 +1719,10 @@ drm_pending_state_apply_sync(struct drm_pending_state *pending_state)
|
|||
if (ret != 0) {
|
||||
weston_log("Couldn't apply state for output %s\n",
|
||||
output_state->output->base.name);
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (device->recovery_status == DRM_RECOVERY_SCHEDULED) {
|
||||
device->recovery_status = DRM_RECOVERY_APPLIED;
|
||||
drm_device_recovery_complete(device);
|
||||
}
|
||||
if (failed)
|
||||
drm_device_recovery_required(device);
|
||||
device->state_invalid = false;
|
||||
|
||||
assert(wl_list_empty(&pending_state->output_list));
|
||||
|
||||
|
|
@ -1889,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);
|
||||
}
|
||||
|
||||
|
|
@ -1903,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;
|
||||
|
|
@ -1920,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) {
|
||||
|
|
@ -1939,9 +1797,6 @@ atomic_flip_handler(int fd, unsigned int frame, unsigned int sec,
|
|||
weston_compositor_read_presentation_clock(ec, &now);
|
||||
sec = now.tv_sec;
|
||||
usec = now.tv_nsec / 1000;
|
||||
|
||||
/* Tearing does not have vsync nor hardware time. */
|
||||
flags = WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION;
|
||||
}
|
||||
|
||||
drm_debug(b, "[atomic][CRTC:%u] flip processing started\n", crtc_id);
|
||||
|
|
@ -1951,26 +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);
|
||||
|
||||
assert(device->atomic_completes_pending > 0);
|
||||
device->atomic_completes_pending--;
|
||||
|
||||
/* We've just completed a recovery operation. */
|
||||
if (!device->atomic_completes_pending &&
|
||||
device->recovery_status == DRM_RECOVERY_APPLIED)
|
||||
drm_device_recovery_complete(device);
|
||||
|
||||
/* We're in an invalid state but were waiting for outstanding flips
|
||||
* to complete before we could begin the recovery process
|
||||
*/
|
||||
if (!device->atomic_completes_pending &&
|
||||
device->recovery_status != DRM_RECOVERY_UNNECESSARY) {
|
||||
assert(device->recovery_status == DRM_RECOVERY_WAIT_FOR_IDLE);
|
||||
|
||||
drm_device_recovery_schedule(device);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1988,7 +1823,7 @@ on_drm_input(int fd, uint32_t mask, void *data)
|
|||
* uses the KMS objects (CRTC, planes, etc) in use by the writeback. */
|
||||
wl_list_for_each(crtc, &device->crtc_list, link) {
|
||||
state = crtc->output ? crtc->output->wb_state : NULL;
|
||||
if (state && !drm_writeback_try_complete(state))
|
||||
if (state && drm_writeback_should_wait_completion(state))
|
||||
wait_wb_completion = true;
|
||||
}
|
||||
if (wait_wb_completion)
|
||||
|
|
@ -2012,9 +1847,9 @@ init_kms_caps(struct drm_device *device)
|
|||
uint64_t cap;
|
||||
int ret;
|
||||
|
||||
weston_log("using %s\n", device->kms_device->filename);
|
||||
weston_log("using %s\n", device->drm.filename);
|
||||
|
||||
ret = drmGetCap(device->kms_device->fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_TIMESTAMP_MONOTONIC, &cap);
|
||||
if (ret != 0 || cap != 1) {
|
||||
weston_log("Error: kernel DRM KMS does not support DRM_CAP_TIMESTAMP_MONOTONIC.\n");
|
||||
return -1;
|
||||
|
|
@ -2022,64 +1857,45 @@ init_kms_caps(struct drm_device *device)
|
|||
|
||||
b->base.supported_presentation_clocks = 1 << CLOCK_MONOTONIC;
|
||||
|
||||
ret = drmGetCap(device->kms_device->fd, DRM_CAP_CURSOR_WIDTH, &cap);
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_CURSOR_WIDTH, &cap);
|
||||
if (ret == 0)
|
||||
device->cursor_width = cap;
|
||||
else
|
||||
device->cursor_width = 64;
|
||||
|
||||
ret = drmGetCap(device->kms_device->fd, DRM_CAP_CURSOR_HEIGHT, &cap);
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_CURSOR_HEIGHT, &cap);
|
||||
if (ret == 0)
|
||||
device->cursor_height = cap;
|
||||
else
|
||||
device->cursor_height = 64;
|
||||
|
||||
ret = drmSetClientCap(device->kms_device->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||
if (ret) {
|
||||
weston_log("Error: drm card doesn't support universal planes!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = drmGetCap(device->kms_device->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 = drmSetClientCap(device->kms_device->fd, DRM_CLIENT_CAP_ATOMIC, 1);
|
||||
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));
|
||||
}
|
||||
weston_log("DRM: %s atomic modesetting\n",
|
||||
device->atomic_modeset ? "supports" : "does not support");
|
||||
|
||||
if (!getenv("WESTON_DISABLE_GBM_MODIFIERS")) {
|
||||
ret = drmGetCap(device->kms_device->fd, DRM_CAP_ADDFB2_MODIFIERS, &cap);
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_ADDFB2_MODIFIERS, &cap);
|
||||
if (ret == 0)
|
||||
device->fb_modifiers = cap;
|
||||
}
|
||||
weston_log("DRM: %s GBM modifiers\n",
|
||||
device->fb_modifiers ? "supports" : "does not support");
|
||||
|
||||
drmSetClientCap(device->kms_device->fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
|
||||
drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_WRITEBACK_CONNECTORS, 1);
|
||||
|
||||
ret = drmGetCap(device->kms_device->fd, DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP, &cap);
|
||||
ret = drmGetCap(device->drm.fd, DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP, &cap);
|
||||
if (ret == 0)
|
||||
device->tearing_supported = cap;
|
||||
weston_log("DRM: %s Atomic async page flip\n",
|
||||
|
|
@ -2094,9 +1910,9 @@ init_kms_caps(struct drm_device *device)
|
|||
* enabled.
|
||||
*/
|
||||
if (!device->atomic_modeset || getenv("WESTON_FORCE_RENDERER"))
|
||||
device->disable_client_buffer_scanout = true;
|
||||
device->sprites_are_broken = true;
|
||||
|
||||
ret = drmSetClientCap(device->kms_device->fd, DRM_CLIENT_CAP_ASPECT_RATIO, 1);
|
||||
ret = drmSetClientCap(device->drm.fd, DRM_CLIENT_CAP_ASPECT_RATIO, 1);
|
||||
device->aspect_ratio_supported = (ret == 0);
|
||||
weston_log("DRM: %s picture aspect ratio\n",
|
||||
device->aspect_ratio_supported ? "supports" : "does not support");
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ static long backlight_get(struct backlight *backlight, char *node)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = read(fd, buffer, sizeof(buffer));
|
||||
ret = read(fd, &buffer, sizeof(buffer));
|
||||
if (ret < 1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
|
|
@ -119,6 +119,12 @@ long backlight_set_brightness(struct backlight *backlight, long brightness)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = read(fd, &buffer, sizeof(buffer));
|
||||
if (ret < 1) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
str_printf(&buffer, "%ld", brightness);
|
||||
if (!buffer) {
|
||||
ret = -1;
|
||||
|
|
@ -234,7 +240,7 @@ struct backlight *backlight_init(struct udev_device *drm_device,
|
|||
if (fd < 0)
|
||||
goto out;
|
||||
|
||||
ret = read (fd, buffer, sizeof(buffer));
|
||||
ret = read (fd, &buffer, sizeof(buffer));
|
||||
close (fd);
|
||||
|
||||
if (ret < 1)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,20 @@ if not get_option('backend-drm')
|
|||
subdir_done()
|
||||
endif
|
||||
|
||||
dep_libdisplay_info = dependency(
|
||||
'libdisplay-info',
|
||||
version: ['>= 0.1.1', '< 0.3.0'],
|
||||
fallback: ['display-info', 'di_dep'],
|
||||
default_options: [
|
||||
'werror=false',
|
||||
],
|
||||
required: true,
|
||||
not_found_message: 'Required by DRM-backend.',
|
||||
)
|
||||
if dep_libdisplay_info.version().version_compare('>= 0.2.0')
|
||||
config_h.set('HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY', '1')
|
||||
endif
|
||||
|
||||
lib_backlight = static_library(
|
||||
'backlight',
|
||||
'libbacklight.c',
|
||||
|
|
@ -34,7 +48,6 @@ srcs_drm = [
|
|||
|
||||
deps_drm = [
|
||||
dep_egl, # optional
|
||||
dep_vulkan, # optional
|
||||
dep_libm,
|
||||
dep_libdl,
|
||||
dep_libshared,
|
||||
|
|
@ -56,16 +69,21 @@ if get_option('renderer-gl')
|
|||
config_h.set('BUILD_DRM_GBM', '1')
|
||||
endif
|
||||
|
||||
if get_option('renderer-vulkan')
|
||||
if not dep_gbm.found()
|
||||
error('drm-backend with Vulkan renderer requires gbm which was not found. Or, you can use \'-Drenderer-vulkan=false\'.')
|
||||
endif
|
||||
deps_drm += dep_gbm
|
||||
srcs_drm += 'drm-gbm.c'
|
||||
config_h.set('BUILD_DRM_GBM', '1')
|
||||
if get_option('backend-drm-screencast-vaapi')
|
||||
foreach name : [ 'libva', 'libva-drm' ]
|
||||
d = dependency(name, version: '>= 0.34.0', required: false)
|
||||
if not d.found()
|
||||
error('VA-API recorder requires @0@ >= 0.34.0 which was not found. Or, you can use \'-Dbackend-drm-screencast-vaapi=false\'.'.format(name))
|
||||
endif
|
||||
deps_drm += d
|
||||
endforeach
|
||||
|
||||
srcs_drm += 'vaapi-recorder.c'
|
||||
deps_drm += dependency('threads')
|
||||
config_h.set('BUILD_VAAPI_RECORDER', '1')
|
||||
endif
|
||||
|
||||
if get_option('deprecated-remoting') or get_option('deprecated-pipewire')
|
||||
if get_option('remoting') or get_option('pipewire')
|
||||
if not get_option('renderer-gl')
|
||||
error('DRM virtual requires renderer-gl.')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <libdisplay-info/cta.h>
|
||||
#include <libdisplay-info/edid.h>
|
||||
#include <libdisplay-info/info.h>
|
||||
|
||||
#include "drm-internal.h"
|
||||
|
|
@ -53,10 +51,6 @@ struct drm_head_info {
|
|||
* enum weston_colorimetry_mode bits.
|
||||
*/
|
||||
uint32_t colorimetry_mask;
|
||||
|
||||
/* The monitor supported color foramts, combination of
|
||||
* enum_weston_color_format bits. */
|
||||
uint32_t color_format_mask;
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -139,7 +133,7 @@ drm_mode_ensure_blob(struct drm_device *device, struct drm_mode *mode)
|
|||
if (mode->blob_id)
|
||||
return 0;
|
||||
|
||||
ret = drmModeCreatePropertyBlob(device->kms_device->fd,
|
||||
ret = drmModeCreatePropertyBlob(device->drm.fd,
|
||||
&mode->mode_info,
|
||||
sizeof(mode->mode_info),
|
||||
&mode->blob_id);
|
||||
|
|
@ -233,6 +227,8 @@ parse_modeline(const char *s, drmModeModeInfo *mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY
|
||||
|
||||
static uint32_t
|
||||
get_eotf_mask(const struct di_info *info)
|
||||
{
|
||||
|
|
@ -288,76 +284,22 @@ get_colorimetry_mask(const struct di_info *info)
|
|||
return mask;
|
||||
}
|
||||
|
||||
static bool
|
||||
has_yuv420_cap_map(const struct di_edid_cta *cta)
|
||||
#else /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
|
||||
|
||||
static uint32_t
|
||||
get_eotf_mask(const struct di_info *info)
|
||||
{
|
||||
const struct di_cta_data_block *const *data_blocks;
|
||||
enum di_cta_data_block_tag db_tag;
|
||||
int i;
|
||||
|
||||
data_blocks = di_edid_cta_get_data_blocks(cta);
|
||||
for (i = 0; data_blocks[i] != NULL; i++) {
|
||||
db_tag = di_cta_data_block_get_tag(data_blocks[i]);
|
||||
if (db_tag == DI_CTA_DATA_BLOCK_YCBCR420_CAP_MAP)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return WESTON_EOTF_MODE_SDR;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_color_format_mask(const struct di_info *info)
|
||||
get_colorimetry_mask(const struct di_info *info)
|
||||
{
|
||||
const struct di_edid *edid = di_info_get_edid(info);
|
||||
const struct di_edid_color_encoding_formats *fmts =
|
||||
di_edid_get_color_encoding_formats(edid);
|
||||
const struct di_edid_ext *const *exts = di_edid_get_extensions(edid);
|
||||
uint32_t mask = WESTON_COLOR_FORMAT_AUTO;
|
||||
int i;
|
||||
|
||||
if (fmts) {
|
||||
if (fmts->rgb444)
|
||||
mask |= WESTON_COLOR_FORMAT_RGB;
|
||||
|
||||
if (fmts->ycrcb444)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV444;
|
||||
|
||||
if (fmts->ycrcb422)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||
}
|
||||
|
||||
for (i = 0; exts[i] ; i++) {
|
||||
const struct di_edid_cta *cta;
|
||||
const struct di_edid_cta_flags *cta_flags;
|
||||
|
||||
switch (di_edid_ext_get_tag(exts[i])) {
|
||||
case DI_EDID_EXT_CEA:
|
||||
cta = di_edid_ext_get_cta(exts[i]);
|
||||
cta_flags = di_edid_cta_get_flags(cta);
|
||||
|
||||
mask |= WESTON_COLOR_FORMAT_RGB;
|
||||
|
||||
if (cta_flags->ycc444)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV444;
|
||||
|
||||
if (cta_flags->ycc422)
|
||||
mask |= WESTON_COLOR_FORMAT_YUV422;
|
||||
|
||||
/* FIXME: YUV420 detection is really complicated,
|
||||
* do it properly at some point...
|
||||
*/
|
||||
if (has_yuv420_cap_map(cta))
|
||||
mask |= WESTON_COLOR_FORMAT_YUV420;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mask;
|
||||
return WESTON_COLORIMETRY_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBDISPLAY_INFO_HIGH_LEVEL_COLORIMETRY */
|
||||
|
||||
static struct di_info *
|
||||
drm_head_info_from_edid(struct drm_head_info *dhi,
|
||||
const uint8_t *data,
|
||||
|
|
@ -383,7 +325,6 @@ drm_head_info_from_edid(struct drm_head_info *dhi,
|
|||
dhi->serial_number = di_info_get_serial(di_ctx);
|
||||
dhi->eotf_mask = get_eotf_mask(di_ctx);
|
||||
dhi->colorimetry_mask = get_colorimetry_mask(di_ctx);
|
||||
dhi->color_format_mask = get_color_format_mask(di_ctx);
|
||||
|
||||
return di_ctx;
|
||||
}
|
||||
|
|
@ -428,7 +369,7 @@ drm_head_maybe_update_display_data(struct drm_head *head,
|
|||
&head->connector.props[WDRM_CONNECTOR_EDID],
|
||||
props, 0);
|
||||
if (blob_id)
|
||||
edid_blob = drmModeGetPropertyBlob(device->kms_device->fd, blob_id);
|
||||
edid_blob = drmModeGetPropertyBlob(device->drm.fd, blob_id);
|
||||
|
||||
if (edid_blob && edid_blob->length > 0) {
|
||||
if (!head->display_data ||
|
||||
|
|
@ -553,7 +494,7 @@ static void
|
|||
drm_output_destroy_mode(struct drm_device *device, struct drm_mode *mode)
|
||||
{
|
||||
if (mode->blob_id)
|
||||
drmModeDestroyPropertyBlob(device->kms_device->fd, mode->blob_id);
|
||||
drmModeDestroyPropertyBlob(device->drm.fd, mode->blob_id);
|
||||
wl_list_remove(&mode->base.link);
|
||||
free(mode);
|
||||
}
|
||||
|
|
@ -656,46 +597,26 @@ void
|
|||
update_head_from_connector(struct drm_head *head)
|
||||
{
|
||||
struct drm_connector *connector = &head->connector;
|
||||
struct drm_backend *b = head->connector.device->backend;
|
||||
drmModeObjectProperties *props = connector->props_drm;
|
||||
drmModeConnector *conn = connector->conn;
|
||||
int vrr_capable;
|
||||
uint32_t vrr_mode_mask = 0;
|
||||
uint32_t conn_id = head->connector.connector_id;
|
||||
bool ret;
|
||||
|
||||
ret = weston_head_set_non_desktop(&head->base,
|
||||
weston_head_set_non_desktop(&head->base,
|
||||
check_non_desktop(connector, props));
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] non-desktop property changed\n", conn_id);
|
||||
|
||||
ret = weston_head_set_subpixel(&head->base,
|
||||
weston_head_set_subpixel(&head->base,
|
||||
drm_subpixel_to_wayland(conn->subpixel));
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] subpixel property changed\n", conn_id);
|
||||
|
||||
ret = weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] physical size changed\n", conn_id);
|
||||
weston_head_set_physical_size(&head->base, conn->mmWidth, conn->mmHeight);
|
||||
|
||||
ret = weston_head_set_transform(&head->base,
|
||||
weston_head_set_transform(&head->base,
|
||||
get_panel_orientation(connector, props));
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] transform property changed\n", conn_id);
|
||||
|
||||
/* Unknown connection status is assumed disconnected. */
|
||||
ret = weston_head_set_connection_status(&head->base,
|
||||
weston_head_set_connection_status(&head->base,
|
||||
conn->connection == DRM_MODE_CONNECTED);
|
||||
if (ret)
|
||||
drm_debug(b, "\t[CONN:%d] connection status changed\n", conn_id);
|
||||
|
||||
/* If EDID did not change, skip everything about it */
|
||||
if (!drm_head_maybe_update_display_data(head, props)) {
|
||||
if (!ret)
|
||||
drm_debug(b, "\t[CONN:%d] Hot-plug event received "
|
||||
"but no connector changes detected\n", conn_id);
|
||||
if (!drm_head_maybe_update_display_data(head, props))
|
||||
return;
|
||||
}
|
||||
|
||||
struct drm_head_info dhi;
|
||||
|
||||
|
|
@ -709,18 +630,11 @@ update_head_from_connector(struct drm_head *head)
|
|||
dhi.serial_number);
|
||||
|
||||
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
|
||||
|
||||
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
|
||||
|
||||
dhi.colorimetry_mask &= drm_head_get_kms_colorimetry_modes(head);
|
||||
weston_head_set_supported_colorimetry_mask(&head->base, dhi.colorimetry_mask);
|
||||
|
||||
vrr_capable = drm_property_get_value(&head->connector.props[WDRM_CONNECTOR_VRR_CAPABLE],
|
||||
head->connector.props_drm, 0);
|
||||
if (vrr_capable)
|
||||
vrr_mode_mask = WESTON_VRR_MODE_GAME;
|
||||
weston_head_set_supported_vrr_modes_mask(&head->base, vrr_mode_mask);
|
||||
|
||||
drm_head_info_fini(&dhi);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,7 @@
|
|||
#include <xf86drmMode.h>
|
||||
|
||||
#include "drm-internal.h"
|
||||
#include "shared/weston-assert.h"
|
||||
#include "shared/weston-drm-fourcc.h"
|
||||
#include "shared/xalloc.h"
|
||||
|
||||
/**
|
||||
* Allocate a new, empty, plane state.
|
||||
|
|
@ -49,7 +47,6 @@ drm_plane_state_alloc(struct drm_output_state *state_output,
|
|||
assert(state);
|
||||
state->output_state = state_output;
|
||||
state->plane = plane;
|
||||
state->handle = NULL;
|
||||
state->in_fence_fd = -1;
|
||||
state->rotation = drm_rotation_from_output_transform(plane,
|
||||
WL_OUTPUT_TRANSFORM_NORMAL);
|
||||
|
|
@ -58,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
|
||||
|
|
@ -102,7 +96,7 @@ drm_plane_state_free(struct drm_plane_state *state, bool force)
|
|||
if (state->damage_blob_id != 0) {
|
||||
device = state->plane->device;
|
||||
|
||||
drmModeDestroyPropertyBlob(device->kms_device->fd,
|
||||
drmModeDestroyPropertyBlob(device->drm.fd,
|
||||
state->damage_blob_id);
|
||||
state->damage_blob_id = 0;
|
||||
}
|
||||
|
|
@ -216,16 +210,16 @@ drm_plane_state_put_back(struct drm_plane_state *state)
|
|||
}
|
||||
|
||||
/**
|
||||
* Given a weston_paint_node, fill the drm_plane_state's co-ordinates to
|
||||
* display on a given plane.
|
||||
* Given a weston_view, fill the drm_plane_state's co-ordinates to display on
|
||||
* a given plane.
|
||||
*/
|
||||
void
|
||||
bool
|
||||
drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
||||
struct weston_paint_node *pnode,
|
||||
struct weston_paint_node *node,
|
||||
uint64_t zpos)
|
||||
{
|
||||
struct drm_output *output = state->handle->output;
|
||||
struct weston_view *ev = pnode->view;
|
||||
struct drm_output *output = state->output;
|
||||
struct weston_view *ev = node->view;
|
||||
struct weston_buffer *buffer = ev->surface->buffer_ref.buffer;
|
||||
pixman_region32_t dest_rect;
|
||||
pixman_box32_t *box;
|
||||
|
|
@ -234,16 +228,16 @@ 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(pnode, state->plane));
|
||||
if (!drm_paint_node_transform_supported(node, state->plane))
|
||||
return false;
|
||||
|
||||
assert(pnode->valid_transform);
|
||||
state->rotation = drm_rotation_from_output_transform(state->plane, pnode->transform);
|
||||
assert(node->valid_transform);
|
||||
state->rotation = drm_rotation_from_output_transform(state->plane, node->transform);
|
||||
|
||||
/* Update the base weston_plane co-ordinates. */
|
||||
box = pixman_region32_extents(&ev->transform.boundingbox);
|
||||
state->plane->base.x = box->x1;
|
||||
state->plane->base.y = box->y1;
|
||||
|
||||
/* First calculate the destination co-ordinates by taking the
|
||||
* area of the view which is visible on this output, performing any
|
||||
|
|
@ -263,10 +257,10 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
|||
/* Now calculate the source rectangle, by transforming the destination
|
||||
* rectangle by the output to buffer matrix. */
|
||||
corners[0] = weston_matrix_transform_coord(
|
||||
&pnode->output_to_buffer_matrix,
|
||||
&node->output_to_buffer_matrix,
|
||||
weston_coord(box->x1, box->y1));
|
||||
corners[1] = weston_matrix_transform_coord(
|
||||
&pnode->output_to_buffer_matrix,
|
||||
&node->output_to_buffer_matrix,
|
||||
weston_coord(box->x2, box->y2));
|
||||
sxf1 = corners[0].x;
|
||||
syf1 = corners[0].y;
|
||||
|
|
@ -315,10 +309,11 @@ drm_plane_state_coords_for_paint_node(struct drm_plane_state *state,
|
|||
|
||||
/* The alpha of the view is normalized to alpha value range
|
||||
* [min_alpha, max_alpha] that got from drm. The alpha value would
|
||||
* never exceed max_alpha if pnode->view_alpha <= 1.0.
|
||||
* never exceed max_alpha if ev->alpha <= 1.0.
|
||||
*/
|
||||
state->alpha = min_alpha +
|
||||
(uint16_t)round((max_alpha - min_alpha) * pnode->view_alpha);
|
||||
state->alpha = min_alpha + (uint16_t)round((max_alpha - min_alpha) * ev->alpha);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -403,12 +398,10 @@ drm_output_state_duplicate(struct drm_output_state *src,
|
|||
struct drm_pending_state *pending_state,
|
||||
enum drm_output_state_duplicate_mode plane_mode)
|
||||
{
|
||||
struct weston_compositor *compositor = src->output->base.compositor;
|
||||
struct drm_output_state *dst = xmalloc(sizeof(*dst));
|
||||
struct drm_output_state *dst = malloc(sizeof(*dst));
|
||||
struct drm_plane_state *ps;
|
||||
|
||||
/* The reuse bit isn't stored in the state */
|
||||
weston_assert_false(compositor, src->mode & DRM_OUTPUT_PROPOSE_STATE_REUSE);
|
||||
assert(dst);
|
||||
|
||||
/* Copy the whole structure, then individually modify the
|
||||
* pending_state, as well as the list link into our pending
|
||||
|
|
@ -426,7 +419,7 @@ drm_output_state_duplicate(struct drm_output_state *src,
|
|||
wl_list_for_each(ps, &src->plane_list, link) {
|
||||
/* Don't carry planes which are now disabled; these should be
|
||||
* free for other outputs to reuse. */
|
||||
if (!ps->handle)
|
||||
if (!ps->output)
|
||||
continue;
|
||||
|
||||
if (plane_mode == DRM_OUTPUT_STATE_CLEAR_PLANES)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
1161
libweston/backend-drm/vaapi-recorder.c
Normal file
1161
libweston/backend-drm/vaapi-recorder.c
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue