mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2025-12-25 02:30:06 +01:00
Compare commits
154 commits
master
...
xwayland-2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
449b197e7e | ||
|
|
d2a7903154 | ||
|
|
2c5e87e3df | ||
|
|
fce91bcbe2 | ||
|
|
9d20532389 | ||
|
|
41ae2e70ad | ||
|
|
b7c5685a26 | ||
|
|
437a0cad0b | ||
|
|
fa6b40037a | ||
|
|
34ef671aa5 | ||
|
|
a50e6a2e33 | ||
|
|
1119ea220a | ||
|
|
6f1acb0dff | ||
|
|
3a6d035aec | ||
|
|
91e42e523c | ||
|
|
bd43d90cd1 | ||
|
|
ed54cc2a03 | ||
|
|
b32d637f51 | ||
|
|
852595a51d | ||
|
|
15075baac2 | ||
|
|
6d33c347ea | ||
|
|
5b1d9da00f | ||
|
|
9dbe93ebee | ||
|
|
6f567221a6 | ||
|
|
fb6df2a68c | ||
|
|
1932abe3d0 | ||
|
|
842f4abde4 | ||
|
|
318085a6f5 | ||
|
|
40efa6359c | ||
|
|
cc15c9fa40 | ||
|
|
39c7ed837b | ||
|
|
60df821467 | ||
|
|
bfbb53e0b9 | ||
|
|
80f8d0b8e2 | ||
|
|
543708ae93 | ||
|
|
69f1580140 | ||
|
|
f04096af3c | ||
|
|
ffc3aa63d3 | ||
|
|
f18a83d6f1 | ||
|
|
f7e3397e4d | ||
|
|
cea92a3e09 | ||
|
|
1a8f0cb007 | ||
|
|
e6a5d545ce | ||
|
|
e1b6193a9d | ||
|
|
f8e32cba6e | ||
|
|
1ae92b8f63 | ||
|
|
ffd4d2a268 | ||
|
|
efd3e1ca3d | ||
|
|
5294c436ac | ||
|
|
15a169cd1a | ||
|
|
f221e9f903 | ||
|
|
7c25024879 | ||
|
|
f340f082b8 | ||
|
|
30427d3ddc | ||
|
|
5e320e1193 | ||
|
|
cec5c7c3b2 | ||
|
|
a939e47c13 | ||
|
|
ce9d187101 | ||
|
|
ca0799e7f2 | ||
|
|
3bfef8d7c0 | ||
|
|
26120df7aa | ||
|
|
113245b1ab | ||
|
|
0713e7e382 | ||
|
|
8d9b8249a7 | ||
|
|
02546fa66a | ||
|
|
e4d9cbf0e9 | ||
|
|
5d84e4779b | ||
|
|
2d5494ebbb | ||
|
|
cfda3969a1 | ||
|
|
4335bdeb01 | ||
|
|
6d384ab8bf | ||
|
|
fc7b6c7549 | ||
|
|
83033ce108 | ||
|
|
44d1b7e4c1 | ||
|
|
013311852d | ||
|
|
2f1ea65b6d | ||
|
|
0d1b7672e7 | ||
|
|
a73fb98dc3 | ||
|
|
98fb1d48c4 | ||
|
|
b701969331 | ||
|
|
16645b410d | ||
|
|
13cfe2ec85 | ||
|
|
11d0f4f19d | ||
|
|
e50ea9181a | ||
|
|
fa70fdf961 | ||
|
|
05a3a4068b | ||
|
|
4262fb182b | ||
|
|
54a591b9b8 | ||
|
|
4d88af2228 | ||
|
|
2a360e5c0f | ||
|
|
a2446275c9 | ||
|
|
978093d1a5 | ||
|
|
4543d4a25a | ||
|
|
8937d47d08 | ||
|
|
a1651d41e7 | ||
|
|
b3635ba69e | ||
|
|
fac3486a66 | ||
|
|
ce7fb8139a | ||
|
|
98326b8c9f | ||
|
|
ca52da8cba | ||
|
|
c0bd91f49e | ||
|
|
cec99a3811 | ||
|
|
8130fa083c | ||
|
|
38060228c1 | ||
|
|
4942b7c137 | ||
|
|
f834e104aa | ||
|
|
aa0ea88e13 | ||
|
|
6a916c9658 | ||
|
|
8f611b0f22 | ||
|
|
33486519dc | ||
|
|
6636b7c003 | ||
|
|
4382a4f84e | ||
|
|
1539f208e2 | ||
|
|
b1734ae737 | ||
|
|
23400afb72 | ||
|
|
05f4411523 | ||
|
|
fbd40e878b | ||
|
|
526dcbe120 | ||
|
|
1d21f8db26 | ||
|
|
59bf93c770 | ||
|
|
dc2e34aa0e | ||
|
|
1126d55f80 | ||
|
|
ce0e52dd0b | ||
|
|
2d0dabbe10 | ||
|
|
ce6c665e77 | ||
|
|
3f4745cc4a | ||
|
|
88ab664fab | ||
|
|
5a4b654334 | ||
|
|
9f28e2a85d | ||
|
|
07470d2ca2 | ||
|
|
f10354d16a | ||
|
|
de65e7df4d | ||
|
|
eec66b819d | ||
|
|
cb6c7256ab | ||
|
|
34832a182c | ||
|
|
74d02b98ab | ||
|
|
aa17d7eba6 | ||
|
|
158246a0af | ||
|
|
80af615ea9 | ||
|
|
4725674a23 | ||
|
|
9f4d612e7e | ||
|
|
84b6d7e2c5 | ||
|
|
596db5424d | ||
|
|
751af1243e | ||
|
|
3d5eb2df23 | ||
|
|
9cd94d3976 | ||
|
|
6b100681d6 | ||
|
|
7f3a9a4059 | ||
|
|
94228264a7 | ||
|
|
1f80c795e0 | ||
|
|
dfea734656 | ||
|
|
34fac2d7df | ||
|
|
735009cda3 | ||
|
|
700cdeeee4 |
889 changed files with 1247 additions and 261921 deletions
|
|
@ -73,7 +73,7 @@ cache:
|
|||
- '%CYGWIN_ROOT%\home\%USERNAME%\.ccache'
|
||||
build_script:
|
||||
- SET PATH=%CYGWIN_ROOT%/bin
|
||||
- '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; meson setup --prefix=/usr -Dxv=false -Dxf86bigfont=true -Dxephyr=true -Dxnest=true -Dxvfb=true -Dxwin=true -Dxorg=true -Dpciaccess=false -Dint10=false -Dglamor=false build"'
|
||||
- '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; meson setup --prefix=/usr -Dxv=false -Dxf86bigfont=true -Dxvfb=true -Dglamor=false build"'
|
||||
- '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; meson configure build"'
|
||||
- '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; ninja -C build"'
|
||||
- '%CYGWIN_ROOT%/bin/bash -lc "cd $APPVEYOR_BUILD_FOLDER; ccache -s"'
|
||||
|
|
|
|||
121
.gitlab-ci.yml
121
.gitlab-ci.yml
|
|
@ -19,7 +19,7 @@ variables:
|
|||
FDO_UPSTREAM_REPO: xorg/xserver
|
||||
FDO_DISTRIBUTION_VERSION: bullseye-slim
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/debian-install.sh'
|
||||
FDO_DISTRIBUTION_TAG: "2024-03-26-explicit-sync-2"
|
||||
FDO_DISTRIBUTION_TAG: "2024-09-24-no-xorg"
|
||||
MESON_BUILDDIR: "build"
|
||||
|
||||
include:
|
||||
|
|
@ -34,7 +34,6 @@ include:
|
|||
stages:
|
||||
- docker-image
|
||||
- build-and-test
|
||||
- drivers
|
||||
- test
|
||||
|
||||
.ci-run-policy:
|
||||
|
|
@ -46,54 +45,6 @@ stages:
|
|||
# Cancel CI run if a newer commit is pushed to the same branch
|
||||
interruptible: true
|
||||
|
||||
# This is everything but the DDXen
|
||||
.dix_paths: &dix_paths
|
||||
# Directories
|
||||
- .gitlab-ci/**/*
|
||||
- composite/**/*
|
||||
- config/**/*
|
||||
- damageext/**/*
|
||||
- dbe/**/*
|
||||
- dix/**/*
|
||||
- doc/**/*
|
||||
- dri3/**/*
|
||||
- exa/**/*
|
||||
- fb/**/*
|
||||
- glamor/**/*
|
||||
- glx/**/*
|
||||
- include/**/*
|
||||
- m4/**/*
|
||||
- man/**/*
|
||||
- mi/**/*
|
||||
- miext/**/*
|
||||
- os/**/*
|
||||
- present/**/*
|
||||
- pseudoramiX/**/*
|
||||
- randr/**/*
|
||||
- record/**/*
|
||||
- render/**/*
|
||||
- test/**/*
|
||||
- Xext/**/*
|
||||
- xfixes/**/*
|
||||
- Xi/**/*
|
||||
- xkb/**/*
|
||||
# Files
|
||||
- hw/meson.build
|
||||
- .gitlab-ci.yml
|
||||
- meson*
|
||||
- xorg-server.m4
|
||||
- xorg-server.pc.in
|
||||
- xserver.ent.in
|
||||
|
||||
.xorg_paths: &xorg_paths
|
||||
- hw/xfree86/**/*
|
||||
|
||||
.xwayland_paths: &xwayland_paths
|
||||
- hw/xwayland/**/*
|
||||
|
||||
.all_ddx_paths:
|
||||
- hw/**/*
|
||||
|
||||
debian-bullseye:
|
||||
extends:
|
||||
- .fdo.container-build@debian
|
||||
|
|
@ -147,81 +98,21 @@ meson-nolibdecor:
|
|||
MESON_EXTRA_ARGS: >
|
||||
-Dlibdecor=false
|
||||
|
||||
mingw-cross-build:
|
||||
extends: .common-build-and-test
|
||||
script:
|
||||
- .gitlab-ci/meson-build.sh --run-install
|
||||
variables:
|
||||
MESON_ARGS: --cross-file=.gitlab-ci/cross-i686-w64-mingw32.txt -Dglx=false -Dsecure-rpc=false -Dlisten_tcp=true
|
||||
|
||||
meson-dist:
|
||||
extends: .common-build-and-test
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- $MESON_BUILDDIR/meson-logs/
|
||||
- $MESON_BUILDDIR/xserver-*/$MESON_BUILDDIR/meson-logs/
|
||||
- $MESON_BUILDDIR/xwayland-*/$MESON_BUILDDIR/meson-logs/
|
||||
script:
|
||||
- .gitlab-ci/meson-build.sh --run-dist
|
||||
- mkdir xserver-tarball
|
||||
- tar xf $MESON_BUILDDIR/meson-dist/xserver-*.tar.xz -C xserver-tarball --strip-components=1
|
||||
- .gitlab-ci/meson-build.sh -C xserver-tarball --skip-test --skip-dist --run-install
|
||||
- mkdir xwayland-tarball
|
||||
- tar xf $MESON_BUILDDIR/meson-dist/xwayland-*.tar.xz -C xwayland-tarball --strip-components=1
|
||||
- .gitlab-ci/meson-build.sh -C xwayland-tarball --skip-test --skip-dist --run-install
|
||||
variables:
|
||||
MESON_DIST_ARGS: --no-tests
|
||||
DESTDIR: xserver-tarball/install/
|
||||
|
||||
xf86-driver-build-test:
|
||||
extends:
|
||||
- .fdo.distribution-image@debian
|
||||
- .ci-run-policy
|
||||
stage: drivers
|
||||
parallel:
|
||||
matrix:
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-input-evdev
|
||||
SHA: xf86-input-evdev-2.10.6
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-input-libinput
|
||||
SHA: xf86-input-libinput-1.4.0
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-input-mouse
|
||||
SHA: xf86-input-mouse-1.9.5
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-input-synaptics
|
||||
SHA: xf86-input-synaptics-1.9.2
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-video-amdgpu
|
||||
SHA: xf86-video-amdgpu-23.0.0
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati
|
||||
SHA: xf86-video-ati-22.0.0
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-video-qxl
|
||||
SHA: xf86-video-qxl-0.1.6
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-video-vesa
|
||||
SHA: xf86-video-vesa-2.6.0
|
||||
- REPO: https://gitlab.freedesktop.org/xorg/driver/xf86-video-vmware
|
||||
SHA: xf86-video-vmware-13.4.0
|
||||
script:
|
||||
# Install the server first
|
||||
- .gitlab-ci/meson-build.sh --skip-test --run-install
|
||||
- unset MESON_EXTRA_ARGS
|
||||
- DRIVER=$(basename $REPO)
|
||||
- git clone "$REPO" "$DRIVER"
|
||||
- GIT_DIR="$DRIVER/.git" git checkout -f "$SHA"
|
||||
- |
|
||||
if [[ -e "$DRIVER/meson.build" ]]; then
|
||||
.gitlab-ci/meson-build.sh -C "$DRIVER" --skip-test
|
||||
else
|
||||
pushd "$DRIVER" || exit 1
|
||||
./autogen.sh && make
|
||||
fi
|
||||
needs:
|
||||
- "meson"
|
||||
variables:
|
||||
GIT_DEPTH: 1
|
||||
MESON_ARGS: -Dprefix=/usr/
|
||||
MESON_EXTRA_ARGS: -Dxwayland=false -Dxnest=false -Dxvfb=false -Dxquartz=false -Ddocs=false
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||
changes:
|
||||
*dix_paths
|
||||
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
|
||||
changes:
|
||||
*xorg_paths
|
||||
DESTDIR: xwayland-tarball/install/
|
||||
|
||||
#
|
||||
# Verify that commit messages are as expected
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
[binaries]
|
||||
c = 'i686-w64-mingw32-gcc'
|
||||
cpp = 'i686-w64-mingw32-g++'
|
||||
ar = 'i686-w64-mingw32-ar'
|
||||
strip = 'i686-w64-mingw32-strip'
|
||||
pkgconfig = '/usr/local/bin/i686-w64-mingw32-pkg-config'
|
||||
windres = 'i686-w64-mingw32-windres'
|
||||
exe_wrapper = 'wine'
|
||||
|
||||
[properties]
|
||||
# Directory that contains 'bin', 'lib', etc for the toolchain
|
||||
root = '/usr/i686-w64-mingw32'
|
||||
# Directory that contains 'bin', 'lib', etc which have been cross-compiled
|
||||
sys_root = '/usr/i686-w64-mingw32'
|
||||
|
||||
[host_machine]
|
||||
system = 'windows'
|
||||
cpu_family = 'x86'
|
||||
cpu = 'i686'
|
||||
endian = 'little'
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
set -o xtrace
|
||||
|
||||
HOST=$1
|
||||
|
||||
# Debian's cross-pkg-config wrappers are broken for MinGW targets, since
|
||||
# dpkg-architecture doesn't know about MinGW target triplets.
|
||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=930492
|
||||
cat >/usr/local/bin/${HOST}-pkg-config <<EOF
|
||||
#!/bin/sh
|
||||
|
||||
PKG_CONFIG_SYSROOT_DIR=/usr/${HOST} PKG_CONFIG_LIBDIR=/usr/${HOST}/lib/pkgconfig:/usr/share/pkgconfig pkg-config \$@
|
||||
EOF
|
||||
chmod +x /usr/local/bin/${HOST}-pkg-config
|
||||
|
||||
# when cross-compiling, some autoconf tests cannot be run:
|
||||
|
||||
# --enable-malloc0returnsnull
|
||||
export xorg_cv_malloc0_returns_null=yes
|
||||
|
||||
build() {
|
||||
url=$1
|
||||
commit=$2
|
||||
config=$3
|
||||
|
||||
name=$(basename ${url} .git)
|
||||
|
||||
if [[ $commit =~ ^[[:xdigit:]]{1,}$ ]]
|
||||
then
|
||||
git clone ${url} ${name}
|
||||
git -C ${name} checkout ${commit}
|
||||
else
|
||||
git clone --depth 1 --branch ${commit:-master} --recurse-submodules -c advice.detachedHead=false ${url} ${name}
|
||||
fi
|
||||
|
||||
pushd ${name}
|
||||
NOCONFIGURE=1 ./autogen.sh || ./.bootstrap
|
||||
./configure ${config} --host=${HOST} --prefix= --with-sysroot=/usr/${HOST}/
|
||||
make -j$(nproc)
|
||||
DESTDIR=/usr/${HOST} make install
|
||||
|
||||
popd
|
||||
rm -rf ${OLDPWD}
|
||||
}
|
||||
|
||||
build 'https://gitlab.freedesktop.org/pixman/pixman.git' 'pixman-0.38.4'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/pthread-stubs.git' '0.4'
|
||||
# we can't use the xorgproto pkgconfig files from /usr/share/pkgconfig, because
|
||||
# these would add -I/usr/include to CFLAGS, which breaks cross-compilation
|
||||
build 'https://gitlab.freedesktop.org/xorg/proto/xorgproto.git' 'xorgproto-2024.1' '--datadir=/lib'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libXau.git' 'libXau-1.0.9'
|
||||
build 'https://gitlab.freedesktop.org/xorg/proto/xcbproto.git' 'xcb-proto-1.14.1'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libxcb.git' 'libxcb-1.14'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libxtrans.git' 'xtrans-1.4.0'
|
||||
# the default value of keysymdefdir is taken from the includedir variable for
|
||||
# xproto, which isn't adjusted by pkg-config for the sysroot
|
||||
# Using -fcommon to address build failure when cross-compiling for windows.
|
||||
# See discussion at https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/913
|
||||
CFLAGS="-fcommon" build 'https://gitlab.freedesktop.org/xorg/lib/libX11.git' 'libX11-1.6.9' "--with-keysymdefdir=/usr/${HOST}/include/X11"
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libxkbfile.git' 'libxkbfile-1.1.0'
|
||||
# freetype needs an explicit --build to know it's cross-compiling
|
||||
# disable png as freetype tries to use libpng-config, even when cross-compiling
|
||||
build 'git://git.savannah.gnu.org/freetype/freetype2.git' 'VER-2-10-1' "--build=$(cc -dumpmachine) --with-png=no"
|
||||
build 'https://gitlab.freedesktop.org/xorg//font/util.git' 'font-util-1.3.2'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libfontenc.git' 'libfontenc-1.1.4'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libXfont.git' 'libXfont2-2.0.3'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libXdmcp.git' 'libXdmcp-1.1.3'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libXfixes.git' 'libXfixes-5.0.3'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libxcb-util.git' '0.4.0'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libxcb-image.git' '0.4.0'
|
||||
build 'https://gitlab.freedesktop.org/xorg/lib/libxcb-wm.git' '0.4.1'
|
||||
|
||||
# workaround xcb_windefs.h leaking all Windows API types into X server build
|
||||
# (some of which clash which types defined by Xmd.h) XXX: This is a bit of a
|
||||
# hack, as it makes this header depend on xorgproto. Maybe an upstreamable
|
||||
# fix would involve a macro defined in the X server (XFree86Server?
|
||||
# XCB_NO_WINAPI?), which makes xcb_windefs.h wrap things like XWinsock.h
|
||||
# does???
|
||||
sed -i s#winsock2#X11/Xwinsock# /usr/${HOST}/include/xcb/xcb_windefs.h
|
||||
|
|
@ -6,8 +6,10 @@ set -o xtrace
|
|||
# Packages which are needed by this script, but not for the xserver build
|
||||
EPHEMERAL="
|
||||
libcairo2-dev
|
||||
libevdev-dev
|
||||
libexpat-dev
|
||||
libgles2-mesa-dev
|
||||
libinput-dev
|
||||
libxkbcommon-dev
|
||||
x11-utils
|
||||
x11-xserver-utils
|
||||
|
|
@ -27,9 +29,7 @@ apt-get install -y \
|
|||
build-essential \
|
||||
ca-certificates \
|
||||
ccache \
|
||||
dpkg-dev \
|
||||
flex \
|
||||
gcc-mingw-w64-i686 \
|
||||
git \
|
||||
libaudit-dev \
|
||||
libbsd-dev \
|
||||
|
|
@ -48,14 +48,12 @@ apt-get install -y \
|
|||
libgles2 \
|
||||
libglx-mesa0 \
|
||||
libinput10 \
|
||||
libinput-dev \
|
||||
libnvidia-egl-wayland-dev \
|
||||
libpango1.0-0 \
|
||||
libpango1.0-dev \
|
||||
libpciaccess-dev \
|
||||
libpixman-1-dev \
|
||||
libselinux1-dev \
|
||||
libspice-protocol-dev \
|
||||
libsystemd-dev \
|
||||
libtool \
|
||||
libudev-dev \
|
||||
|
|
@ -96,11 +94,9 @@ apt-get install -y \
|
|||
libxt-dev \
|
||||
libxtst-dev \
|
||||
libxv-dev \
|
||||
libz-mingw-w64-dev \
|
||||
linux-libc-dev/bullseye-backports \
|
||||
mesa-common-dev \
|
||||
meson \
|
||||
mingw-w64-tools \
|
||||
nettle-dev \
|
||||
pkg-config \
|
||||
python3-attr \
|
||||
|
|
@ -115,8 +111,6 @@ apt-get install -y \
|
|||
xtrans-dev \
|
||||
xutils-dev
|
||||
|
||||
.gitlab-ci/cross-prereqs-build.sh i686-w64-mingw32
|
||||
|
||||
cd /root
|
||||
|
||||
# Xwayland requires drm 2.4.116 for drmSyncobjEventfd
|
||||
|
|
@ -160,7 +154,7 @@ cd ..
|
|||
rm -rf wayland-protocols
|
||||
|
||||
# Install libdecor for Xwayland
|
||||
git clone https://gitlab.gnome.org/jadahl/libdecor.git --depth 1 --branch=0.1.0
|
||||
git clone https://gitlab.freedesktop.org/libdecor/libdecor.git --depth 1 --branch=0.1.1
|
||||
cd libdecor
|
||||
meson _build -D{demo,install_demo}=false
|
||||
ninja -C _build -j${FDO_CI_CONCURRENT:-4} install
|
||||
|
|
|
|||
27
.travis.yml
27
.travis.yml
|
|
@ -1,27 +0,0 @@
|
|||
language: c
|
||||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
branches:
|
||||
except:
|
||||
- /appveyor.*/
|
||||
|
||||
os: osx
|
||||
osx_image: xcode9.2
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: TOOL=meson
|
||||
- env: TOOL=autotools
|
||||
|
||||
install:
|
||||
- brew update
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache meson
|
||||
|
||||
script:
|
||||
- ./test/scripts/build-travis-osx.sh $TOOL
|
||||
- ccache -s
|
||||
|
||||
before_cache:
|
||||
- brew cleanup
|
||||
|
|
@ -73,7 +73,3 @@ libxserver_xext_vidmode = static_library('libxserver_xext_vidmode',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data(hdrs_xext, install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
|||
92
Xext/sync.c
92
Xext/sync.c
|
|
@ -200,8 +200,8 @@ SyncAddTriggerToSyncObject(SyncTrigger * pTrigger)
|
|||
return Success;
|
||||
}
|
||||
|
||||
if (!(pCur = malloc(sizeof(SyncTriggerList))))
|
||||
return BadAlloc;
|
||||
/* Failure is not an option, it's succeed or burst! */
|
||||
pCur = XNFalloc(sizeof(SyncTriggerList));
|
||||
|
||||
pCur->pTrigger = pTrigger;
|
||||
pCur->next = pTrigger->pSync->pTriglist;
|
||||
|
|
@ -330,11 +330,6 @@ SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
|
|||
client->errorValue = syncObject;
|
||||
return rc;
|
||||
}
|
||||
if (pSync != pTrigger->pSync) { /* new counter for trigger */
|
||||
SyncDeleteTriggerFromSyncObject(pTrigger);
|
||||
pTrigger->pSync = pSync;
|
||||
newSyncObject = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* if system counter, ask it what the current value is */
|
||||
|
|
@ -356,6 +351,24 @@ SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
|
|||
}
|
||||
}
|
||||
|
||||
if (changes & (XSyncCAValueType | XSyncCAValue)) {
|
||||
if (pTrigger->value_type == XSyncAbsolute)
|
||||
pTrigger->test_value = pTrigger->wait_value;
|
||||
else { /* relative */
|
||||
Bool overflow;
|
||||
|
||||
if (pCounter == NULL)
|
||||
return BadMatch;
|
||||
|
||||
overflow = checked_int64_add(&pTrigger->test_value,
|
||||
pCounter->value, pTrigger->wait_value);
|
||||
if (overflow) {
|
||||
client->errorValue = pTrigger->wait_value >> 32;
|
||||
return BadValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (changes & XSyncCATestType) {
|
||||
|
||||
if (pSync && SYNC_FENCE == pSync->type) {
|
||||
|
|
@ -384,21 +397,11 @@ SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
|
|||
}
|
||||
}
|
||||
|
||||
if (changes & (XSyncCAValueType | XSyncCAValue)) {
|
||||
if (pTrigger->value_type == XSyncAbsolute)
|
||||
pTrigger->test_value = pTrigger->wait_value;
|
||||
else { /* relative */
|
||||
Bool overflow;
|
||||
|
||||
if (pCounter == NULL)
|
||||
return BadMatch;
|
||||
|
||||
overflow = checked_int64_add(&pTrigger->test_value,
|
||||
pCounter->value, pTrigger->wait_value);
|
||||
if (overflow) {
|
||||
client->errorValue = pTrigger->wait_value >> 32;
|
||||
return BadValue;
|
||||
}
|
||||
if (changes & XSyncCACounter) {
|
||||
if (pSync != pTrigger->pSync) { /* new counter for trigger */
|
||||
SyncDeleteTriggerFromSyncObject(pTrigger);
|
||||
pTrigger->pSync = pSync;
|
||||
newSyncObject = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -406,8 +409,7 @@ SyncInitTrigger(ClientPtr client, SyncTrigger * pTrigger, XID syncObject,
|
|||
* a new counter on a trigger
|
||||
*/
|
||||
if (newSyncObject) {
|
||||
if ((rc = SyncAddTriggerToSyncObject(pTrigger)) != Success)
|
||||
return rc;
|
||||
SyncAddTriggerToSyncObject(pTrigger);
|
||||
}
|
||||
else if (pCounter && IsSystemCounter(pCounter)) {
|
||||
SyncComputeBracketValues(pCounter);
|
||||
|
|
@ -798,8 +800,14 @@ SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask,
|
|||
int status;
|
||||
XSyncCounter counter;
|
||||
Mask origmask = mask;
|
||||
SyncTrigger trigger;
|
||||
Bool select_events_changed = FALSE;
|
||||
Bool select_events_value = FALSE;
|
||||
int64_t delta;
|
||||
|
||||
counter = pAlarm->trigger.pSync ? pAlarm->trigger.pSync->id : None;
|
||||
trigger = pAlarm->trigger;
|
||||
delta = pAlarm->delta;
|
||||
counter = trigger.pSync ? trigger.pSync->id : None;
|
||||
|
||||
while (mask) {
|
||||
int index2 = lowbit(mask);
|
||||
|
|
@ -815,24 +823,24 @@ SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask,
|
|||
case XSyncCAValueType:
|
||||
mask &= ~XSyncCAValueType;
|
||||
/* sanity check in SyncInitTrigger */
|
||||
pAlarm->trigger.value_type = *values++;
|
||||
trigger.value_type = *values++;
|
||||
break;
|
||||
|
||||
case XSyncCAValue:
|
||||
mask &= ~XSyncCAValue;
|
||||
pAlarm->trigger.wait_value = ((int64_t)values[0] << 32) | values[1];
|
||||
trigger.wait_value = ((int64_t)values[0] << 32) | values[1];
|
||||
values += 2;
|
||||
break;
|
||||
|
||||
case XSyncCATestType:
|
||||
mask &= ~XSyncCATestType;
|
||||
/* sanity check in SyncInitTrigger */
|
||||
pAlarm->trigger.test_type = *values++;
|
||||
trigger.test_type = *values++;
|
||||
break;
|
||||
|
||||
case XSyncCADelta:
|
||||
mask &= ~XSyncCADelta;
|
||||
pAlarm->delta = ((int64_t)values[0] << 32) | values[1];
|
||||
delta = ((int64_t)values[0] << 32) | values[1];
|
||||
values += 2;
|
||||
break;
|
||||
|
||||
|
|
@ -842,10 +850,8 @@ SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask,
|
|||
client->errorValue = *values;
|
||||
return BadValue;
|
||||
}
|
||||
status = SyncEventSelectForAlarm(pAlarm, client,
|
||||
(Bool) (*values++));
|
||||
if (status != Success)
|
||||
return status;
|
||||
select_events_value = (Bool) (*values++);
|
||||
select_events_changed = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -854,25 +860,33 @@ SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm * pAlarm, Mask mask,
|
|||
}
|
||||
}
|
||||
|
||||
if (select_events_changed) {
|
||||
status = SyncEventSelectForAlarm(pAlarm, client, select_events_value);
|
||||
if (status != Success)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* "If the test-type is PositiveComparison or PositiveTransition
|
||||
* and delta is less than zero, or if the test-type is
|
||||
* NegativeComparison or NegativeTransition and delta is
|
||||
* greater than zero, a Match error is generated."
|
||||
*/
|
||||
if (origmask & (XSyncCADelta | XSyncCATestType)) {
|
||||
if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
|
||||
(pAlarm->trigger.test_type == XSyncPositiveTransition))
|
||||
&& pAlarm->delta < 0)
|
||||
if ((((trigger.test_type == XSyncPositiveComparison) ||
|
||||
(trigger.test_type == XSyncPositiveTransition))
|
||||
&& delta < 0)
|
||||
||
|
||||
(((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
|
||||
(pAlarm->trigger.test_type == XSyncNegativeTransition))
|
||||
&& pAlarm->delta > 0)
|
||||
(((trigger.test_type == XSyncNegativeComparison) ||
|
||||
(trigger.test_type == XSyncNegativeTransition))
|
||||
&& delta > 0)
|
||||
) {
|
||||
return BadMatch;
|
||||
}
|
||||
}
|
||||
|
||||
/* postpone this until now, when we're sure nothing else can go wrong */
|
||||
pAlarm->delta = delta;
|
||||
pAlarm->trigger = trigger;
|
||||
if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, RTCounter,
|
||||
origmask & XSyncCAAllTrigger)) != Success)
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ ProcXListInputDevices(ClientPtr client)
|
|||
};
|
||||
|
||||
/* allocate space for saving skip value */
|
||||
skip = calloc(sizeof(Bool), inputInfo.numDevices);
|
||||
skip = calloc(inputInfo.numDevices, sizeof(Bool));
|
||||
if (!skip)
|
||||
return BadAlloc;
|
||||
|
||||
|
|
|
|||
|
|
@ -129,14 +129,15 @@ static void FreePointerBarrierClient(struct PointerBarrierClient *c)
|
|||
|
||||
static struct PointerBarrierDevice *GetBarrierDevice(struct PointerBarrierClient *c, int deviceid)
|
||||
{
|
||||
struct PointerBarrierDevice *pbd = NULL;
|
||||
struct PointerBarrierDevice *p, *pbd = NULL;
|
||||
|
||||
xorg_list_for_each_entry(pbd, &c->per_device, entry) {
|
||||
if (pbd->deviceid == deviceid)
|
||||
xorg_list_for_each_entry(p, &c->per_device, entry) {
|
||||
if (p->deviceid == deviceid) {
|
||||
pbd = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BUG_WARN(!pbd);
|
||||
return pbd;
|
||||
}
|
||||
|
||||
|
|
@ -337,6 +338,9 @@ barrier_find_nearest(BarrierScreenPtr cs, DeviceIntPtr dev,
|
|||
double distance;
|
||||
|
||||
pbd = GetBarrierDevice(c, dev->id);
|
||||
if (!pbd)
|
||||
continue;
|
||||
|
||||
if (pbd->seen)
|
||||
continue;
|
||||
|
||||
|
|
@ -445,6 +449,9 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
|
|||
nearest = &c->barrier;
|
||||
|
||||
pbd = GetBarrierDevice(c, master->id);
|
||||
if (!pbd)
|
||||
continue;
|
||||
|
||||
new_sequence = !pbd->hit;
|
||||
|
||||
pbd->seen = TRUE;
|
||||
|
|
@ -485,6 +492,9 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
|
|||
int flags = 0;
|
||||
|
||||
pbd = GetBarrierDevice(c, master->id);
|
||||
if (!pbd)
|
||||
continue;
|
||||
|
||||
pbd->seen = FALSE;
|
||||
if (!pbd->hit)
|
||||
continue;
|
||||
|
|
@ -679,6 +689,9 @@ BarrierFreeBarrier(void *data, XID id)
|
|||
continue;
|
||||
|
||||
pbd = GetBarrierDevice(c, dev->id);
|
||||
if (!pbd)
|
||||
continue;
|
||||
|
||||
if (!pbd->hit)
|
||||
continue;
|
||||
|
||||
|
|
@ -738,6 +751,8 @@ static void remove_master_func(void *res, XID id, void *devid)
|
|||
barrier = container_of(b, struct PointerBarrierClient, barrier);
|
||||
|
||||
pbd = GetBarrierDevice(barrier, *deviceid);
|
||||
if (!pbd)
|
||||
return;
|
||||
|
||||
if (pbd->hit) {
|
||||
BarrierEvent ev = {
|
||||
|
|
@ -903,6 +918,10 @@ ProcXIBarrierReleasePointer(ClientPtr client)
|
|||
barrier = container_of(b, struct PointerBarrierClient, barrier);
|
||||
|
||||
pbd = GetBarrierDevice(barrier, dev->id);
|
||||
if (!pbd) {
|
||||
client->errorValue = dev->id;
|
||||
return BadDevice;
|
||||
}
|
||||
|
||||
if (pbd->barrier_event_id == event_id)
|
||||
pbd->release_event_id = event_id;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "exevents.h"
|
||||
#include "exglobals.h"
|
||||
#include "geext.h"
|
||||
#include "misc.h"
|
||||
#include "xace.h"
|
||||
#include "xiquerydevice.h" /* for GetDeviceUse */
|
||||
|
||||
|
|
@ -215,46 +216,68 @@ disable_clientpointer(DeviceIntPtr dev)
|
|||
}
|
||||
}
|
||||
|
||||
static DeviceIntPtr
|
||||
find_disabled_master(int type)
|
||||
{
|
||||
DeviceIntPtr dev;
|
||||
|
||||
/* Once a master device is disabled it loses the pairing, so returning the first
|
||||
* match is good enough */
|
||||
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
|
||||
if (dev->type == type)
|
||||
return dev;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
remove_master(ClientPtr client, xXIRemoveMasterInfo * r, int flags[MAXDEVICES])
|
||||
{
|
||||
DeviceIntPtr ptr, keybd, XTestptr, XTestkeybd;
|
||||
DeviceIntPtr dev, ptr, keybd, XTestptr, XTestkeybd;
|
||||
int rc = Success;
|
||||
|
||||
if (r->return_mode != XIAttachToMaster && r->return_mode != XIFloating)
|
||||
return BadValue;
|
||||
|
||||
rc = dixLookupDevice(&ptr, r->deviceid, client, DixDestroyAccess);
|
||||
rc = dixLookupDevice(&dev, r->deviceid, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
if (!IsMaster(ptr)) {
|
||||
if (!IsMaster(dev)) {
|
||||
client->errorValue = r->deviceid;
|
||||
rc = BadDevice;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* XXX: For now, don't allow removal of VCP, VCK */
|
||||
if (ptr == inputInfo.pointer ||ptr == inputInfo.keyboard) {
|
||||
if (dev == inputInfo.pointer || dev == inputInfo.keyboard) {
|
||||
rc = BadDevice;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
ptr = GetMaster(ptr, MASTER_POINTER);
|
||||
if ((ptr = GetMaster(dev, MASTER_POINTER)) == NULL)
|
||||
ptr = find_disabled_master(MASTER_POINTER);
|
||||
BUG_RETURN_VAL(ptr == NULL, BadDevice);
|
||||
rc = dixLookupDevice(&ptr, ptr->id, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
keybd = GetMaster(ptr, MASTER_KEYBOARD);
|
||||
|
||||
if ((keybd = GetMaster(dev, MASTER_KEYBOARD)) == NULL)
|
||||
keybd = find_disabled_master(MASTER_KEYBOARD);
|
||||
BUG_RETURN_VAL(keybd == NULL, BadDevice);
|
||||
rc = dixLookupDevice(&keybd, keybd->id, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
XTestptr = GetXTestDevice(ptr);
|
||||
BUG_RETURN_VAL(XTestptr == NULL, BadDevice);
|
||||
rc = dixLookupDevice(&XTestptr, XTestptr->id, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
XTestkeybd = GetXTestDevice(keybd);
|
||||
BUG_RETURN_VAL(XTestkeybd == NULL, BadDevice);
|
||||
rc = dixLookupDevice(&XTestkeybd, XTestkeybd->id, client, DixDestroyAccess);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ ProcXIGrabDevice(ClientPtr client)
|
|||
if (ret != Success)
|
||||
return ret;
|
||||
|
||||
if (!dev->enabled)
|
||||
return AlreadyGrabbed;
|
||||
|
||||
if (!IsMaster(dev))
|
||||
stuff->paired_device_mode = GrabModeAsync;
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ ProcXIQueryDevice(ClientPtr client)
|
|||
len += SizeDeviceInfo(dev);
|
||||
}
|
||||
else {
|
||||
skip = calloc(sizeof(Bool), inputInfo.numDevices);
|
||||
skip = calloc(inputInfo.numDevices, sizeof(Bool));
|
||||
if (!skip)
|
||||
return BadAlloc;
|
||||
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
|
|||
CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen);
|
||||
WindowPtr pLayerWin;
|
||||
Bool anyMarked = FALSE;
|
||||
int status = Success;
|
||||
|
||||
if (pWin == cs->pOverlayWin) {
|
||||
return Success;
|
||||
|
|
@ -218,13 +219,13 @@ compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update)
|
|||
|
||||
if (!compCheckRedirect(pWin)) {
|
||||
FreeResource(ccw->id, RT_NONE);
|
||||
return BadAlloc;
|
||||
status = BadAlloc;
|
||||
}
|
||||
|
||||
if (anyMarked)
|
||||
compHandleMarkedWindows(pWin, pLayerWin);
|
||||
|
||||
return Success;
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -605,9 +606,12 @@ compAllocPixmap(WindowPtr pWin)
|
|||
int h = pWin->drawable.height + (bw << 1);
|
||||
PixmapPtr pPixmap = compNewPixmap(pWin, x, y, w, h);
|
||||
CompWindowPtr cw = GetCompWindow(pWin);
|
||||
Bool status;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
if (!pPixmap) {
|
||||
status = FALSE;
|
||||
goto out;
|
||||
}
|
||||
if (cw->update == CompositeRedirectAutomatic)
|
||||
pWin->redirectDraw = RedirectDrawAutomatic;
|
||||
else
|
||||
|
|
@ -621,14 +625,16 @@ compAllocPixmap(WindowPtr pWin)
|
|||
DamageRegister(&pWin->drawable, cw->damage);
|
||||
cw->damageRegistered = TRUE;
|
||||
}
|
||||
status = TRUE;
|
||||
|
||||
out:
|
||||
/* Make sure our borderClip is up to date */
|
||||
RegionUninit(&cw->borderClip);
|
||||
RegionCopy(&cw->borderClip, &pWin->borderClip);
|
||||
cw->borderClipX = pWin->drawable.x;
|
||||
cw->borderClipY = pWin->drawable.y;
|
||||
|
||||
return TRUE;
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -15,7 +15,3 @@ libxserver_composite = static_library('libxserver_composite',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data(hdrs_composite, install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
# Collection of quirks and blacklist/whitelists for specific devices.
|
||||
|
||||
|
||||
# Accelerometer device, posts data through ABS_X/ABS_Y, making X unusable
|
||||
# http://bugs.freedesktop.org/show_bug.cgi?id=22442
|
||||
Section "InputClass"
|
||||
Identifier "ThinkPad HDAPS accelerometer blacklist"
|
||||
MatchProduct "ThinkPad HDAPS accelerometer data"
|
||||
Option "Ignore" "on"
|
||||
EndSection
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=523914
|
||||
# Mouse does not move in PV Xen guest
|
||||
# Explicitly tell evdev to not ignore the absolute axes.
|
||||
Section "InputClass"
|
||||
Identifier "Xen Virtual Pointer axis blacklist"
|
||||
MatchProduct "Xen Virtual Pointer"
|
||||
Option "IgnoreAbsoluteAxes" "off"
|
||||
Option "IgnoreRelativeAxes" "off"
|
||||
EndSection
|
||||
|
||||
# https://bugs.freedesktop.org/show_bug.cgi?id=55867
|
||||
# Bug 55867 - Doesn't know how to tag XI_TRACKBALL
|
||||
Section "InputClass"
|
||||
Identifier "Tag trackballs as XI_TRACKBALL"
|
||||
MatchProduct "trackball"
|
||||
MatchDriver "evdev"
|
||||
Option "TypeName" "TRACKBALL"
|
||||
EndSection
|
||||
|
||||
# https://bugs.freedesktop.org/show_bug.cgi?id=62831
|
||||
# Bug 62831 - Mionix Naos 5000 mouse detected incorrectly
|
||||
Section "InputClass"
|
||||
Identifier "Tag Mionix Naos 5000 mouse XI_MOUSE"
|
||||
MatchProduct "La-VIEW Technology Naos 5000 Mouse"
|
||||
MatchDriver "evdev"
|
||||
Option "TypeName" "MOUSE"
|
||||
EndSection
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2152414
|
||||
# Xorg server does not correctly select the DCP for the display without
|
||||
# a quirk on Apple Silicon
|
||||
Section "OutputClass"
|
||||
Identifier "appledrm"
|
||||
MatchDriver "apple"
|
||||
Driver "modesetting"
|
||||
Option "PrimaryGPU" "true"
|
||||
EndSection
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "input.h"
|
||||
#include "list.h"
|
||||
|
||||
void remove_devices(const char *backend, const char *config_info);
|
||||
BOOL device_is_duplicate(const char *config_info);
|
||||
|
||||
#ifdef CONFIG_UDEV
|
||||
int config_udev_pre_init(void);
|
||||
int config_udev_init(void);
|
||||
void config_udev_fini(void);
|
||||
void config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback);
|
||||
#elif defined(CONFIG_HAL)
|
||||
int config_hal_init(void);
|
||||
void config_hal_fini(void);
|
||||
#elif defined(CONFIG_WSCONS)
|
||||
int config_wscons_init(void);
|
||||
void config_wscons_fini(void);
|
||||
#endif
|
||||
151
config/config.c
151
config/config.c
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include "os.h"
|
||||
#include "inputstr.h"
|
||||
#include "hotplug.h"
|
||||
#include "config-backends.h"
|
||||
#include "systemd-logind.h"
|
||||
|
||||
void
|
||||
config_pre_init(void)
|
||||
{
|
||||
#ifdef CONFIG_UDEV
|
||||
if (!config_udev_pre_init())
|
||||
ErrorF("[config] failed to pre-init udev\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
config_init(void)
|
||||
{
|
||||
#ifdef CONFIG_UDEV
|
||||
if (!config_udev_init())
|
||||
ErrorF("[config] failed to initialise udev\n");
|
||||
#elif defined(CONFIG_HAL)
|
||||
if (!config_hal_init())
|
||||
ErrorF("[config] failed to initialise HAL\n");
|
||||
#elif defined(CONFIG_WSCONS)
|
||||
if (!config_wscons_init())
|
||||
ErrorF("[config] failed to initialise wscons\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
config_fini(void)
|
||||
{
|
||||
#if defined(CONFIG_UDEV)
|
||||
config_udev_fini();
|
||||
#elif defined(CONFIG_HAL)
|
||||
config_hal_fini();
|
||||
#elif defined(CONFIG_WSCONS)
|
||||
config_wscons_fini();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
config_odev_probe(config_odev_probe_proc_ptr probe_callback)
|
||||
{
|
||||
#if defined(CONFIG_UDEV_KMS)
|
||||
config_udev_odev_probe(probe_callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
remove_device(const char *backend, DeviceIntPtr dev)
|
||||
{
|
||||
/* this only gets called for devices that have already been added */
|
||||
LogMessage(X_INFO, "config/%s: removing device %s\n", backend, dev->name);
|
||||
|
||||
/* Call PIE here so we don't try to dereference a device that's
|
||||
* already been removed. */
|
||||
input_lock();
|
||||
ProcessInputEvents();
|
||||
DeleteInputDeviceRequest(dev);
|
||||
input_unlock();
|
||||
}
|
||||
|
||||
void
|
||||
remove_devices(const char *backend, const char *config_info)
|
||||
{
|
||||
DeviceIntPtr dev, next;
|
||||
|
||||
for (dev = inputInfo.devices; dev; dev = next) {
|
||||
next = dev->next;
|
||||
if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
|
||||
remove_device(backend, dev);
|
||||
}
|
||||
for (dev = inputInfo.off_devices; dev; dev = next) {
|
||||
next = dev->next;
|
||||
if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
|
||||
remove_device(backend, dev);
|
||||
}
|
||||
|
||||
RemoveInputDeviceTraces(config_info);
|
||||
}
|
||||
|
||||
BOOL
|
||||
device_is_duplicate(const char *config_info)
|
||||
{
|
||||
DeviceIntPtr dev;
|
||||
|
||||
for (dev = inputInfo.devices; dev; dev = dev->next) {
|
||||
if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
|
||||
if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct OdevAttributes *
|
||||
config_odev_allocate_attributes(void)
|
||||
{
|
||||
struct OdevAttributes *attribs =
|
||||
xnfcalloc(1, sizeof (struct OdevAttributes));
|
||||
attribs->fd = -1;
|
||||
return attribs;
|
||||
}
|
||||
|
||||
void
|
||||
config_odev_free_attributes(struct OdevAttributes *attribs)
|
||||
{
|
||||
if (attribs->fd != -1)
|
||||
systemd_logind_release_fd(attribs->major, attribs->minor, attribs->fd);
|
||||
free(attribs->path);
|
||||
free(attribs->syspath);
|
||||
free(attribs->busid);
|
||||
free(attribs->driver);
|
||||
free(attribs);
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
D-BUS Configuration API v2
|
||||
----------------------------
|
||||
|
||||
The X server will register the bus name org.x.config.displayN, and the
|
||||
object /org/x/config/N, where N is the display number.
|
||||
|
||||
Currently only hotplugging of input devices is supported.
|
||||
|
||||
org.x.config.input:
|
||||
org.x.config.input.version:
|
||||
Returns one unsigned int32, which is the API version.
|
||||
|
||||
org.x.config.input.add:
|
||||
Takes an argument of key/value option pairs in arrays, e.g.:
|
||||
[ss][ss][ss][ss]
|
||||
is the signature for four options. These options will be passed
|
||||
to the input driver as with any others.
|
||||
Option names beginning with _ are not allowed; they are reserved
|
||||
for internal use.
|
||||
|
||||
Returns a number of signed int32s. Positive integers are the
|
||||
device IDs of new devices; negative numbers are X error codes,
|
||||
as defined in X.h. BadMatch will be returned if the options
|
||||
given do not match any device. BadValue is returned for a malformed
|
||||
message. (Example: 8 is new device ID 8; -8 is BadMatch.)
|
||||
|
||||
Notably, BadAlloc is never returned: the server internally signals
|
||||
to D-BUS that the attempt failed for lack of memory.
|
||||
|
||||
org.x.config.input.remove:
|
||||
Takes one uint32 argument, which is the device ID to remove, i.e.:
|
||||
u
|
||||
is the signature.
|
||||
|
||||
Returns one signed int32 which represents an X status as defined in
|
||||
X.h. See org.x.config.input.add. Error codes are negative numbers.
|
||||
|
||||
org.x.config.input.listDevices:
|
||||
Lists the currently active devices. No argument.
|
||||
Return value is sequence of [<id> <name>] [<id> <name>] ..., i.e. [us].
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "dix.h"
|
||||
#include "os.h"
|
||||
#include "dbus-core.h"
|
||||
|
||||
/* How often to attempt reconnecting when we get booted off the bus. */
|
||||
#define RECONNECT_DELAY (10 * 1000) /* in ms */
|
||||
|
||||
struct dbus_core_info {
|
||||
int fd;
|
||||
DBusConnection *connection;
|
||||
OsTimerPtr timer;
|
||||
struct dbus_core_hook *hooks;
|
||||
};
|
||||
static struct dbus_core_info bus_info = { .fd = -1 };
|
||||
|
||||
static CARD32 reconnect_timer(OsTimerPtr timer, CARD32 time, void *arg);
|
||||
|
||||
static void
|
||||
socket_handler(int fd, int ready, void *data)
|
||||
{
|
||||
struct dbus_core_info *info = data;
|
||||
|
||||
if (info->connection) {
|
||||
do {
|
||||
dbus_connection_read_write_dispatch(info->connection, 0);
|
||||
} while (info->connection &&
|
||||
dbus_connection_get_is_connected(info->connection) &&
|
||||
dbus_connection_get_dispatch_status(info->connection) ==
|
||||
DBUS_DISPATCH_DATA_REMAINS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect (if we haven't already been forcefully disconnected), clean up
|
||||
* after ourselves, and call all registered disconnect hooks.
|
||||
*/
|
||||
static void
|
||||
teardown(void)
|
||||
{
|
||||
struct dbus_core_hook *hook;
|
||||
|
||||
if (bus_info.timer) {
|
||||
TimerFree(bus_info.timer);
|
||||
bus_info.timer = NULL;
|
||||
}
|
||||
|
||||
/* We should really have pre-disconnect hooks and run them here, for
|
||||
* completeness. But then it gets awkward, given that you can't
|
||||
* guarantee that they'll be called ... */
|
||||
if (bus_info.connection)
|
||||
dbus_connection_unref(bus_info.connection);
|
||||
|
||||
if (bus_info.fd != -1)
|
||||
RemoveNotifyFd(bus_info.fd);
|
||||
bus_info.fd = -1;
|
||||
bus_info.connection = NULL;
|
||||
|
||||
for (hook = bus_info.hooks; hook; hook = hook->next) {
|
||||
if (hook->disconnect)
|
||||
hook->disconnect(hook->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a filter, which only handles the disconnected signal, which
|
||||
* doesn't go to the normal message handling function. This takes
|
||||
* precedence over the message handling function, so have have to be
|
||||
* careful to ignore anything we don't want to deal with here.
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
message_filter(DBusConnection * connection, DBusMessage * message, void *data)
|
||||
{
|
||||
/* If we get disconnected, then take everything down, and attempt to
|
||||
* reconnect immediately (assuming it's just a restart). The
|
||||
* connection isn't valid at this point, so throw it out immediately. */
|
||||
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
|
||||
DebugF("[dbus-core] disconnected from bus\n");
|
||||
bus_info.connection = NULL;
|
||||
teardown();
|
||||
|
||||
if (bus_info.timer)
|
||||
TimerFree(bus_info.timer);
|
||||
bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to connect to the system bus, and set a filter to deal with
|
||||
* disconnection (see message_filter above).
|
||||
*
|
||||
* @return 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
connect_to_bus(void)
|
||||
{
|
||||
DBusError error;
|
||||
struct dbus_core_hook *hook;
|
||||
|
||||
dbus_error_init(&error);
|
||||
bus_info.connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (!bus_info.connection || dbus_error_is_set(&error)) {
|
||||
LogMessage(X_ERROR, "dbus-core: error connecting to system bus: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
goto err_begin;
|
||||
}
|
||||
|
||||
/* Thankyou. Really, thankyou. */
|
||||
dbus_connection_set_exit_on_disconnect(bus_info.connection, FALSE);
|
||||
|
||||
if (!dbus_connection_get_unix_fd(bus_info.connection, &bus_info.fd)) {
|
||||
ErrorF("[dbus-core] couldn't get fd for system bus\n");
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
if (!dbus_connection_add_filter(bus_info.connection, message_filter,
|
||||
&bus_info, NULL)) {
|
||||
ErrorF("[dbus-core] couldn't add filter: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
dbus_error_free(&error);
|
||||
SetNotifyFd(bus_info.fd, socket_handler, X_NOTIFY_READ, &bus_info);
|
||||
|
||||
for (hook = bus_info.hooks; hook; hook = hook->next) {
|
||||
if (hook->connect)
|
||||
hook->connect(bus_info.connection, hook->data);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err_fd:
|
||||
bus_info.fd = -1;
|
||||
err_unref:
|
||||
dbus_connection_unref(bus_info.connection);
|
||||
bus_info.connection = NULL;
|
||||
err_begin:
|
||||
dbus_error_free(&error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CARD32
|
||||
reconnect_timer(OsTimerPtr timer, CARD32 time, void *arg)
|
||||
{
|
||||
if (connect_to_bus()) {
|
||||
TimerFree(bus_info.timer);
|
||||
bus_info.timer = NULL;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return RECONNECT_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dbus_core_add_hook(struct dbus_core_hook *hook)
|
||||
{
|
||||
struct dbus_core_hook **prev;
|
||||
|
||||
for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next);
|
||||
|
||||
hook->next = NULL;
|
||||
*prev = hook;
|
||||
|
||||
/* If we're already connected, call the connect hook. */
|
||||
if (bus_info.connection)
|
||||
hook->connect(bus_info.connection, hook->data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dbus_core_remove_hook(struct dbus_core_hook *hook)
|
||||
{
|
||||
struct dbus_core_hook **prev;
|
||||
|
||||
for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next) {
|
||||
if (*prev == hook) {
|
||||
*prev = hook->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dbus_core_init(void)
|
||||
{
|
||||
memset(&bus_info, 0, sizeof(bus_info));
|
||||
bus_info.fd = -1;
|
||||
bus_info.hooks = NULL;
|
||||
if (!connect_to_bus())
|
||||
bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dbus_core_fini(void)
|
||||
{
|
||||
teardown();
|
||||
}
|
||||
|
|
@ -1,199 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Convert xorg keys from hal FDIs files to xorg.conf InputClass sections.
|
||||
# Modified from Martin Pitt's original fdi2mpi.py script:
|
||||
# http://cgit.freedesktop.org/media-player-info/tree/tools/fdi2mpi.py
|
||||
#
|
||||
# (C) 2010 Dan Nicholson
|
||||
# (C) 2009 Canonical Ltd.
|
||||
# Author: Dan Nicholson <dbn.lists@gmail.com>
|
||||
# Author: Martin Pitt <martin.pitt@ubuntu.com>
|
||||
#
|
||||
# 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
|
||||
# fur- nished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice 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,
|
||||
# FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||
# NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import sys, xml.dom.minidom
|
||||
|
||||
# dict converting <match> tags to Match* entries
|
||||
match_table = {
|
||||
'info.product': 'MatchProduct',
|
||||
'input.product': 'MatchProduct',
|
||||
'info.vendor': 'MatchVendor',
|
||||
'input.vendor': 'MatchVendor',
|
||||
'info.device': 'MatchDevicePath',
|
||||
'linux.device_file': 'MatchDevicePath',
|
||||
'/org/freedesktop/Hal/devices/computer:system.kernel.name': 'MatchOS',
|
||||
'@info.parent:pnp.id': 'MatchPnPID',
|
||||
}
|
||||
|
||||
# dict converting info.capabilities list to Match* entries
|
||||
cap_match_table = {
|
||||
'input.keys': 'MatchIsKeyboard',
|
||||
'input.keyboard': 'MatchIsKeyboard',
|
||||
'input.keypad': 'MatchIsKeyboard',
|
||||
'input.mouse': 'MatchIsPointer',
|
||||
'input.joystick': 'MatchIsJoystick',
|
||||
'input.tablet': 'MatchIsTablet',
|
||||
'input.touchpad': 'MatchIsTouchpad',
|
||||
'input.touchscreen': 'MatchIsTouchscreen',
|
||||
}
|
||||
|
||||
def device_glob(path):
|
||||
'''Convert a contains device path to a glob entry'''
|
||||
if path[0] != '/':
|
||||
path = '*' + path
|
||||
return path + '*'
|
||||
|
||||
def parse_match(node):
|
||||
'''Parse a <match> tag to a tuple with InputClass values'''
|
||||
match = None
|
||||
value = None
|
||||
booltype = False
|
||||
|
||||
# see what type of key we have
|
||||
if node.attributes.has_key('key'):
|
||||
key = node.attributes['key'].nodeValue
|
||||
if key in match_table:
|
||||
match = match_table[key]
|
||||
elif key == 'info.capabilities':
|
||||
booltype = True
|
||||
|
||||
# bail out now if it's unrecognized
|
||||
if not match and not booltype:
|
||||
return (match, value)
|
||||
|
||||
if node.attributes.has_key('string'):
|
||||
value = node.attributes['string'].nodeValue
|
||||
elif node.attributes.has_key('contains'):
|
||||
value = node.attributes['contains'].nodeValue
|
||||
if match == 'MatchDevicePath':
|
||||
value = device_glob(value)
|
||||
elif booltype and value in cap_match_table:
|
||||
match = cap_match_table[value]
|
||||
value = 'yes'
|
||||
elif node.attributes.has_key('string_outof'):
|
||||
value = node.attributes['string_outof'].nodeValue.replace(';','|')
|
||||
elif node.attributes.has_key('contains_outof'):
|
||||
all_values = node.attributes['contains_outof'].nodeValue.split(';')
|
||||
for v in all_values:
|
||||
if match == 'MatchDevicePath':
|
||||
v = device_glob(v)
|
||||
elif match == 'MatchPnPID' and len(v) < 7:
|
||||
v += '*'
|
||||
if value:
|
||||
value += '|' + v
|
||||
else:
|
||||
value = v
|
||||
|
||||
return (match, value)
|
||||
|
||||
def parse_options(node):
|
||||
'''Parse the x11_* options and return InputClass entries'''
|
||||
driver = ''
|
||||
ignore = False
|
||||
options = []
|
||||
for n in node.childNodes:
|
||||
if n.nodeType != xml.dom.minidom.Node.ELEMENT_NODE:
|
||||
continue
|
||||
|
||||
tag = n.tagName
|
||||
key = n.attributes['key'].nodeValue
|
||||
value = ''
|
||||
|
||||
if n.hasChildNodes():
|
||||
content_node = n.childNodes[0]
|
||||
assert content_node.nodeType == xml.dom.Node.TEXT_NODE
|
||||
value = content_node.nodeValue
|
||||
|
||||
if tag == 'match':
|
||||
continue
|
||||
assert tag in ('addset', 'merge', 'append', 'remove')
|
||||
|
||||
if tag == 'remove' and key == 'input.x11_driver':
|
||||
ignore = True
|
||||
elif key == 'input.x11_driver':
|
||||
driver = value
|
||||
elif key.startswith('input.x11_options.'):
|
||||
option = key.split('.', 2)[2]
|
||||
options.append((option, value))
|
||||
|
||||
return (driver, ignore, options)
|
||||
|
||||
def is_match_node(node):
|
||||
'''Check if a node is a <match> element'''
|
||||
return node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and \
|
||||
node.tagName == 'match'
|
||||
|
||||
def parse_all_matches(node):
|
||||
'''Parse a x11 match tag and any parents that don't supply their
|
||||
own options'''
|
||||
matches = []
|
||||
|
||||
while True:
|
||||
(key, value) = parse_match(node)
|
||||
if key and value:
|
||||
matches.append((key, value))
|
||||
|
||||
# walk up to a parent match node
|
||||
node = node.parentNode
|
||||
if node is None or not is_match_node(node):
|
||||
break
|
||||
|
||||
# leave if there other options at this level
|
||||
children = set([n.tagName for n in node.childNodes
|
||||
if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE])
|
||||
if children & set(['addset', 'merge', 'append']):
|
||||
break
|
||||
|
||||
return matches
|
||||
|
||||
# stupid counter to give "unique" rule names
|
||||
num_sections = 1
|
||||
def print_section(matches, driver, ignore, options):
|
||||
'''Print a valid InputClass section to stdout'''
|
||||
global num_sections
|
||||
print 'Section "InputClass"'
|
||||
print '\tIdentifier "Converted Class %d"' % num_sections
|
||||
num_sections += 1
|
||||
for m, v in matches:
|
||||
print '\t%s "%s"' % (m, v)
|
||||
if driver:
|
||||
print '\tDriver "%s"' % driver
|
||||
if ignore:
|
||||
print '\tOption "Ignore" "yes"'
|
||||
for o, v in options:
|
||||
print '\tOption "%s" "%s"' % (o, v)
|
||||
print 'EndSection'
|
||||
|
||||
def parse_fdi(fdi):
|
||||
'''Parse x11 matches from fdi'''
|
||||
# find all <match> leaf nodes
|
||||
num = 0
|
||||
for match_node in fdi.getElementsByTagName('match'):
|
||||
# see if there are any options at this level
|
||||
(driver, ignore, options) = parse_options(match_node)
|
||||
if not driver and not ignore and not options:
|
||||
continue
|
||||
|
||||
matches = parse_all_matches(match_node)
|
||||
if num > 0:
|
||||
print
|
||||
print_section(matches, driver, ignore, options)
|
||||
num += 1
|
||||
|
||||
for f in sys.argv[1:]:
|
||||
parse_fdi(xml.dom.minidom.parse(f))
|
||||
675
config/hal.c
675
config/hal.c
|
|
@ -1,675 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2007 Daniel Stone
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <hal/libhal.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "dbus-core.h"
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
#include "hotplug.h"
|
||||
#include "config-backends.h"
|
||||
#include "os.h"
|
||||
|
||||
#define LIBHAL_PROP_KEY "input.x11_options."
|
||||
#define LIBHAL_XKB_PROP_KEY "input.xkb."
|
||||
|
||||
struct config_hal_info {
|
||||
DBusConnection *system_bus;
|
||||
LibHalContext *hal_ctx;
|
||||
};
|
||||
|
||||
/* Used for special handling of xkb options. */
|
||||
struct xkb_options {
|
||||
char *layout;
|
||||
char *model;
|
||||
char *rules;
|
||||
char *variant;
|
||||
char *options;
|
||||
};
|
||||
|
||||
static void
|
||||
device_removed(LibHalContext * ctx, const char *udi)
|
||||
{
|
||||
char *value;
|
||||
|
||||
if (asprintf(&value, "hal:%s", udi) == -1)
|
||||
return;
|
||||
|
||||
remove_devices("hal", value);
|
||||
|
||||
free(value);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_prop_string(LibHalContext * hal_ctx, const char *udi, const char *name)
|
||||
{
|
||||
char *prop, *ret;
|
||||
|
||||
prop = libhal_device_get_property_string(hal_ctx, udi, name, NULL);
|
||||
LogMessageVerb(X_INFO, 10, "config/hal: getting %s on %s returned %s\n",
|
||||
name, udi, prop ? prop : "(null)");
|
||||
if (prop) {
|
||||
ret = strdup(prop);
|
||||
libhal_free_string(prop);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_prop_string_array(LibHalContext * hal_ctx, const char *udi,
|
||||
const char *prop)
|
||||
{
|
||||
char **props, *ret, *str;
|
||||
int i, len = 0;
|
||||
|
||||
props = libhal_device_get_property_strlist(hal_ctx, udi, prop, NULL);
|
||||
if (props) {
|
||||
for (i = 0; props[i]; i++)
|
||||
len += strlen(props[i]);
|
||||
|
||||
ret = calloc(sizeof(char), len + i); /* i - 1 commas, 1 NULL */
|
||||
if (!ret) {
|
||||
libhal_free_string_array(props);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = ret;
|
||||
for (i = 0; props[i]; i++) {
|
||||
strcpy(str, props[i]);
|
||||
str += strlen(props[i]);
|
||||
*str++ = ',';
|
||||
}
|
||||
*(str - 1) = '\0';
|
||||
|
||||
libhal_free_string_array(props);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
device_added(LibHalContext * hal_ctx, const char *udi)
|
||||
{
|
||||
char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL;
|
||||
char *hal_tags, *parent;
|
||||
InputOption *input_options = NULL;
|
||||
InputAttributes attrs = { 0 };
|
||||
DeviceIntPtr dev = NULL;
|
||||
DBusError error;
|
||||
struct xkb_options xkb_opts = { 0 };
|
||||
int rc;
|
||||
|
||||
LibHalPropertySet *set = NULL;
|
||||
LibHalPropertySetIterator set_iter;
|
||||
char *psi_key = NULL, *tmp_val;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
driver = get_prop_string(hal_ctx, udi, "input.x11_driver");
|
||||
if (!driver) {
|
||||
/* verbose, don't tell the user unless they _want_ to see it */
|
||||
LogMessageVerb(X_INFO, 7,
|
||||
"config/hal: no driver specified for device %s\n", udi);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
path = get_prop_string(hal_ctx, udi, "input.device");
|
||||
if (!path) {
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: no driver or path specified for %s\n", udi);
|
||||
goto unwind;
|
||||
}
|
||||
attrs.device = strdup(path);
|
||||
|
||||
name = get_prop_string(hal_ctx, udi, "info.product");
|
||||
if (!name)
|
||||
name = strdup("(unnamed)");
|
||||
else
|
||||
attrs.product = strdup(name);
|
||||
|
||||
attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor");
|
||||
hal_tags = get_prop_string(hal_ctx, udi, "input.tags");
|
||||
attrs.tags = xstrtokenize(hal_tags, ",");
|
||||
free(hal_tags);
|
||||
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL))
|
||||
attrs.flags |= ATTR_KEY | ATTR_KEYBOARD;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.mouse", NULL))
|
||||
attrs.flags |= ATTR_POINTER;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.joystick", NULL))
|
||||
attrs.flags |= ATTR_JOYSTICK;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.tablet", NULL))
|
||||
attrs.flags |= ATTR_TABLET;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.tablet_pad", NULL))
|
||||
attrs.flags |= ATTR_TABLET_PAD;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.touchpad", NULL))
|
||||
attrs.flags |= ATTR_TOUCHPAD;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL))
|
||||
attrs.flags |= ATTR_TOUCHSCREEN;
|
||||
|
||||
parent = get_prop_string(hal_ctx, udi, "info.parent");
|
||||
if (parent) {
|
||||
int usb_vendor, usb_product;
|
||||
char *old_parent;
|
||||
|
||||
/* construct USB ID in lowercase - "0000:ffff" */
|
||||
usb_vendor = libhal_device_get_property_int(hal_ctx, parent,
|
||||
"usb.vendor_id", NULL);
|
||||
LogMessageVerb(X_INFO, 10,
|
||||
"config/hal: getting usb.vendor_id on %s "
|
||||
"returned %04x\n", parent, usb_vendor);
|
||||
usb_product = libhal_device_get_property_int(hal_ctx, parent,
|
||||
"usb.product_id", NULL);
|
||||
LogMessageVerb(X_INFO, 10,
|
||||
"config/hal: getting usb.product_id on %s "
|
||||
"returned %04x\n", parent, usb_product);
|
||||
if (usb_vendor && usb_product)
|
||||
if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_product)
|
||||
== -1)
|
||||
attrs.usb_id = NULL;
|
||||
|
||||
attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
|
||||
old_parent = parent;
|
||||
|
||||
while (!attrs.pnp_id &&
|
||||
(parent = get_prop_string(hal_ctx, parent, "info.parent"))) {
|
||||
attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
|
||||
|
||||
free(old_parent);
|
||||
old_parent = parent;
|
||||
}
|
||||
|
||||
free(old_parent);
|
||||
}
|
||||
|
||||
input_options = input_option_new(NULL, "_source", "server/hal");
|
||||
if (!input_options) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't allocate first key/value pair\n");
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* most drivers use device.. not path. evdev uses both however, but the
|
||||
* path version isn't documented apparently. support both for now. */
|
||||
input_options = input_option_new(input_options, "path", path);
|
||||
input_options = input_option_new(input_options, "device", path);
|
||||
|
||||
input_options = input_option_new(input_options, "driver", driver);
|
||||
input_options = input_option_new(input_options, "name", name);
|
||||
|
||||
if (asprintf(&config_info, "hal:%s", udi) == -1) {
|
||||
config_info = NULL;
|
||||
LogMessage(X_ERROR, "config/hal: couldn't allocate name\n");
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* Check for duplicate devices */
|
||||
if (device_is_duplicate(config_info)) {
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: device %s already added. Ignoring.\n", name);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* ok, grab options from hal.. iterate through all properties
|
||||
* and lets see if any of them are options that we can add */
|
||||
set = libhal_device_get_all_properties(hal_ctx, udi, &error);
|
||||
|
||||
if (!set) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't get property list for %s: %s (%s)\n",
|
||||
udi, error.name, error.message);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
libhal_psi_init(&set_iter, set);
|
||||
while (libhal_psi_has_more(&set_iter)) {
|
||||
/* we are looking for supported keys.. extract and add to options */
|
||||
psi_key = libhal_psi_get_key(&set_iter);
|
||||
|
||||
if (psi_key) {
|
||||
|
||||
/* normal options first (input.x11_options.<propname>) */
|
||||
if (!strncasecmp
|
||||
(psi_key, LIBHAL_PROP_KEY, sizeof(LIBHAL_PROP_KEY) - 1)) {
|
||||
char *tmp;
|
||||
|
||||
/* only support strings for all values */
|
||||
tmp_val = get_prop_string(hal_ctx, udi, psi_key);
|
||||
|
||||
if (tmp_val) {
|
||||
|
||||
/* xkb needs special handling. HAL specs include
|
||||
* input.xkb.xyz options, but the x11-input.fdi specifies
|
||||
* input.x11_options.Xkbxyz options. By default, we use
|
||||
* the former, unless the specific X11 ones are specified.
|
||||
* Since we can't predict the order in which the keys
|
||||
* arrive, we need to store them.
|
||||
*/
|
||||
if ((tmp = strcasestr(psi_key, "xkb")) && strlen(tmp) >= 4) {
|
||||
if (!strcasecmp(&tmp[3], "layout")) {
|
||||
free(xkb_opts.layout);
|
||||
xkb_opts.layout = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "model")) {
|
||||
free(xkb_opts.model);
|
||||
xkb_opts.model = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "rules")) {
|
||||
free(xkb_opts.rules);
|
||||
xkb_opts.rules = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "variant")) {
|
||||
free(xkb_opts.variant);
|
||||
xkb_opts.variant = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "options")) {
|
||||
free(xkb_opts.options);
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* all others */
|
||||
input_options =
|
||||
input_option_new(input_options,
|
||||
psi_key + sizeof(LIBHAL_PROP_KEY) -
|
||||
1, tmp_val);
|
||||
free(tmp_val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* server 1.4 had xkb_options as strlist. */
|
||||
if ((tmp = strcasestr(psi_key, "xkb")) &&
|
||||
(strlen(tmp) >= 4) &&
|
||||
(!strcasecmp(&tmp[3], "options")) &&
|
||||
(tmp_val =
|
||||
get_prop_string_array(hal_ctx, udi, psi_key))) {
|
||||
free(xkb_opts.options);
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncasecmp
|
||||
(psi_key, LIBHAL_XKB_PROP_KEY,
|
||||
sizeof(LIBHAL_XKB_PROP_KEY) - 1)) {
|
||||
char *tmp;
|
||||
|
||||
/* only support strings for all values */
|
||||
tmp_val = get_prop_string(hal_ctx, udi, psi_key);
|
||||
|
||||
if (tmp_val && strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) {
|
||||
|
||||
tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1];
|
||||
|
||||
if (!strcasecmp(tmp, "layout")) {
|
||||
if (!xkb_opts.layout)
|
||||
xkb_opts.layout = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "rules")) {
|
||||
if (!xkb_opts.rules)
|
||||
xkb_opts.rules = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "variant")) {
|
||||
if (!xkb_opts.variant)
|
||||
xkb_opts.variant = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "model")) {
|
||||
if (!xkb_opts.model)
|
||||
xkb_opts.model = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "options")) {
|
||||
if (!xkb_opts.options)
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
free(tmp_val);
|
||||
}
|
||||
else {
|
||||
/* server 1.4 had xkb options as strlist */
|
||||
tmp_val = get_prop_string_array(hal_ctx, udi, psi_key);
|
||||
if (tmp_val &&
|
||||
strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) {
|
||||
tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1];
|
||||
if (!strcasecmp(tmp, ".options") && (!xkb_opts.options))
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
free(tmp_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* psi_key doesn't need to be freed */
|
||||
libhal_psi_next(&set_iter);
|
||||
}
|
||||
|
||||
/* Now add xkb options */
|
||||
if (xkb_opts.layout)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_layout", xkb_opts.layout);
|
||||
if (xkb_opts.rules)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_rules", xkb_opts.rules);
|
||||
if (xkb_opts.variant)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_variant", xkb_opts.variant);
|
||||
if (xkb_opts.model)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_model", xkb_opts.model);
|
||||
if (xkb_opts.options)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_options", xkb_opts.options);
|
||||
input_options = input_option_new(input_options, "config_info", config_info);
|
||||
|
||||
/* this isn't an error, but how else do you output something that the user can see? */
|
||||
LogMessage(X_INFO, "config/hal: Adding input device %s\n", name);
|
||||
if ((rc = NewInputDeviceRequest(input_options, &attrs, &dev)) != Success) {
|
||||
LogMessage(X_ERROR, "config/hal: NewInputDeviceRequest failed (%d)\n",
|
||||
rc);
|
||||
dev = NULL;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
unwind:
|
||||
if (set)
|
||||
libhal_free_property_set(set);
|
||||
free(path);
|
||||
free(driver);
|
||||
free(name);
|
||||
free(config_info);
|
||||
input_option_free_list(&input_options);
|
||||
|
||||
free(attrs.product);
|
||||
free(attrs.vendor);
|
||||
free(attrs.device);
|
||||
free(attrs.pnp_id);
|
||||
free(attrs.usb_id);
|
||||
if (attrs.tags) {
|
||||
char **tag = attrs.tags;
|
||||
|
||||
while (*tag) {
|
||||
free(*tag);
|
||||
tag++;
|
||||
}
|
||||
free(attrs.tags);
|
||||
}
|
||||
|
||||
free(xkb_opts.layout);
|
||||
free(xkb_opts.rules);
|
||||
free(xkb_opts.model);
|
||||
free(xkb_opts.variant);
|
||||
free(xkb_opts.options);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_hook(void *data)
|
||||
{
|
||||
DBusError error;
|
||||
struct config_hal_info *info = data;
|
||||
|
||||
if (info->hal_ctx) {
|
||||
if (dbus_connection_get_is_connected(info->system_bus)) {
|
||||
dbus_error_init(&error);
|
||||
if (!libhal_ctx_shutdown(info->hal_ctx, &error))
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: disconnect_hook couldn't shut down context: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
libhal_ctx_free(info->hal_ctx);
|
||||
}
|
||||
|
||||
info->hal_ctx = NULL;
|
||||
info->system_bus = NULL;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
connect_and_register(DBusConnection * connection, struct config_hal_info *info)
|
||||
{
|
||||
DBusError error;
|
||||
char **devices;
|
||||
int num_devices, i;
|
||||
|
||||
if (info->hal_ctx)
|
||||
return TRUE; /* already registered, pretend we did something */
|
||||
|
||||
info->system_bus = connection;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
info->hal_ctx = libhal_ctx_new();
|
||||
if (!info->hal_ctx) {
|
||||
LogMessage(X_ERROR, "config/hal: couldn't create HAL context\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!libhal_ctx_set_dbus_connection(info->hal_ctx, info->system_bus)) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't associate HAL context with bus\n");
|
||||
goto out_err;
|
||||
}
|
||||
if (!libhal_ctx_init(info->hal_ctx, &error)) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't initialise context: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
goto out_err;
|
||||
}
|
||||
if (!libhal_device_property_watch_all(info->hal_ctx, &error)) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't watch all properties: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
goto out_ctx;
|
||||
}
|
||||
libhal_ctx_set_device_added(info->hal_ctx, device_added);
|
||||
libhal_ctx_set_device_removed(info->hal_ctx, device_removed);
|
||||
|
||||
devices = libhal_find_device_by_capability(info->hal_ctx, "input",
|
||||
&num_devices, &error);
|
||||
/* FIXME: Get default devices if error is set. */
|
||||
if (dbus_error_is_set(&error)) {
|
||||
LogMessage(X_ERROR, "config/hal: couldn't find input device: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
goto out_ctx;
|
||||
}
|
||||
for (i = 0; i < num_devices; i++)
|
||||
device_added(info->hal_ctx, devices[i]);
|
||||
libhal_free_string_array(devices);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return TRUE;
|
||||
|
||||
out_ctx:
|
||||
dbus_error_free(&error);
|
||||
|
||||
if (!libhal_ctx_shutdown(info->hal_ctx, &error)) {
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: couldn't shut down context: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
|
||||
out_err:
|
||||
dbus_error_free(&error);
|
||||
|
||||
if (info->hal_ctx) {
|
||||
libhal_ctx_free(info->hal_ctx);
|
||||
}
|
||||
|
||||
info->hal_ctx = NULL;
|
||||
info->system_bus = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle NewOwnerChanged signals to deal with HAL startup at X server runtime.
|
||||
*
|
||||
* NewOwnerChanged is send once when HAL shuts down, and once again when it
|
||||
* comes back up. Message has three arguments, first is the name
|
||||
* (org.freedesktop.Hal), the second one is the old owner, third one is new
|
||||
* owner.
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
ownerchanged_handler(DBusConnection * connection, DBusMessage * message,
|
||||
void *data)
|
||||
{
|
||||
int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
if (dbus_message_is_signal(message,
|
||||
"org.freedesktop.DBus", "NameOwnerChanged")) {
|
||||
DBusError error;
|
||||
char *name, *old_owner, *new_owner;
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_message_get_args(message, &error,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &old_owner,
|
||||
DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID);
|
||||
|
||||
if (dbus_error_is_set(&error)) {
|
||||
ErrorF
|
||||
("[config/hal] failed to get NameOwnerChanged args: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
}
|
||||
else if (name && strcmp(name, "org.freedesktop.Hal") == 0) {
|
||||
|
||||
if (!old_owner || !strlen(old_owner)) {
|
||||
DebugF("[config/hal] HAL startup detected.\n");
|
||||
if (connect_and_register
|
||||
(connection, (struct config_hal_info *) data))
|
||||
dbus_connection_unregister_object_path(connection,
|
||||
"/org/freedesktop/DBus");
|
||||
else
|
||||
ErrorF("[config/hal] Failed to connect to HAL bus.\n");
|
||||
}
|
||||
|
||||
ret = DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler for the NameOwnerChanged signal.
|
||||
*/
|
||||
static BOOL
|
||||
listen_for_startup(DBusConnection * connection, void *data)
|
||||
{
|
||||
DBusObjectPathVTable vtable = {.message_function = ownerchanged_handler, };
|
||||
DBusError error;
|
||||
const char MATCH_RULE[] = "sender='org.freedesktop.DBus',"
|
||||
"interface='org.freedesktop.DBus',"
|
||||
"type='signal',"
|
||||
"path='/org/freedesktop/DBus'," "member='NameOwnerChanged'";
|
||||
int rc = FALSE;
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_bus_add_match(connection, MATCH_RULE, &error);
|
||||
if (!dbus_error_is_set(&error)) {
|
||||
if (dbus_connection_register_object_path(connection,
|
||||
"/org/freedesktop/DBus",
|
||||
&vtable, data))
|
||||
rc = TRUE;
|
||||
else
|
||||
ErrorF("[config/hal] cannot register object path.\n");
|
||||
}
|
||||
else {
|
||||
ErrorF("[config/hal] couldn't add match rule: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
ErrorF("[config/hal] cannot detect a HAL startup.\n");
|
||||
}
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_hook(DBusConnection * connection, void *data)
|
||||
{
|
||||
struct config_hal_info *info = data;
|
||||
|
||||
if (listen_for_startup(connection, data) &&
|
||||
connect_and_register(connection, info))
|
||||
dbus_connection_unregister_object_path(connection,
|
||||
"/org/freedesktop/DBus");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct config_hal_info hal_info;
|
||||
|
||||
static struct dbus_core_hook hook = {
|
||||
.connect = connect_hook,
|
||||
.disconnect = disconnect_hook,
|
||||
.data = &hal_info,
|
||||
};
|
||||
|
||||
int
|
||||
config_hal_init(void)
|
||||
{
|
||||
memset(&hal_info, 0, sizeof(hal_info));
|
||||
hal_info.system_bus = NULL;
|
||||
hal_info.hal_ctx = NULL;
|
||||
|
||||
if (!dbus_core_add_hook(&hook)) {
|
||||
LogMessage(X_ERROR, "config/hal: failed to add D-Bus hook\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verbose message */
|
||||
LogMessageVerb(X_INFO, 7, "config/hal: initialized\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_hal_fini(void)
|
||||
{
|
||||
dbus_core_remove_hook(&hook);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
srcs_config = [
|
||||
'config.c',
|
||||
]
|
||||
|
||||
config_dep = [common_dep]
|
||||
|
||||
if build_dbus
|
||||
srcs_config += 'dbus-core.c'
|
||||
config_dep += dbus_dep
|
||||
endif
|
||||
|
||||
if build_hal
|
||||
srcs_config += 'hal.c'
|
||||
config_dep += hal_dep
|
||||
endif
|
||||
|
||||
if build_udev
|
||||
srcs_config += 'udev.c'
|
||||
config_dep += udev_dep
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'netbsd' or host_machine.system() == 'openbsd'
|
||||
srcs_config += 'wscons.c'
|
||||
endif
|
||||
|
||||
if build_xorg
|
||||
install_data('10-quirks.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'X11/xorg.conf.d'))
|
||||
endif
|
||||
|
||||
libxserver_config = static_library('libxserver_config',
|
||||
srcs_config,
|
||||
include_directories: inc,
|
||||
dependencies: config_dep,
|
||||
)
|
||||
610
config/udev.c
610
config/udev.c
|
|
@ -1,610 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Julien Cristau
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author: Julien Cristau <jcristau@debian.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <libudev.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
#include "hotplug.h"
|
||||
#include "config-backends.h"
|
||||
#include "os.h"
|
||||
#include "globals.h"
|
||||
#include "systemd-logind.h"
|
||||
|
||||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#define UDEV_XKB_PROP_KEY "xkb"
|
||||
|
||||
#define LOG_PROPERTY(path, prop, val) \
|
||||
LogMessageVerb(X_INFO, 10, \
|
||||
"config/udev: getting property %s on %s " \
|
||||
"returned \"%s\"\n", \
|
||||
(prop), (path), (val) ? (val) : "(null)")
|
||||
#define LOG_SYSATTR(path, attr, val) \
|
||||
LogMessageVerb(X_INFO, 10, \
|
||||
"config/udev: getting attribute %s on %s " \
|
||||
"returned \"%s\"\n", \
|
||||
(attr), (path), (val) ? (val) : "(null)")
|
||||
|
||||
static struct udev_monitor *udev_monitor;
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
static void
|
||||
config_udev_odev_setup_attribs(struct udev_device *udev_device, const char *path, const char *syspath,
|
||||
int major, int minor,
|
||||
config_odev_probe_proc_ptr probe_callback);
|
||||
#endif
|
||||
|
||||
static char itoa_buf[16];
|
||||
|
||||
static const char *itoa(int i)
|
||||
{
|
||||
snprintf(itoa_buf, sizeof(itoa_buf), "%d", i);
|
||||
return itoa_buf;
|
||||
}
|
||||
|
||||
static Bool
|
||||
check_seat(struct udev_device *udev_device)
|
||||
{
|
||||
const char *dev_seat;
|
||||
|
||||
dev_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
|
||||
if (!dev_seat)
|
||||
dev_seat = "seat0";
|
||||
|
||||
if (SeatId && strcmp(dev_seat, SeatId))
|
||||
return FALSE;
|
||||
|
||||
if (!SeatId && strcmp(dev_seat, "seat0"))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
device_added(struct udev_device *udev_device)
|
||||
{
|
||||
const char *path, *name = NULL;
|
||||
char *config_info = NULL;
|
||||
const char *syspath;
|
||||
const char *tags_prop;
|
||||
const char *key, *value, *tmp;
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
const char *subsys = NULL;
|
||||
#endif
|
||||
InputOption *input_options;
|
||||
InputAttributes attrs = { };
|
||||
DeviceIntPtr dev = NULL;
|
||||
struct udev_list_entry *set, *entry;
|
||||
struct udev_device *parent;
|
||||
int rc;
|
||||
dev_t devnum;
|
||||
|
||||
path = udev_device_get_devnode(udev_device);
|
||||
|
||||
syspath = udev_device_get_syspath(udev_device);
|
||||
|
||||
if (!path || !syspath)
|
||||
return;
|
||||
|
||||
if (!check_seat(udev_device))
|
||||
return;
|
||||
|
||||
devnum = udev_device_get_devnum(udev_device);
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
subsys = udev_device_get_subsystem(udev_device);
|
||||
|
||||
if (subsys && !strcmp(subsys, "drm")) {
|
||||
const char *sysname = udev_device_get_sysname(udev_device);
|
||||
|
||||
if (strncmp(sysname, "card", 4) != 0)
|
||||
return;
|
||||
|
||||
/* Check for devices already added through xf86platformProbe() */
|
||||
if (xf86_find_platform_device_by_devnum(major(devnum), minor(devnum)))
|
||||
return;
|
||||
|
||||
LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
|
||||
|
||||
config_udev_odev_setup_attribs(udev_device, path, syspath, major(devnum),
|
||||
minor(devnum), NewGPUDeviceRequest);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
value = udev_device_get_property_value(udev_device, "ID_INPUT");
|
||||
if (!value || !strcmp(value, "0")) {
|
||||
LogMessageVerb(X_INFO, 10,
|
||||
"config/udev: ignoring device %s without "
|
||||
"property ID_INPUT set\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
input_options = input_option_new(NULL, "_source", "server/udev");
|
||||
if (!input_options)
|
||||
return;
|
||||
|
||||
parent = udev_device_get_parent(udev_device);
|
||||
if (parent) {
|
||||
const char *ppath = udev_device_get_devnode(parent);
|
||||
const char *product = udev_device_get_property_value(parent, "PRODUCT");
|
||||
const char *pnp_id = udev_device_get_sysattr_value(parent, "id");
|
||||
unsigned int usb_vendor, usb_model;
|
||||
|
||||
name = udev_device_get_sysattr_value(parent, "name");
|
||||
LOG_SYSATTR(ppath, "name", name);
|
||||
if (!name) {
|
||||
name = udev_device_get_property_value(parent, "NAME");
|
||||
LOG_PROPERTY(ppath, "NAME", name);
|
||||
}
|
||||
|
||||
/* construct USB ID in lowercase hex - "0000:ffff" */
|
||||
if (product &&
|
||||
sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) {
|
||||
char *usb_id;
|
||||
if (asprintf(&usb_id, "%04x:%04x", usb_vendor, usb_model)
|
||||
== -1)
|
||||
usb_id = NULL;
|
||||
else
|
||||
LOG_PROPERTY(ppath, "PRODUCT", product);
|
||||
attrs.usb_id = usb_id;
|
||||
}
|
||||
|
||||
while (!pnp_id && (parent = udev_device_get_parent(parent))) {
|
||||
pnp_id = udev_device_get_sysattr_value(parent, "id");
|
||||
if (!pnp_id)
|
||||
continue;
|
||||
|
||||
attrs.pnp_id = strdup(pnp_id);
|
||||
ppath = udev_device_get_devnode(parent);
|
||||
LOG_SYSATTR(ppath, "id", pnp_id);
|
||||
}
|
||||
|
||||
}
|
||||
if (!name)
|
||||
name = "(unnamed)";
|
||||
else
|
||||
attrs.product = strdup(name);
|
||||
input_options = input_option_new(input_options, "name", name);
|
||||
input_options = input_option_new(input_options, "path", path);
|
||||
input_options = input_option_new(input_options, "device", path);
|
||||
input_options = input_option_new(input_options, "major", itoa(major(devnum)));
|
||||
input_options = input_option_new(input_options, "minor", itoa(minor(devnum)));
|
||||
if (path)
|
||||
attrs.device = strdup(path);
|
||||
|
||||
tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags");
|
||||
LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop);
|
||||
attrs.tags = xstrtokenize(tags_prop, ",");
|
||||
|
||||
if (asprintf(&config_info, "udev:%s", syspath) == -1) {
|
||||
config_info = NULL;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
if (device_is_duplicate(config_info)) {
|
||||
LogMessage(X_WARNING, "config/udev: device %s already added. "
|
||||
"Ignoring.\n", name);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
set = udev_device_get_properties_list_entry(udev_device);
|
||||
udev_list_entry_foreach(entry, set) {
|
||||
key = udev_list_entry_get_name(entry);
|
||||
if (!key)
|
||||
continue;
|
||||
value = udev_list_entry_get_value(entry);
|
||||
if (!strncasecmp(key, UDEV_XKB_PROP_KEY, sizeof(UDEV_XKB_PROP_KEY) - 1)) {
|
||||
LOG_PROPERTY(path, key, value);
|
||||
tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1;
|
||||
if (!strcasecmp(tmp, "rules"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_rules", value);
|
||||
else if (!strcasecmp(tmp, "layout"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_layout", value);
|
||||
else if (!strcasecmp(tmp, "variant"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_variant", value);
|
||||
else if (!strcasecmp(tmp, "model"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_model", value);
|
||||
else if (!strcasecmp(tmp, "options"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_options", value);
|
||||
}
|
||||
else if (!strcmp(key, "ID_VENDOR")) {
|
||||
LOG_PROPERTY(path, key, value);
|
||||
attrs.vendor = strdup(value);
|
||||
} else if (!strncmp(key, "ID_INPUT_", 9)) {
|
||||
const struct pfmap {
|
||||
const char *property;
|
||||
unsigned int flag;
|
||||
} map[] = {
|
||||
{ "ID_INPUT_KEY", ATTR_KEY },
|
||||
{ "ID_INPUT_KEYBOARD", ATTR_KEYBOARD },
|
||||
{ "ID_INPUT_MOUSE", ATTR_POINTER },
|
||||
{ "ID_INPUT_JOYSTICK", ATTR_JOYSTICK },
|
||||
{ "ID_INPUT_TABLET", ATTR_TABLET },
|
||||
{ "ID_INPUT_TABLET_PAD", ATTR_TABLET_PAD },
|
||||
{ "ID_INPUT_TOUCHPAD", ATTR_TOUCHPAD },
|
||||
{ "ID_INPUT_TOUCHSCREEN", ATTR_TOUCHSCREEN },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
/* Anything but the literal string "0" is considered a
|
||||
* boolean true. The empty string isn't a thing with udev
|
||||
* properties anyway */
|
||||
if (value && strcmp(value, "0")) {
|
||||
const struct pfmap *m = map;
|
||||
|
||||
while (m->property != NULL) {
|
||||
if (!strcmp(m->property, key)) {
|
||||
LOG_PROPERTY(path, key, value);
|
||||
attrs.flags |= m->flag;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input_options = input_option_new(input_options, "config_info", config_info);
|
||||
|
||||
/* Default setting needed for non-seat0 seats */
|
||||
if (ServerIsNotSeat0())
|
||||
input_options = input_option_new(input_options, "GrabDevice", "on");
|
||||
|
||||
LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
|
||||
name, path);
|
||||
rc = NewInputDeviceRequest(input_options, &attrs, &dev);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
unwind:
|
||||
free(config_info);
|
||||
input_option_free_list(&input_options);
|
||||
|
||||
free(attrs.usb_id);
|
||||
free(attrs.pnp_id);
|
||||
free(attrs.product);
|
||||
free(attrs.device);
|
||||
free(attrs.vendor);
|
||||
if (attrs.tags) {
|
||||
char **tag = attrs.tags;
|
||||
|
||||
while (*tag) {
|
||||
free(*tag);
|
||||
tag++;
|
||||
}
|
||||
free(attrs.tags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
device_removed(struct udev_device *device)
|
||||
{
|
||||
char *value;
|
||||
const char *syspath = udev_device_get_syspath(device);
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
const char *subsys = udev_device_get_subsystem(device);
|
||||
|
||||
if (subsys && !strcmp(subsys, "drm")) {
|
||||
const char *sysname = udev_device_get_sysname(device);
|
||||
const char *path = udev_device_get_devnode(device);
|
||||
dev_t devnum = udev_device_get_devnum(device);
|
||||
|
||||
if ((strncmp(sysname,"card", 4) != 0) || (path == NULL))
|
||||
return;
|
||||
|
||||
LogMessage(X_INFO, "config/udev: removing GPU device %s %s\n",
|
||||
syspath, path);
|
||||
config_udev_odev_setup_attribs(device, path, syspath, major(devnum),
|
||||
minor(devnum), DeleteGPUDeviceRequest);
|
||||
/* Retry vtenter after a drm node removal */
|
||||
systemd_logind_vtenter();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (asprintf(&value, "udev:%s", syspath) == -1)
|
||||
return;
|
||||
|
||||
remove_devices("udev", value);
|
||||
|
||||
free(value);
|
||||
}
|
||||
|
||||
static void
|
||||
socket_handler(int fd, int ready, void *data)
|
||||
{
|
||||
struct udev_device *udev_device;
|
||||
const char *action;
|
||||
|
||||
input_lock();
|
||||
udev_device = udev_monitor_receive_device(udev_monitor);
|
||||
if (!udev_device) {
|
||||
input_unlock();
|
||||
return;
|
||||
}
|
||||
action = udev_device_get_action(udev_device);
|
||||
if (action) {
|
||||
if (!strcmp(action, "add")) {
|
||||
device_removed(udev_device);
|
||||
device_added(udev_device);
|
||||
} else if (!strcmp(action, "change")) {
|
||||
/* ignore change for the drm devices */
|
||||
const char *subsys = udev_device_get_subsystem(udev_device);
|
||||
|
||||
if (subsys && strcmp(subsys, "drm")) {
|
||||
device_removed(udev_device);
|
||||
device_added(udev_device);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(action, "remove"))
|
||||
device_removed(udev_device);
|
||||
}
|
||||
udev_device_unref(udev_device);
|
||||
input_unlock();
|
||||
}
|
||||
|
||||
int
|
||||
config_udev_pre_init(void)
|
||||
{
|
||||
struct udev *udev;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return 0;
|
||||
|
||||
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||
if (!udev_monitor)
|
||||
return 0;
|
||||
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
|
||||
NULL);
|
||||
/* For Wacom serial devices */
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL);
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
/* For output GPU devices */
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "drm", NULL);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UDEV_MONITOR_FILTER_ADD_MATCH_TAG
|
||||
if (ServerIsNotSeat0())
|
||||
udev_monitor_filter_add_match_tag(udev_monitor, SeatId);
|
||||
#endif
|
||||
if (udev_monitor_enable_receiving(udev_monitor)) {
|
||||
ErrorF("config/udev: failed to bind the udev monitor\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
config_udev_init(void)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_enumerate *enumerate;
|
||||
struct udev_list_entry *devices, *device;
|
||||
|
||||
udev = udev_monitor_get_udev(udev_monitor);
|
||||
enumerate = udev_enumerate_new(udev);
|
||||
if (!enumerate)
|
||||
return 0;
|
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
udev_enumerate_add_match_subsystem(enumerate, "tty");
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
udev_enumerate_add_match_subsystem(enumerate, "drm");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UDEV_ENUMERATE_ADD_MATCH_TAG
|
||||
if (ServerIsNotSeat0())
|
||||
udev_enumerate_add_match_tag(enumerate, SeatId);
|
||||
#endif
|
||||
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry_foreach(device, devices) {
|
||||
const char *syspath = udev_list_entry_get_name(device);
|
||||
struct udev_device *udev_device =
|
||||
udev_device_new_from_syspath(udev, syspath);
|
||||
|
||||
/* Device might be gone by the time we try to open it */
|
||||
if (!udev_device)
|
||||
continue;
|
||||
|
||||
device_added(udev_device);
|
||||
udev_device_unref(udev_device);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
|
||||
SetNotifyFd(udev_monitor_get_fd(udev_monitor), socket_handler, X_NOTIFY_READ, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_udev_fini(void)
|
||||
{
|
||||
struct udev *udev;
|
||||
|
||||
if (!udev_monitor)
|
||||
return;
|
||||
|
||||
udev = udev_monitor_get_udev(udev_monitor);
|
||||
|
||||
RemoveNotifyFd(udev_monitor_get_fd(udev_monitor));
|
||||
udev_monitor_unref(udev_monitor);
|
||||
udev_monitor = NULL;
|
||||
udev_unref(udev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
|
||||
/* Find the last occurrence of the needle in haystack */
|
||||
static char *strrstr(const char *haystack, const char *needle)
|
||||
{
|
||||
char *prev, *last, *tmp;
|
||||
|
||||
prev = strstr(haystack, needle);
|
||||
if (!prev)
|
||||
return NULL;
|
||||
|
||||
last = prev;
|
||||
tmp = prev + 1;
|
||||
|
||||
while (tmp) {
|
||||
last = strstr(tmp, needle);
|
||||
if (!last)
|
||||
return prev;
|
||||
else {
|
||||
prev = last;
|
||||
tmp = prev + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
/* For certain devices udev does not create ID_PATH entry (which is presumably a bug
|
||||
* in udev). We work around that by implementing a minimal ID_PATH calculator
|
||||
* ourselves along the same logic that udev uses. This works only for the case of
|
||||
* a PCI device being directly connected to a PCI bus, but it will cover most end
|
||||
* users with e.g. a new laptop which only has beta hardware driver support.
|
||||
* See https://gitlab.freedesktop.org/xorg/xserver/-/issues/993 */
|
||||
static char*
|
||||
config_udev_get_fallback_bus_id(struct udev_device *udev_device)
|
||||
{
|
||||
const char *sysname;
|
||||
char *busid;
|
||||
|
||||
udev_device = udev_device_get_parent(udev_device);
|
||||
if (udev_device == NULL)
|
||||
return NULL;
|
||||
|
||||
if (strcmp(udev_device_get_subsystem(udev_device), "pci") != 0)
|
||||
return NULL;
|
||||
|
||||
sysname = udev_device_get_sysname(udev_device);
|
||||
busid = XNFalloc(strlen(sysname) + 5);
|
||||
busid[0] = '\0';
|
||||
strcat(busid, "pci:");
|
||||
strcat(busid, sysname);
|
||||
|
||||
return busid;
|
||||
}
|
||||
|
||||
static void
|
||||
config_udev_odev_setup_attribs(struct udev_device *udev_device, const char *path, const char *syspath,
|
||||
int major, int minor,
|
||||
config_odev_probe_proc_ptr probe_callback)
|
||||
{
|
||||
struct OdevAttributes *attribs = config_odev_allocate_attributes();
|
||||
const char *value, *str;
|
||||
|
||||
attribs->path = XNFstrdup(path);
|
||||
attribs->syspath = XNFstrdup(syspath);
|
||||
attribs->major = major;
|
||||
attribs->minor = minor;
|
||||
|
||||
value = udev_device_get_property_value(udev_device, "ID_PATH");
|
||||
if (value && (str = strrstr(value, "pci-"))) {
|
||||
value = str;
|
||||
|
||||
if ((str = strstr(value, "usb-")))
|
||||
value = str;
|
||||
|
||||
attribs->busid = XNFstrdup(value);
|
||||
attribs->busid[3] = ':';
|
||||
}
|
||||
|
||||
if (!value)
|
||||
attribs->busid = config_udev_get_fallback_bus_id(udev_device);
|
||||
|
||||
/* ownership of attribs is passed to probe layer */
|
||||
probe_callback(attribs);
|
||||
}
|
||||
|
||||
void
|
||||
config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_enumerate *enumerate;
|
||||
struct udev_list_entry *devices, *device;
|
||||
|
||||
udev = udev_monitor_get_udev(udev_monitor);
|
||||
enumerate = udev_enumerate_new(udev);
|
||||
if (!enumerate)
|
||||
return;
|
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "drm");
|
||||
udev_enumerate_add_match_sysname(enumerate, "card[0-9]*");
|
||||
#ifdef HAVE_UDEV_ENUMERATE_ADD_MATCH_TAG
|
||||
if (ServerIsNotSeat0())
|
||||
udev_enumerate_add_match_tag(enumerate, SeatId);
|
||||
#endif
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry_foreach(device, devices) {
|
||||
const char *syspath = udev_list_entry_get_name(device);
|
||||
struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
|
||||
const char *path = udev_device_get_devnode(udev_device);
|
||||
const char *sysname = udev_device_get_sysname(udev_device);
|
||||
dev_t devnum = udev_device_get_devnum(udev_device);
|
||||
const char *subsys = udev_device_get_subsystem(udev_device);
|
||||
|
||||
if (!path || !syspath || !subsys)
|
||||
goto no_probe;
|
||||
else if (strcmp(subsys, "drm") != 0)
|
||||
goto no_probe;
|
||||
else if (strncmp(sysname, "card", 4) != 0)
|
||||
goto no_probe;
|
||||
else if (!check_seat(udev_device))
|
||||
goto no_probe;
|
||||
|
||||
config_udev_odev_setup_attribs(udev_device, path, syspath, major(devnum),
|
||||
minor(devnum), probe_callback);
|
||||
no_probe:
|
||||
udev_device_unref(udev_device);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
271
config/wscons.c
271
config/wscons.c
|
|
@ -1,271 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Matthieu Herrb
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <dev/wscons/wsconsio.h>
|
||||
#include <dev/wscons/wsksymdef.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
#include "os.h"
|
||||
#include "config-backends.h"
|
||||
|
||||
#define WSCONS_KBD_DEVICE "/dev/wskbd"
|
||||
#define WSCONS_MOUSE_PREFIX "/dev/wsmouse"
|
||||
|
||||
#define KB_OVRENC \
|
||||
{ KB_UK, "gb" }, \
|
||||
{ KB_SV, "se" }, \
|
||||
{ KB_SG, "ch" }, \
|
||||
{ KB_SF, "ch" }, \
|
||||
{ KB_LA, "latam" }, \
|
||||
{ KB_CF, "ca" }
|
||||
|
||||
struct nameint {
|
||||
int val;
|
||||
const char *name;
|
||||
} kbdenc[] = {
|
||||
KB_OVRENC,
|
||||
KB_ENCTAB
|
||||
#ifndef __NetBSD__
|
||||
,
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
|
||||
struct nameint kbdvar[] = {
|
||||
{KB_NODEAD | KB_SG, "de_nodeadkeys"},
|
||||
{KB_NODEAD | KB_SF, "fr_nodeadkeys"},
|
||||
{KB_SF, "fr"},
|
||||
{KB_DVORAK | KB_CF, "fr-dvorak"},
|
||||
{KB_DVORAK | KB_FR, "bepo"},
|
||||
{KB_DVORAK, "dvorak"},
|
||||
{KB_CF, "fr-legacy"},
|
||||
{KB_NODEAD, "nodeadkeys"},
|
||||
{0}
|
||||
};
|
||||
|
||||
struct nameint kbdopt[] = {
|
||||
{KB_SWAPCTRLCAPS, "ctrl:swapcaps"},
|
||||
{0}
|
||||
};
|
||||
|
||||
struct nameint kbdmodel[] = {
|
||||
{WSKBD_TYPE_ZAURUS, "zaurus"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void
|
||||
wscons_add_keyboard(void)
|
||||
{
|
||||
InputAttributes attrs = { };
|
||||
DeviceIntPtr dev = NULL;
|
||||
InputOption *input_options = NULL;
|
||||
char *config_info = NULL;
|
||||
int fd, i, rc;
|
||||
unsigned int type;
|
||||
kbd_t wsenc = 0;
|
||||
|
||||
/* Find keyboard configuration */
|
||||
fd = open(WSCONS_KBD_DEVICE, O_RDWR | O_NONBLOCK | O_EXCL);
|
||||
if (fd == -1) {
|
||||
LogMessage(X_ERROR, "wskbd: open %s: %s\n",
|
||||
WSCONS_KBD_DEVICE, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, WSKBDIO_GETENCODING, &wsenc) == -1) {
|
||||
LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GETENCODING) "
|
||||
"failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, WSKBDIO_GTYPE, &type) == -1) {
|
||||
LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GTYPE) "
|
||||
"failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
input_options = input_option_new(input_options, "_source", "server/wscons");
|
||||
if (input_options == NULL)
|
||||
return;
|
||||
|
||||
LogMessage(X_INFO, "config/wscons: checking input device %s\n",
|
||||
WSCONS_KBD_DEVICE);
|
||||
input_options = input_option_new(input_options, "name", WSCONS_KBD_DEVICE);
|
||||
input_options = input_option_new(input_options, "driver", "kbd");
|
||||
|
||||
if (asprintf(&config_info, "wscons:%s", WSCONS_KBD_DEVICE) == -1)
|
||||
goto unwind;
|
||||
if (KB_ENCODING(wsenc) == KB_USER) {
|
||||
/* Ignore wscons "user" layout */
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: ignoring \"user\" layout\n");
|
||||
goto kbd_config_done;
|
||||
}
|
||||
for (i = 0; kbdenc[i].val; i++)
|
||||
if (KB_ENCODING(wsenc) == kbdenc[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using layout %s\n",
|
||||
kbdenc[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_layout", kbdenc[i].name);
|
||||
break;
|
||||
}
|
||||
for (i = 0; kbdvar[i].val; i++)
|
||||
if (wsenc == kbdvar[i].val || KB_VARIANT(wsenc) == kbdvar[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using variant %s\n",
|
||||
kbdvar[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_variant", kbdvar[i].name);
|
||||
break;
|
||||
}
|
||||
for (i = 0; kbdopt[i].val; i++)
|
||||
if (KB_VARIANT(wsenc) == kbdopt[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using option %s\n",
|
||||
kbdopt[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_options", kbdopt[i].name);
|
||||
break;
|
||||
}
|
||||
for (i = 0; kbdmodel[i].val; i++)
|
||||
if (type == kbdmodel[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using model %s\n",
|
||||
kbdmodel[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_model", kbdmodel[i].name);
|
||||
break;
|
||||
}
|
||||
|
||||
kbd_config_done:
|
||||
attrs.flags |= ATTR_KEY | ATTR_KEYBOARD;
|
||||
rc = NewInputDeviceRequest(input_options, &attrs, &dev);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
for (; dev; dev = dev->next) {
|
||||
free(dev->config_info);
|
||||
dev->config_info = strdup(config_info);
|
||||
}
|
||||
unwind:
|
||||
input_option_free_list(&input_options);
|
||||
}
|
||||
|
||||
static void
|
||||
wscons_add_pointer(const char *path, const char *driver, int flags)
|
||||
{
|
||||
InputAttributes attrs = { };
|
||||
DeviceIntPtr dev = NULL;
|
||||
InputOption *input_options = NULL;
|
||||
char *config_info = NULL;
|
||||
int rc;
|
||||
|
||||
if (asprintf(&config_info, "wscons:%s", path) == -1)
|
||||
return;
|
||||
|
||||
input_options = input_option_new(input_options, "_source", "server/wscons");
|
||||
if (input_options == NULL)
|
||||
return;
|
||||
|
||||
input_options = input_option_new(input_options, "name", strdup(path));
|
||||
input_options = input_option_new(input_options, "driver", strdup(driver));
|
||||
input_options = input_option_new(input_options, "device", strdup(path));
|
||||
LogMessage(X_INFO, "config/wscons: checking input device %s\n", path);
|
||||
attrs.flags |= flags;
|
||||
rc = NewInputDeviceRequest(input_options, &attrs, &dev);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
for (; dev; dev = dev->next) {
|
||||
free(dev->config_info);
|
||||
dev->config_info = strdup(config_info);
|
||||
}
|
||||
unwind:
|
||||
input_option_free_list(&input_options);
|
||||
}
|
||||
|
||||
static void
|
||||
wscons_add_pointers(void)
|
||||
{
|
||||
char devname[256];
|
||||
int fd, i, wsmouse_type;
|
||||
|
||||
/* Check pointing devices */
|
||||
for (i = 0; i < 4; i++) {
|
||||
snprintf(devname, sizeof(devname), "%s%d", WSCONS_MOUSE_PREFIX, i);
|
||||
LogMessageVerb(X_INFO, 10, "wsmouse: checking %s\n", devname);
|
||||
#ifdef HAVE_OPEN_DEVICE
|
||||
fd = open_device(devname, O_RDWR | O_NONBLOCK | O_EXCL);
|
||||
#else
|
||||
fd = open(devname, O_RDWR | O_NONBLOCK | O_EXCL);
|
||||
#endif
|
||||
if (fd == -1) {
|
||||
LogMessageVerb(X_WARNING, 10, "%s: %s\n", devname, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (ioctl(fd, WSMOUSEIO_GTYPE, &wsmouse_type) != 0) {
|
||||
LogMessageVerb(X_WARNING, 10,
|
||||
"%s: WSMOUSEIO_GTYPE failed\n", devname);
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
close(fd);
|
||||
switch (wsmouse_type) {
|
||||
#ifdef WSMOUSE_TYPE_SYNAPTICS
|
||||
case WSMOUSE_TYPE_SYNAPTICS:
|
||||
wscons_add_pointer(devname, "synaptics", ATTR_TOUCHPAD);
|
||||
break;
|
||||
#endif
|
||||
case WSMOUSE_TYPE_TPANEL:
|
||||
wscons_add_pointer(devname, "ws", ATTR_TOUCHSCREEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Add a default entry catching all other mux elements as pointers */
|
||||
wscons_add_pointer(WSCONS_MOUSE_PREFIX, "ws", ATTR_POINTER);
|
||||
}
|
||||
|
||||
int
|
||||
config_wscons_init(void)
|
||||
{
|
||||
wscons_add_keyboard();
|
||||
wscons_add_pointers();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_wscons_fini(void)
|
||||
{
|
||||
/* Not much to do ? */
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<deviceinfo version="0.2">
|
||||
<device>
|
||||
|
||||
<!-- The way this works:
|
||||
|
||||
Match against some input device (see the HAL specification for more
|
||||
information), and then merge in keys, which you can use to specify
|
||||
the configuration similar to the way you would in xorg.conf. You will
|
||||
need to restart HAL after making changes. If you are having issues,
|
||||
starting X with the -logverbose 7 flag may yield useful information.
|
||||
|
||||
Keys Supported:
|
||||
|
||||
Key "input.x11_driver" (string)
|
||||
This specifies the driver to use. You MUST specify this option,
|
||||
or a driver will not be loaded and the rest will be ignored by
|
||||
Xorg
|
||||
|
||||
Key "input.x11_options.<option name>" (string)
|
||||
This allows you to specify arbitrary options to pass to the driver.
|
||||
Anything you would normally specify in xorg.conf goes here. So, for
|
||||
option "Mode" in xorg.conf, you would specify the key name of
|
||||
"input.x11_options.Mode".
|
||||
|
||||
Do not specify "input.x11_options.Device" since "input.device"
|
||||
will be used automatically.
|
||||
|
||||
You MUST specify all options as strings, otherwise the server will
|
||||
ignore them.
|
||||
|
||||
Legacy Keys
|
||||
"input.xkb.rules"
|
||||
"input.xkb.model"
|
||||
"input.xkb.layout"
|
||||
"input.xkb.variant"
|
||||
"input.xkb.options"
|
||||
|
||||
These keys are deprecated. Use these instead:
|
||||
"input.x11_options.XkbRules"
|
||||
"input.x11_options.XkbModel"
|
||||
"input.x11_options.XkbLayout"
|
||||
"input.x11_options.XkbVariant"
|
||||
"input.x11_options.XkbOptions"
|
||||
|
||||
See the evdev documentation for more information.
|
||||
|
||||
FIXME: Support tablets too.
|
||||
TODO: I think its fixed, can't test
|
||||
|
||||
-->
|
||||
|
||||
<match key="info.capabilities" contains="input.mouse">
|
||||
<merge key="input.x11_driver" type="string">mouse</merge>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="Linux">
|
||||
<merge key="input.x11_driver" type="string">evdev</merge>
|
||||
</match>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="SunOS">
|
||||
<match key="input.device" contains="usb">
|
||||
<merge key="input.x11_options.StreamsModule" type="string">usbms</merge>
|
||||
<merge key="input.x11_options.Protocol" type="string">VUID</merge>
|
||||
</match>
|
||||
</match>
|
||||
</match>
|
||||
|
||||
<match key="info.capabilities" contains="input.keys">
|
||||
<merge key="input.x11_options.XkbRules" type="string">base</merge>
|
||||
|
||||
<!-- If we're using Linux, we use evdev by default (falling back to
|
||||
kbd otherwise). -->
|
||||
<merge key="input.x11_driver" type="string">kbd</merge>
|
||||
<merge key="input.x11_options.XkbModel" type="string">pc105</merge>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="Linux">
|
||||
<merge key="input.x11_driver" type="string">evdev</merge>
|
||||
<merge key="input.x11_options.XkbModel" type="string">evdev</merge>
|
||||
</match>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="SunOS">
|
||||
<match key="input.device" contains="usb">
|
||||
<merge key="input.x11_options.StreamsModule" type="string">usbkbm</merge>
|
||||
<merge key="input.x11_options.Protocol" type="string">VUID</merge>
|
||||
</match>
|
||||
</match>
|
||||
|
||||
<merge key="input.x11_options.XkbLayout" type="string">us</merge>
|
||||
|
||||
<merge key="input.x11_options.XkbVariant" type="string" />
|
||||
</match>
|
||||
</device>
|
||||
</deviceinfo>
|
||||
|
|
@ -12,7 +12,3 @@ libxserver_dbe = static_library('libxserver_dbe',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data(hdrs_dbe, install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1250,6 +1250,7 @@ FindBestPixel(EntryPtr pentFirst, int size, xrgb * prgb, int channel)
|
|||
case PSEUDOMAP:
|
||||
dg = (long) pent->co.local.green - prgb->green;
|
||||
db = (long) pent->co.local.blue - prgb->blue;
|
||||
/* fallthrough */
|
||||
case REDMAP:
|
||||
dr = (long) pent->co.local.red - prgb->red;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -981,6 +981,23 @@ FreeAllDeviceClasses(ClassesPtr classes)
|
|||
|
||||
}
|
||||
|
||||
static void
|
||||
FreePendingFrozenDeviceEvents(DeviceIntPtr dev)
|
||||
{
|
||||
QdEventPtr qe, tmp;
|
||||
|
||||
if (!dev->deviceGrab.sync.frozen)
|
||||
return;
|
||||
|
||||
/* Dequeue any frozen pending events */
|
||||
xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
|
||||
if (qe->device == dev) {
|
||||
xorg_list_del(&qe->next);
|
||||
free(qe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close down a device and free all resources.
|
||||
* Once closed down, the driver will probably not expect you that you'll ever
|
||||
|
|
@ -1045,6 +1062,7 @@ CloseDevice(DeviceIntPtr dev)
|
|||
valuator_mask_free(&dev->last.touches[j].valuators);
|
||||
free(dev->last.touches);
|
||||
dev->config_info = NULL;
|
||||
FreePendingFrozenDeviceEvents(dev);
|
||||
dixFreePrivates(dev->devPrivates, PRIVATE_DEVICE);
|
||||
free(dev);
|
||||
}
|
||||
|
|
@ -2699,11 +2717,14 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
|
|||
dev->spriteInfo->paired = dev;
|
||||
}
|
||||
else {
|
||||
DeviceIntPtr keyboard = GetMaster(dev, MASTER_KEYBOARD);
|
||||
|
||||
dev->spriteInfo->sprite = master->spriteInfo->sprite;
|
||||
dev->spriteInfo->paired = master;
|
||||
dev->spriteInfo->spriteOwner = FALSE;
|
||||
|
||||
XkbPushLockedStateToSlaves(GetMaster(dev, MASTER_KEYBOARD), 0, 0);
|
||||
if (keyboard)
|
||||
XkbPushLockedStateToSlaves(keyboard, 0, 0);
|
||||
RecalculateMasterButtons(master);
|
||||
}
|
||||
|
||||
|
|
@ -2728,7 +2749,7 @@ GetPairedDevice(DeviceIntPtr dev)
|
|||
if (!IsMaster(dev) && !IsFloating(dev))
|
||||
dev = GetMaster(dev, MASTER_ATTACHED);
|
||||
|
||||
return dev->spriteInfo? dev->spriteInfo->paired: NULL;
|
||||
return (dev && dev->spriteInfo) ? dev->spriteInfo->paired: NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -517,9 +517,10 @@ Dispatch(void)
|
|||
|
||||
/* now, finally, deal with client requests */
|
||||
result = ReadRequestFromClient(client);
|
||||
if (result <= 0) {
|
||||
if (result < 0)
|
||||
CloseDownClient(client);
|
||||
if (result == 0)
|
||||
break;
|
||||
else if (result == -1) {
|
||||
CloseDownClient(client);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -540,7 +541,7 @@ Dispatch(void)
|
|||
client->index,
|
||||
client->requestBuffer);
|
||||
#endif
|
||||
if (result > (maxBigRequestSize << 2))
|
||||
if (result < 0 || result > (maxBigRequestSize << 2))
|
||||
result = BadLength;
|
||||
else {
|
||||
result = XaceHookDispatch(client, client->majorOp);
|
||||
|
|
@ -3106,6 +3107,10 @@ ProcFreeCursor(ClientPtr client)
|
|||
rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
|
||||
client, DixDestroyAccess);
|
||||
if (rc == Success) {
|
||||
if (pCursor == rootCursor) {
|
||||
client->errorValue = stuff->id;
|
||||
return BadCursor;
|
||||
}
|
||||
FreeResource(stuff->id, RT_NONE);
|
||||
return Success;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1352,18 +1352,18 @@ int
|
|||
PolyText(ClientPtr client, DrawablePtr pDraw, GC * pGC, unsigned char *pElt,
|
||||
unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
|
||||
{
|
||||
PTclosureRec local_closure;
|
||||
|
||||
local_closure.pElt = pElt;
|
||||
local_closure.endReq = endReq;
|
||||
local_closure.client = client;
|
||||
local_closure.pDraw = pDraw;
|
||||
local_closure.xorg = xorg;
|
||||
local_closure.yorg = yorg;
|
||||
local_closure.reqType = reqType;
|
||||
local_closure.pGC = pGC;
|
||||
local_closure.did = did;
|
||||
local_closure.err = Success;
|
||||
PTclosureRec local_closure = {
|
||||
.client = client,
|
||||
.pDraw = pDraw,
|
||||
.pGC = pGC,
|
||||
.pElt = pElt,
|
||||
.endReq = endReq,
|
||||
.xorg = xorg,
|
||||
.yorg = yorg,
|
||||
.reqType = reqType,
|
||||
.did = did,
|
||||
.err = Success
|
||||
};
|
||||
|
||||
(void) doPolyText(client, &local_closure);
|
||||
return Success;
|
||||
|
|
@ -1687,7 +1687,8 @@ SetFontPath(ClientPtr client, int npaths, unsigned char *paths)
|
|||
int bad;
|
||||
|
||||
err = SetFontPathElements(npaths, paths, &bad, FALSE);
|
||||
client->errorValue = bad;
|
||||
if (err != Success)
|
||||
client->errorValue = bad;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -622,14 +622,19 @@ FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
|
|||
switch (ev->num_valuators) {
|
||||
case 6:
|
||||
ev->valuator5 = v->axisVal[first + 5];
|
||||
/* fallthrough */
|
||||
case 5:
|
||||
ev->valuator4 = v->axisVal[first + 4];
|
||||
/* fallthrough */
|
||||
case 4:
|
||||
ev->valuator3 = v->axisVal[first + 3];
|
||||
/* fallthrough */
|
||||
case 3:
|
||||
ev->valuator2 = v->axisVal[first + 2];
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
ev->valuator1 = v->axisVal[first + 1];
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
ev->valuator0 = v->axisVal[first];
|
||||
break;
|
||||
|
|
@ -668,8 +673,10 @@ FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
|
|||
switch (ev->num_valuators) {
|
||||
case 3:
|
||||
ev->valuator2 = v->axisVal[first + 2];
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
ev->valuator1 = v->axisVal[first + 1];
|
||||
/* fallthrough */
|
||||
case 1:
|
||||
ev->valuator0 = v->axisVal[first];
|
||||
break;
|
||||
|
|
@ -724,7 +731,7 @@ DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
|
|||
evcount += ((nval - 3) + 6)/6;
|
||||
}
|
||||
|
||||
BUG_RETURN(evcount <= ARRAY_SIZE(sev));
|
||||
BUG_RETURN(evcount > ARRAY_SIZE(sev));
|
||||
|
||||
FixDeviceStateNotify(dev, ev, k, b, v, first);
|
||||
|
||||
|
|
@ -733,7 +740,7 @@ DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
|
|||
(ev - 1)->deviceid |= MORE_EVENTS;
|
||||
bev->type = DeviceButtonStateNotify;
|
||||
bev->deviceid = dev->id;
|
||||
memcpy((char *) &bev->buttons[4], (char *) &b->down[4],
|
||||
memcpy((char *) &bev->buttons[0], (char *) &b->down[4],
|
||||
DOWN_LENGTH - 4);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -684,6 +684,8 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
|
|||
len += vallen * 4; /* valuators mask */
|
||||
|
||||
*xi = calloc(1, len);
|
||||
if (*xi == NULL)
|
||||
return BadAlloc;
|
||||
xde = (xXIDeviceEvent *) * xi;
|
||||
xde->type = GenericEvent;
|
||||
xde->extension = IReqCode;
|
||||
|
|
@ -734,7 +736,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
|
|||
|
||||
ptr += xde->buttons_len * 4;
|
||||
axisval = (FP3232 *) (ptr + xde->valuators_len * 4);
|
||||
for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) {
|
||||
for (i = 0; i < MAX_VALUATORS; i++) {
|
||||
if (BitIsOn(ev->valuators.mask, i)) {
|
||||
SetBit(ptr, i);
|
||||
*axisval = double_to_fp3232(ev->valuators.data[i]);
|
||||
|
|
@ -752,6 +754,8 @@ eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi)
|
|||
xXITouchOwnershipEvent *xtoe;
|
||||
|
||||
*xi = calloc(1, len);
|
||||
if (*xi == NULL)
|
||||
return BadAlloc;
|
||||
xtoe = (xXITouchOwnershipEvent *) * xi;
|
||||
xtoe->type = GenericEvent;
|
||||
xtoe->extension = IReqCode;
|
||||
|
|
@ -782,6 +786,8 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
|
|||
len += vallen * 4; /* valuators mask */
|
||||
|
||||
*xi = calloc(1, len);
|
||||
if (*xi == NULL)
|
||||
return BadAlloc;
|
||||
raw = (xXIRawEvent *) * xi;
|
||||
raw->type = GenericEvent;
|
||||
raw->extension = IReqCode;
|
||||
|
|
@ -797,7 +803,7 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
|
|||
ptr = (char *) &raw[1];
|
||||
axisval = (FP3232 *) (ptr + raw->valuators_len * 4);
|
||||
axisval_raw = axisval + nvals;
|
||||
for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) {
|
||||
for (i = 0; i < MAX_VALUATORS; i++) {
|
||||
if (BitIsOn(ev->valuators.mask, i)) {
|
||||
SetBit(ptr, i);
|
||||
*axisval = double_to_fp3232(ev->valuators.data[i]);
|
||||
|
|
@ -817,6 +823,8 @@ eventToBarrierEvent(BarrierEvent *ev, xEvent **xi)
|
|||
int len = sizeof(xXIBarrierEvent);
|
||||
|
||||
*xi = calloc(1, len);
|
||||
if (*xi == NULL)
|
||||
return BadAlloc;
|
||||
barrier = (xXIBarrierEvent*) *xi;
|
||||
barrier->type = GenericEvent;
|
||||
barrier->extension = IReqCode;
|
||||
|
|
@ -846,6 +854,8 @@ eventToGesturePinchEvent(GestureEvent *ev, xEvent **xi)
|
|||
xXIGesturePinchEvent *xpe;
|
||||
|
||||
*xi = calloc(1, len);
|
||||
if (*xi == NULL)
|
||||
return BadAlloc;
|
||||
xpe = (xXIGesturePinchEvent *) * xi;
|
||||
xpe->type = GenericEvent;
|
||||
xpe->extension = IReqCode;
|
||||
|
|
@ -888,6 +898,8 @@ eventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi)
|
|||
xXIGestureSwipeEvent *xde;
|
||||
|
||||
*xi = calloc(1, len);
|
||||
if (*xi == NULL)
|
||||
return BadAlloc;
|
||||
xde = (xXIGestureSwipeEvent *) * xi;
|
||||
xde->type = GenericEvent;
|
||||
xde->extension = IReqCode;
|
||||
|
|
|
|||
36
dix/events.c
36
dix/events.c
|
|
@ -1486,6 +1486,30 @@ ReattachToOldMaster(DeviceIntPtr dev)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current master keyboard or, if we're temporarily detached, the one
|
||||
* we've been attached to previously.
|
||||
*/
|
||||
static DeviceIntPtr
|
||||
CurrentOrOldMasterKeyboard(DeviceIntPtr dev)
|
||||
{
|
||||
DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
|
||||
|
||||
if (kbd)
|
||||
return kbd;
|
||||
|
||||
if (dev->saved_master_id) {
|
||||
dixLookupDevice(&kbd, dev->saved_master_id, serverClient, DixUseAccess);
|
||||
if (!kbd)
|
||||
return NULL;
|
||||
/* if dev is a pointer the saved master is a master pointer,
|
||||
* we want the keybard */
|
||||
return GetMaster(kbd, MASTER_KEYBOARD);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update touch records when an explicit grab is activated. Any touches owned by
|
||||
* the grabbing client are updated so the listener state reflects the new grab.
|
||||
|
|
@ -1713,6 +1737,10 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
|
|||
GrabInfoPtr grabinfo = &keybd->deviceGrab;
|
||||
GrabPtr oldgrab = grabinfo->grab;
|
||||
WindowPtr oldWin;
|
||||
DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd);
|
||||
|
||||
if (!master_keyboard)
|
||||
master_keyboard = inputInfo.keyboard;
|
||||
|
||||
/* slave devices need to float for the duration of the grab. */
|
||||
if (grab->grabtype == XI2 && keybd->enabled &&
|
||||
|
|
@ -1728,7 +1756,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
|
|||
else
|
||||
oldWin = keybd->spriteInfo->sprite->win;
|
||||
if (oldWin == FollowKeyboardWin)
|
||||
oldWin = keybd->focus->win;
|
||||
oldWin = master_keyboard->focus->win;
|
||||
if (keybd->valuator)
|
||||
keybd->valuator->motionHintWindow = NullWindow;
|
||||
if (oldWin &&
|
||||
|
|
@ -1759,6 +1787,10 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
|
|||
WindowPtr focusWin;
|
||||
Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
|
||||
keybd->deviceGrab.implicitGrab);
|
||||
DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd);
|
||||
|
||||
if (!master_keyboard)
|
||||
master_keyboard = inputInfo.keyboard;
|
||||
|
||||
if (keybd->valuator)
|
||||
keybd->valuator->motionHintWindow = NullWindow;
|
||||
|
|
@ -1779,7 +1811,7 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
|
|||
focusWin = NullWindow;
|
||||
|
||||
if (focusWin == FollowKeyboardWin)
|
||||
focusWin = inputInfo.keyboard->focus->win;
|
||||
focusWin = master_keyboard->focus->win;
|
||||
|
||||
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ AddExtension(const char *name, int NumEvents, int NumErrors,
|
|||
return ((ExtensionEntry *) NULL);
|
||||
}
|
||||
|
||||
ext = calloc(sizeof(ExtensionEntry), 1);
|
||||
ext = calloc(1, sizeof(ExtensionEntry));
|
||||
if (!ext)
|
||||
return NULL;
|
||||
if (!dixAllocatePrivates(&ext->devPrivates, PRIVATE_EXTENSION)) {
|
||||
|
|
|
|||
3
dix/gc.c
3
dix/gc.c
|
|
@ -813,7 +813,8 @@ CreateScratchGC(ScreenPtr pScreen, unsigned depth)
|
|||
FreeGC(pGC, (XID) 0);
|
||||
pGC = (GCPtr) NULL;
|
||||
}
|
||||
pGC->graphicsExposures = FALSE;
|
||||
else
|
||||
pGC->graphicsExposures = FALSE;
|
||||
return pGC;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ Equipment Corporation.
|
|||
#include <X11/fonts/libxfont2.h>
|
||||
#include "opaque.h"
|
||||
#include "servermd.h"
|
||||
#include "hotplug.h"
|
||||
#include "dixfont.h"
|
||||
#include "extnsionst.h"
|
||||
#include "privates.h"
|
||||
|
|
@ -157,7 +156,7 @@ dix_main(int argc, char *argv[], char *envp[])
|
|||
CreateWellKnownSockets();
|
||||
for (i = 1; i < LimitClients; i++)
|
||||
clients[i] = NullClient;
|
||||
serverClient = calloc(sizeof(ClientRec), 1);
|
||||
serverClient = calloc(1, sizeof(ClientRec));
|
||||
if (!serverClient)
|
||||
FatalError("couldn't create server client");
|
||||
InitClient(serverClient, 0, (void *) NULL);
|
||||
|
|
@ -235,6 +234,8 @@ dix_main(int argc, char *argv[], char *envp[])
|
|||
FatalError("could not open default cursor font");
|
||||
}
|
||||
|
||||
rootCursor = RefCursor(rootCursor);
|
||||
|
||||
#ifdef PANORAMIX
|
||||
/*
|
||||
* Consolidate window and colourmap information for each screen
|
||||
|
|
@ -275,6 +276,8 @@ dix_main(int argc, char *argv[], char *envp[])
|
|||
|
||||
Dispatch();
|
||||
|
||||
UnrefCursor(rootCursor);
|
||||
|
||||
UndisplayDevices();
|
||||
DisableAllDevices();
|
||||
|
||||
|
|
|
|||
|
|
@ -413,7 +413,7 @@ dixRegisterScreenPrivateKey(DevScreenPrivateKey screenKey, ScreenPtr pScreen,
|
|||
assert(key->type == type);
|
||||
return TRUE;
|
||||
}
|
||||
key = calloc(sizeof(DevPrivateKeyRec), 1);
|
||||
key = calloc(1, sizeof(DevPrivateKeyRec));
|
||||
if (!key)
|
||||
return FALSE;
|
||||
if (!dixRegisterPrivateKey(key, type, size)) {
|
||||
|
|
|
|||
|
|
@ -276,11 +276,13 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
|
|||
if (!pProp)
|
||||
return BadAlloc;
|
||||
data = malloc(totalSize);
|
||||
if (!data && len) {
|
||||
dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
|
||||
return BadAlloc;
|
||||
if (totalSize) {
|
||||
if (!data) {
|
||||
dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
|
||||
return BadAlloc;
|
||||
}
|
||||
memcpy(data, value, totalSize);
|
||||
}
|
||||
memcpy(data, value, totalSize);
|
||||
pProp->propertyName = property;
|
||||
pProp->type = type;
|
||||
pProp->format = format;
|
||||
|
|
@ -313,9 +315,11 @@ dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
|
|||
|
||||
if (mode == PropModeReplace) {
|
||||
data = malloc(totalSize);
|
||||
if (!data && len)
|
||||
return BadAlloc;
|
||||
memcpy(data, value, totalSize);
|
||||
if (totalSize) {
|
||||
if (!data)
|
||||
return BadAlloc;
|
||||
memcpy(data, value, totalSize);
|
||||
}
|
||||
pProp->data = data;
|
||||
pProp->size = len;
|
||||
pProp->type = type;
|
||||
|
|
@ -585,17 +589,20 @@ ProcListProperties(ClientPtr client)
|
|||
for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
|
||||
numProps++;
|
||||
|
||||
if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom))))
|
||||
return BadAlloc;
|
||||
if (numProps) {
|
||||
pAtoms = xallocarray(numProps, sizeof(Atom));
|
||||
if (!pAtoms)
|
||||
return BadAlloc;
|
||||
|
||||
numProps = 0;
|
||||
temppAtoms = pAtoms;
|
||||
for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
|
||||
realProp = pProp;
|
||||
rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
|
||||
if (rc == Success && realProp == pProp) {
|
||||
*temppAtoms++ = pProp->propertyName;
|
||||
numProps++;
|
||||
numProps = 0;
|
||||
temppAtoms = pAtoms;
|
||||
for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
|
||||
realProp = pProp;
|
||||
rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
|
||||
if (rc == Success && realProp == pProp) {
|
||||
*temppAtoms++ = pProp->propertyName;
|
||||
numProps++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -609,8 +616,8 @@ ProcListProperties(ClientPtr client)
|
|||
if (numProps) {
|
||||
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
|
||||
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
|
||||
free(pAtoms);
|
||||
}
|
||||
free(pAtoms);
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ InitPredictableAccelerationScheme(DeviceIntPtr dev,
|
|||
schemeData->vel = vel;
|
||||
scheme.accelData = schemeData;
|
||||
if (!InitializePredictableAccelerationProperties(dev, vel, schemeData)) {
|
||||
FreeVelocityData(vel);
|
||||
free(vel);
|
||||
free(schemeData);
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -685,7 +685,7 @@ HashResourceID(XID id, unsigned int numBits)
|
|||
id &= mask;
|
||||
if (numBits < 9)
|
||||
return (id ^ (id >> numBits) ^ (id >> (numBits<<1))) & ~((~0U) << numBits);
|
||||
return (id ^ (id >> numBits)) & ~((~0) << numBits);
|
||||
return (id ^ (id >> numBits)) & ~((~0U) << numBits);
|
||||
}
|
||||
|
||||
static XID
|
||||
|
|
|
|||
|
|
@ -16,7 +16,3 @@ if build_dri3
|
|||
dependencies: [ common_dep, libdrm_dep ],
|
||||
)
|
||||
endif
|
||||
|
||||
if build_xorg
|
||||
install_data(hdrs_dri3, install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
|||
820
exa/exa.h
820
exa/exa.h
|
|
@ -1,820 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Keith Packard
|
||||
* 2004 Eric Anholt
|
||||
* 2005 Zack Rusin
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Copyright holders make no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This is the header containing the public API of EXA for exa drivers.
|
||||
*/
|
||||
|
||||
#ifndef EXA_H
|
||||
#define EXA_H
|
||||
|
||||
#include "scrnintstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "gcstruct.h"
|
||||
#include "picturestr.h"
|
||||
#include "fb.h"
|
||||
|
||||
#define EXA_VERSION_MAJOR 2
|
||||
#define EXA_VERSION_MINOR 6
|
||||
#define EXA_VERSION_RELEASE 0
|
||||
|
||||
typedef struct _ExaOffscreenArea ExaOffscreenArea;
|
||||
|
||||
typedef void (*ExaOffscreenSaveProc) (ScreenPtr pScreen,
|
||||
ExaOffscreenArea * area);
|
||||
|
||||
typedef enum _ExaOffscreenState {
|
||||
ExaOffscreenAvail,
|
||||
ExaOffscreenRemovable,
|
||||
ExaOffscreenLocked
|
||||
} ExaOffscreenState;
|
||||
|
||||
struct _ExaOffscreenArea {
|
||||
int base_offset; /* allocation base */
|
||||
int offset; /* aligned offset */
|
||||
int size; /* total allocation size */
|
||||
unsigned last_use;
|
||||
void *privData;
|
||||
|
||||
ExaOffscreenSaveProc save;
|
||||
|
||||
ExaOffscreenState state;
|
||||
|
||||
ExaOffscreenArea *next;
|
||||
|
||||
unsigned eviction_cost;
|
||||
|
||||
ExaOffscreenArea *prev; /* Double-linked list for defragmentation */
|
||||
int align; /* required alignment */
|
||||
};
|
||||
|
||||
/**
|
||||
* The ExaDriver structure is allocated through exaDriverAlloc(), and then
|
||||
* fllled in by drivers.
|
||||
*/
|
||||
typedef struct _ExaDriver {
|
||||
/**
|
||||
* exa_major and exa_minor should be set by the driver to the version of
|
||||
* EXA which the driver was compiled for (or configures itself at runtime
|
||||
* to support). This allows EXA to extend the structure for new features
|
||||
* without breaking ABI for drivers compiled against older versions.
|
||||
*/
|
||||
int exa_major, exa_minor;
|
||||
|
||||
/**
|
||||
* memoryBase is the address of the beginning of framebuffer memory.
|
||||
* The visible screen should be within memoryBase to memoryBase +
|
||||
* memorySize.
|
||||
*/
|
||||
CARD8 *memoryBase;
|
||||
|
||||
/**
|
||||
* offScreenBase is the offset from memoryBase of the beginning of the area
|
||||
* to be managed by EXA's linear offscreen memory manager.
|
||||
*
|
||||
* In XFree86 DDX drivers, this is probably:
|
||||
* (pScrn->displayWidth * cpp * pScrn->virtualY)
|
||||
*/
|
||||
unsigned long offScreenBase;
|
||||
|
||||
/**
|
||||
* memorySize is the length (in bytes) of framebuffer memory beginning
|
||||
* from memoryBase.
|
||||
*
|
||||
* The offscreen memory manager will manage the area beginning at
|
||||
* (memoryBase + offScreenBase), with a length of (memorySize -
|
||||
* offScreenBase)
|
||||
*
|
||||
* In XFree86 DDX drivers, this is probably (pScrn->videoRam * 1024)
|
||||
*/
|
||||
unsigned long memorySize;
|
||||
|
||||
/**
|
||||
* pixmapOffsetAlign is the byte alignment necessary for pixmap offsets
|
||||
* within framebuffer.
|
||||
*
|
||||
* Hardware typically has a required alignment of offsets, which may or may
|
||||
* not be a power of two. EXA will ensure that pixmaps managed by the
|
||||
* offscreen memory manager meet this alignment requirement.
|
||||
*/
|
||||
int pixmapOffsetAlign;
|
||||
|
||||
/**
|
||||
* pixmapPitchAlign is the byte alignment necessary for pixmap pitches
|
||||
* within the framebuffer.
|
||||
*
|
||||
* Hardware typically has a required alignment of pitches for acceleration.
|
||||
* For 3D hardware, Composite acceleration often requires that source and
|
||||
* mask pixmaps (textures) have a power-of-two pitch, which can be demanded
|
||||
* using EXA_OFFSCREEN_ALIGN_POT. These pitch requirements only apply to
|
||||
* pixmaps managed by the offscreen memory manager. Thus, it is up to the
|
||||
* driver to ensure that the visible screen has an appropriate pitch for
|
||||
* acceleration.
|
||||
*/
|
||||
int pixmapPitchAlign;
|
||||
|
||||
/**
|
||||
* The flags field is bitfield of boolean values controlling EXA's behavior.
|
||||
*
|
||||
* The flags include EXA_OFFSCREEN_PIXMAPS, EXA_OFFSCREEN_ALIGN_POT, and
|
||||
* EXA_TWO_BITBLT_DIRECTIONS.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/** @{ */
|
||||
/**
|
||||
* maxX controls the X coordinate limitation for rendering from the card.
|
||||
* The driver should never receive a request for rendering beyond maxX
|
||||
* in the X direction from the origin of a pixmap.
|
||||
*/
|
||||
int maxX;
|
||||
|
||||
/**
|
||||
* maxY controls the Y coordinate limitation for rendering from the card.
|
||||
* The driver should never receive a request for rendering beyond maxY
|
||||
* in the Y direction from the origin of a pixmap.
|
||||
*/
|
||||
int maxY;
|
||||
/** @} */
|
||||
|
||||
/* private */
|
||||
ExaOffscreenArea *offScreenAreas;
|
||||
Bool needsSync;
|
||||
int lastMarker;
|
||||
|
||||
/** @name Solid
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* PrepareSolid() sets up the driver for doing a solid fill.
|
||||
* @param pPixmap Destination pixmap
|
||||
* @param alu raster operation
|
||||
* @param planemask write mask for the fill
|
||||
* @param fg "foreground" color for the fill
|
||||
*
|
||||
* This call should set up the driver for doing a series of solid fills
|
||||
* through the Solid() call. The alu raster op is one of the GX*
|
||||
* graphics functions listed in X.h, and typically maps to a similar
|
||||
* single-byte "ROP" setting in all hardware. The planemask controls
|
||||
* which bits of the destination should be affected, and will only represent
|
||||
* the bits up to the depth of pPixmap. The fg is the pixel value of the
|
||||
* foreground color referred to in ROP descriptions.
|
||||
*
|
||||
* Note that many drivers will need to store some of the data in the driver
|
||||
* private record, for sending to the hardware with each drawing command.
|
||||
*
|
||||
* The PrepareSolid() call is required of all drivers, but it may fail for any
|
||||
* reason. Failure results in a fallback to software rendering.
|
||||
*/
|
||||
Bool (*PrepareSolid) (PixmapPtr pPixmap,
|
||||
int alu, Pixel planemask, Pixel fg);
|
||||
|
||||
/**
|
||||
* Solid() performs a solid fill set up in the last PrepareSolid() call.
|
||||
*
|
||||
* @param pPixmap destination pixmap
|
||||
* @param x1 left coordinate
|
||||
* @param y1 top coordinate
|
||||
* @param x2 right coordinate
|
||||
* @param y2 bottom coordinate
|
||||
*
|
||||
* Performs the fill set up by the last PrepareSolid() call, covering the
|
||||
* area from (x1,y1) to (x2,y2) in pPixmap. Note that the coordinates are
|
||||
* in the coordinate space of the destination pixmap, so the driver will
|
||||
* need to set up the hardware's offset and pitch for the destination
|
||||
* coordinates according to the pixmap's offset and pitch within
|
||||
* framebuffer. This likely means using exaGetPixmapOffset() and
|
||||
* exaGetPixmapPitch().
|
||||
*
|
||||
* This call is required if PrepareSolid() ever succeeds.
|
||||
*/
|
||||
void (*Solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
|
||||
|
||||
/**
|
||||
* DoneSolid() finishes a set of solid fills.
|
||||
*
|
||||
* @param pPixmap destination pixmap.
|
||||
*
|
||||
* The DoneSolid() call is called at the end of a series of consecutive
|
||||
* Solid() calls following a successful PrepareSolid(). This allows drivers
|
||||
* to finish up emitting drawing commands that were buffered, or clean up
|
||||
* state from PrepareSolid().
|
||||
*
|
||||
* This call is required if PrepareSolid() ever succeeds.
|
||||
*/
|
||||
void (*DoneSolid) (PixmapPtr pPixmap);
|
||||
/** @} */
|
||||
|
||||
/** @name Copy
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* PrepareCopy() sets up the driver for doing a copy within video
|
||||
* memory.
|
||||
*
|
||||
* @param pSrcPixmap source pixmap
|
||||
* @param pDstPixmap destination pixmap
|
||||
* @param dx X copy direction
|
||||
* @param dy Y copy direction
|
||||
* @param alu raster operation
|
||||
* @param planemask write mask for the fill
|
||||
*
|
||||
* This call should set up the driver for doing a series of copies from the
|
||||
* the pSrcPixmap to the pDstPixmap. The dx flag will be positive if the
|
||||
* hardware should do the copy from the left to the right, and dy will be
|
||||
* positive if the copy should be done from the top to the bottom. This
|
||||
* is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap.
|
||||
* If your hardware can only support blits that are (left to right, top to
|
||||
* bottom) or (right to left, bottom to top), then you should set
|
||||
* #EXA_TWO_BITBLT_DIRECTIONS, and EXA will break down Copy operations to
|
||||
* ones that meet those requirements. The alu raster op is one of the GX*
|
||||
* graphics functions listed in X.h, and typically maps to a similar
|
||||
* single-byte "ROP" setting in all hardware. The planemask controls which
|
||||
* bits of the destination should be affected, and will only represent the
|
||||
* bits up to the depth of pPixmap.
|
||||
*
|
||||
* Note that many drivers will need to store some of the data in the driver
|
||||
* private record, for sending to the hardware with each drawing command.
|
||||
*
|
||||
* The PrepareCopy() call is required of all drivers, but it may fail for any
|
||||
* reason. Failure results in a fallback to software rendering.
|
||||
*/
|
||||
Bool (*PrepareCopy) (PixmapPtr pSrcPixmap,
|
||||
PixmapPtr pDstPixmap,
|
||||
int dx, int dy, int alu, Pixel planemask);
|
||||
|
||||
/**
|
||||
* Copy() performs a copy set up in the last PrepareCopy call.
|
||||
*
|
||||
* @param pDstPixmap destination pixmap
|
||||
* @param srcX source X coordinate
|
||||
* @param srcY source Y coordinate
|
||||
* @param dstX destination X coordinate
|
||||
* @param dstY destination Y coordinate
|
||||
* @param width width of the rectangle to be copied
|
||||
* @param height height of the rectangle to be copied.
|
||||
*
|
||||
* Performs the copy set up by the last PrepareCopy() call, copying the
|
||||
* rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source
|
||||
* pixmap to the same-sized rectangle at (dstX, dstY) in the destination
|
||||
* pixmap. Those rectangles may overlap in memory, if
|
||||
* pSrcPixmap == pDstPixmap. Note that this call does not receive the
|
||||
* pSrcPixmap as an argument -- if it's needed in this function, it should
|
||||
* be stored in the driver private during PrepareCopy(). As with Solid(),
|
||||
* the coordinates are in the coordinate space of each pixmap, so the driver
|
||||
* will need to set up source and destination pitches and offsets from those
|
||||
* pixmaps, probably using exaGetPixmapOffset() and exaGetPixmapPitch().
|
||||
*
|
||||
* This call is required if PrepareCopy ever succeeds.
|
||||
*/
|
||||
void (*Copy) (PixmapPtr pDstPixmap,
|
||||
int srcX,
|
||||
int srcY, int dstX, int dstY, int width, int height);
|
||||
|
||||
/**
|
||||
* DoneCopy() finishes a set of copies.
|
||||
*
|
||||
* @param pPixmap destination pixmap.
|
||||
*
|
||||
* The DoneCopy() call is called at the end of a series of consecutive
|
||||
* Copy() calls following a successful PrepareCopy(). This allows drivers
|
||||
* to finish up emitting drawing commands that were buffered, or clean up
|
||||
* state from PrepareCopy().
|
||||
*
|
||||
* This call is required if PrepareCopy() ever succeeds.
|
||||
*/
|
||||
void (*DoneCopy) (PixmapPtr pDstPixmap);
|
||||
/** @} */
|
||||
|
||||
/** @name Composite
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* CheckComposite() checks to see if a composite operation could be
|
||||
* accelerated.
|
||||
*
|
||||
* @param op Render operation
|
||||
* @param pSrcPicture source Picture
|
||||
* @param pMaskPicture mask picture
|
||||
* @param pDstPicture destination Picture
|
||||
*
|
||||
* The CheckComposite() call checks if the driver could handle acceleration
|
||||
* of op with the given source, mask, and destination pictures. This allows
|
||||
* drivers to check source and destination formats, supported operations,
|
||||
* transformations, and component alpha state, and send operations it can't
|
||||
* support to software rendering early on. This avoids costly pixmap
|
||||
* migration to the wrong places when the driver can't accelerate
|
||||
* operations. Note that because migration hasn't happened, the driver
|
||||
* can't know during CheckComposite() what the offsets and pitches of the
|
||||
* pixmaps are going to be.
|
||||
*
|
||||
* See PrepareComposite() for more details on likely issues that drivers
|
||||
* will have in accelerating Composite operations.
|
||||
*
|
||||
* The CheckComposite() call is recommended if PrepareComposite() is
|
||||
* implemented, but is not required.
|
||||
*/
|
||||
Bool (*CheckComposite) (int op,
|
||||
PicturePtr pSrcPicture,
|
||||
PicturePtr pMaskPicture, PicturePtr pDstPicture);
|
||||
|
||||
/**
|
||||
* PrepareComposite() sets up the driver for doing a Composite operation
|
||||
* described in the Render extension protocol spec.
|
||||
*
|
||||
* @param op Render operation
|
||||
* @param pSrcPicture source Picture
|
||||
* @param pMaskPicture mask picture
|
||||
* @param pDstPicture destination Picture
|
||||
* @param pSrc source pixmap
|
||||
* @param pMask mask pixmap
|
||||
* @param pDst destination pixmap
|
||||
*
|
||||
* This call should set up the driver for doing a series of Composite
|
||||
* operations, as described in the Render protocol spec, with the given
|
||||
* pSrcPicture, pMaskPicture, and pDstPicture. The pSrc, pMask, and
|
||||
* pDst are the pixmaps containing the pixel data, and should be used for
|
||||
* setting the offset and pitch used for the coordinate spaces for each of
|
||||
* the Pictures.
|
||||
*
|
||||
* Notes on interpreting Picture structures:
|
||||
* - The Picture structures will always have a valid pDrawable.
|
||||
* - The Picture structures will never have alphaMap set.
|
||||
* - The mask Picture (and therefore pMask) may be NULL, in which case the
|
||||
* operation is simply src OP dst instead of src IN mask OP dst, and
|
||||
* mask coordinates should be ignored.
|
||||
* - pMarkPicture may have componentAlpha set, which greatly changes
|
||||
* the behavior of the Composite operation. componentAlpha has no effect
|
||||
* when set on pSrcPicture or pDstPicture.
|
||||
* - The source and mask Pictures may have a transformation set
|
||||
* (Picture->transform != NULL), which means that the source coordinates
|
||||
* should be transformed by that transformation, resulting in scaling,
|
||||
* rotation, etc. The PictureTransformPoint() call can transform
|
||||
* coordinates for you. Transforms have no effect on Pictures when used
|
||||
* as a destination.
|
||||
* - The source and mask pictures may have a filter set. PictFilterNearest
|
||||
* and PictFilterBilinear are defined in the Render protocol, but others
|
||||
* may be encountered, and must be handled correctly (usually by
|
||||
* PrepareComposite failing, and falling back to software). Filters have
|
||||
* no effect on Pictures when used as a destination.
|
||||
* - The source and mask Pictures may have repeating set, which must be
|
||||
* respected. Many chipsets will be unable to support repeating on
|
||||
* pixmaps that have a width or height that is not a power of two.
|
||||
*
|
||||
* If your hardware can't support source pictures (textures) with
|
||||
* non-power-of-two pitches, you should set #EXA_OFFSCREEN_ALIGN_POT.
|
||||
*
|
||||
* Note that many drivers will need to store some of the data in the driver
|
||||
* private record, for sending to the hardware with each drawing command.
|
||||
*
|
||||
* The PrepareComposite() call is not required. However, it is highly
|
||||
* recommended for performance of antialiased font rendering and performance
|
||||
* of cairo applications. Failure results in a fallback to software
|
||||
* rendering.
|
||||
*/
|
||||
Bool (*PrepareComposite) (int op,
|
||||
PicturePtr pSrcPicture,
|
||||
PicturePtr pMaskPicture,
|
||||
PicturePtr pDstPicture,
|
||||
PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
|
||||
|
||||
/**
|
||||
* Composite() performs a Composite operation set up in the last
|
||||
* PrepareComposite() call.
|
||||
*
|
||||
* @param pDstPixmap destination pixmap
|
||||
* @param srcX source X coordinate
|
||||
* @param srcY source Y coordinate
|
||||
* @param maskX source X coordinate
|
||||
* @param maskY source Y coordinate
|
||||
* @param dstX destination X coordinate
|
||||
* @param dstY destination Y coordinate
|
||||
* @param width destination rectangle width
|
||||
* @param height destination rectangle height
|
||||
*
|
||||
* Performs the Composite operation set up by the last PrepareComposite()
|
||||
* call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height)
|
||||
* in the destination Pixmap. Note that if a transformation was set on
|
||||
* the source or mask Pictures, the source rectangles may not be the same
|
||||
* size as the destination rectangles and filtering. Getting the coordinate
|
||||
* transformation right at the subpixel level can be tricky, and rendercheck
|
||||
* can test this for you.
|
||||
*
|
||||
* This call is required if PrepareComposite() ever succeeds.
|
||||
*/
|
||||
void (*Composite) (PixmapPtr pDst,
|
||||
int srcX,
|
||||
int srcY,
|
||||
int maskX,
|
||||
int maskY, int dstX, int dstY, int width, int height);
|
||||
|
||||
/**
|
||||
* DoneComposite() finishes a set of Composite operations.
|
||||
*
|
||||
* @param pPixmap destination pixmap.
|
||||
*
|
||||
* The DoneComposite() call is called at the end of a series of consecutive
|
||||
* Composite() calls following a successful PrepareComposite(). This allows
|
||||
* drivers to finish up emitting drawing commands that were buffered, or
|
||||
* clean up state from PrepareComposite().
|
||||
*
|
||||
* This call is required if PrepareComposite() ever succeeds.
|
||||
*/
|
||||
void (*DoneComposite) (PixmapPtr pDst);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* UploadToScreen() loads a rectangle of data from src into pDst.
|
||||
*
|
||||
* @param pDst destination pixmap
|
||||
* @param x destination X coordinate.
|
||||
* @param y destination Y coordinate
|
||||
* @param width width of the rectangle to be copied
|
||||
* @param height height of the rectangle to be copied
|
||||
* @param src pointer to the beginning of the source data
|
||||
* @param src_pitch pitch (in bytes) of the lines of source data.
|
||||
*
|
||||
* UploadToScreen() copies data in system memory beginning at src (with
|
||||
* pitch src_pitch) into the destination pixmap from (x, y) to
|
||||
* (x + width, y + height). This is typically done with hostdata uploads,
|
||||
* where the CPU sets up a blit command on the hardware with instructions
|
||||
* that the blit data will be fed through some sort of aperture on the card.
|
||||
*
|
||||
* If UploadToScreen() is performed asynchronously, it is up to the driver
|
||||
* to call exaMarkSync(). This is in contrast to most other acceleration
|
||||
* calls in EXA.
|
||||
*
|
||||
* UploadToScreen() can aid in pixmap migration, but is most important for
|
||||
* the performance of exaGlyphs() (antialiased font drawing) by allowing
|
||||
* pipelining of data uploads, avoiding a sync of the card after each glyph.
|
||||
*
|
||||
* @return TRUE if the driver successfully uploaded the data. FALSE
|
||||
* indicates that EXA should fall back to doing the upload in software.
|
||||
*
|
||||
* UploadToScreen() is not required, but is recommended if Composite
|
||||
* acceleration is supported.
|
||||
*/
|
||||
Bool (*UploadToScreen) (PixmapPtr pDst,
|
||||
int x,
|
||||
int y, int w, int h, char *src, int src_pitch);
|
||||
|
||||
/**
|
||||
* UploadToScratch() is no longer used and will be removed next time the EXA
|
||||
* major version needs to be bumped.
|
||||
*/
|
||||
Bool (*UploadToScratch) (PixmapPtr pSrc, PixmapPtr pDst);
|
||||
|
||||
/**
|
||||
* DownloadFromScreen() loads a rectangle of data from pSrc into dst
|
||||
*
|
||||
* @param pSrc source pixmap
|
||||
* @param x source X coordinate.
|
||||
* @param y source Y coordinate
|
||||
* @param width width of the rectangle to be copied
|
||||
* @param height height of the rectangle to be copied
|
||||
* @param dst pointer to the beginning of the destination data
|
||||
* @param dst_pitch pitch (in bytes) of the lines of destination data.
|
||||
*
|
||||
* DownloadFromScreen() copies data from offscreen memory in pSrc from
|
||||
* (x, y) to (x + width, y + height), to system memory starting at
|
||||
* dst (with pitch dst_pitch). This would usually be done
|
||||
* using scatter-gather DMA, supported by a DRM call, or by blitting to AGP
|
||||
* and then synchronously reading from AGP. Because the implementation
|
||||
* might be synchronous, EXA leaves it up to the driver to call
|
||||
* exaMarkSync() if DownloadFromScreen() was asynchronous. This is in
|
||||
* contrast to most other acceleration calls in EXA.
|
||||
*
|
||||
* DownloadFromScreen() can aid in the largest bottleneck in pixmap
|
||||
* migration, which is the read from framebuffer when evicting pixmaps from
|
||||
* framebuffer memory. Thus, it is highly recommended, even though
|
||||
* implementations are typically complicated.
|
||||
*
|
||||
* @return TRUE if the driver successfully downloaded the data. FALSE
|
||||
* indicates that EXA should fall back to doing the download in software.
|
||||
*
|
||||
* DownloadFromScreen() is not required, but is highly recommended.
|
||||
*/
|
||||
Bool (*DownloadFromScreen) (PixmapPtr pSrc,
|
||||
int x, int y,
|
||||
int w, int h, char *dst, int dst_pitch);
|
||||
|
||||
/**
|
||||
* MarkSync() requests that the driver mark a synchronization point,
|
||||
* returning an driver-defined integer marker which could be requested for
|
||||
* synchronization to later in WaitMarker(). This might be used in the
|
||||
* future to avoid waiting for full hardware stalls before accessing pixmap
|
||||
* data with the CPU, but is not important in the current incarnation of
|
||||
* EXA.
|
||||
*
|
||||
* Note that drivers should call exaMarkSync() when they have done some
|
||||
* acceleration, rather than their own MarkSync() handler, as otherwise EXA
|
||||
* will be unaware of the driver's acceleration and not sync to it during
|
||||
* fallbacks.
|
||||
*
|
||||
* MarkSync() is optional.
|
||||
*/
|
||||
int (*MarkSync) (ScreenPtr pScreen);
|
||||
|
||||
/**
|
||||
* WaitMarker() waits for all rendering before the given marker to have
|
||||
* completed. If the driver does not implement MarkSync(), marker is
|
||||
* meaningless, and all rendering by the hardware should be completed before
|
||||
* WaitMarker() returns.
|
||||
*
|
||||
* Note that drivers should call exaWaitSync() to wait for all acceleration
|
||||
* to finish, as otherwise EXA will be unaware of the driver having
|
||||
* synchronized, resulting in excessive WaitMarker() calls.
|
||||
*
|
||||
* WaitMarker() is required of all drivers.
|
||||
*/
|
||||
void (*WaitMarker) (ScreenPtr pScreen, int marker);
|
||||
|
||||
/** @{ */
|
||||
/**
|
||||
* PrepareAccess() is called before CPU access to an offscreen pixmap.
|
||||
*
|
||||
* @param pPix the pixmap being accessed
|
||||
* @param index the index of the pixmap being accessed.
|
||||
*
|
||||
* PrepareAccess() will be called before CPU access to an offscreen pixmap.
|
||||
* This can be used to set up hardware surfaces for byteswapping or
|
||||
* untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
|
||||
* making CPU access use a different aperture.
|
||||
*
|
||||
* The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC,
|
||||
* #EXA_PREPARE_MASK, #EXA_PREPARE_AUX_DEST, #EXA_PREPARE_AUX_SRC, or
|
||||
* #EXA_PREPARE_AUX_MASK. Since only up to #EXA_NUM_PREPARE_INDICES pixmaps
|
||||
* will have PrepareAccess() called on them per operation, drivers can have
|
||||
* a small, statically-allocated space to maintain state for PrepareAccess()
|
||||
* and FinishAccess() in. Note that PrepareAccess() is only called once per
|
||||
* pixmap and operation, regardless of whether the pixmap is used as a
|
||||
* destination and/or source, and the index may not reflect the usage.
|
||||
*
|
||||
* PrepareAccess() may fail. An example might be the case of hardware that
|
||||
* can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
|
||||
* fails, EXA will migrate the pixmap to system memory.
|
||||
* DownloadFromScreen() must be implemented and must not fail if a driver
|
||||
* wishes to fail in PrepareAccess(). PrepareAccess() must not fail when
|
||||
* pPix is the visible screen, because the visible screen can not be
|
||||
* migrated.
|
||||
*
|
||||
* @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
|
||||
* drawing.
|
||||
* @return FALSE if PrepareAccess() is unsuccessful and EXA should use
|
||||
* DownloadFromScreen() to migate the pixmap out.
|
||||
*/
|
||||
Bool (*PrepareAccess) (PixmapPtr pPix, int index);
|
||||
|
||||
/**
|
||||
* FinishAccess() is called after CPU access to an offscreen pixmap.
|
||||
*
|
||||
* @param pPix the pixmap being accessed
|
||||
* @param index the index of the pixmap being accessed.
|
||||
*
|
||||
* FinishAccess() will be called after finishing CPU access of an offscreen
|
||||
* pixmap set up by PrepareAccess(). Note that the FinishAccess() will not be
|
||||
* called if PrepareAccess() failed and the pixmap was migrated out.
|
||||
*/
|
||||
void (*FinishAccess) (PixmapPtr pPix, int index);
|
||||
|
||||
/**
|
||||
* PixmapIsOffscreen() is an optional driver replacement to
|
||||
* exaPixmapHasGpuCopy(). Set to NULL if you want the standard behaviour
|
||||
* of exaPixmapHasGpuCopy().
|
||||
*
|
||||
* @param pPix the pixmap
|
||||
* @return TRUE if the given drawable is in framebuffer memory.
|
||||
*
|
||||
* exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
|
||||
* memory, meaning that acceleration could probably be done to it, and that it
|
||||
* will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
|
||||
* with the CPU.
|
||||
*
|
||||
*
|
||||
*/
|
||||
Bool (*PixmapIsOffscreen) (PixmapPtr pPix);
|
||||
|
||||
/** @name PrepareAccess() and FinishAccess() indices
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* EXA_PREPARE_DEST is the index for a pixmap that may be drawn to or
|
||||
* read from.
|
||||
*/
|
||||
#define EXA_PREPARE_DEST 0
|
||||
/**
|
||||
* EXA_PREPARE_SRC is the index for a pixmap that may be read from
|
||||
*/
|
||||
#define EXA_PREPARE_SRC 1
|
||||
/**
|
||||
* EXA_PREPARE_SRC is the index for a second pixmap that may be read
|
||||
* from.
|
||||
*/
|
||||
#define EXA_PREPARE_MASK 2
|
||||
/**
|
||||
* EXA_PREPARE_AUX* are additional indices for other purposes, e.g.
|
||||
* separate alpha maps with Composite operations.
|
||||
*/
|
||||
#define EXA_PREPARE_AUX_DEST 3
|
||||
#define EXA_PREPARE_AUX_SRC 4
|
||||
#define EXA_PREPARE_AUX_MASK 5
|
||||
#define EXA_NUM_PREPARE_INDICES 6
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* maxPitchPixels controls the pitch limitation for rendering from
|
||||
* the card.
|
||||
* The driver should never receive a request for rendering a pixmap
|
||||
* that has a pitch (in pixels) beyond maxPitchPixels.
|
||||
*
|
||||
* Setting this field is optional -- if your hardware doesn't have
|
||||
* a pitch limitation in pixels, don't set this. If neither this value
|
||||
* nor maxPitchBytes is set, then maxPitchPixels is set to maxX.
|
||||
* If set, it must not be smaller than maxX.
|
||||
*
|
||||
* @sa maxPitchBytes
|
||||
*/
|
||||
int maxPitchPixels;
|
||||
|
||||
/**
|
||||
* maxPitchBytes controls the pitch limitation for rendering from
|
||||
* the card.
|
||||
* The driver should never receive a request for rendering a pixmap
|
||||
* that has a pitch (in bytes) beyond maxPitchBytes.
|
||||
*
|
||||
* Setting this field is optional -- if your hardware doesn't have
|
||||
* a pitch limitation in bytes, don't set this.
|
||||
* If set, it must not be smaller than maxX * 4.
|
||||
* There's no default value for maxPitchBytes.
|
||||
*
|
||||
* @sa maxPitchPixels
|
||||
*/
|
||||
int maxPitchBytes;
|
||||
|
||||
/* Hooks to allow driver to its own pixmap memory management */
|
||||
void *(*CreatePixmap) (ScreenPtr pScreen, int size, int align);
|
||||
void (*DestroyPixmap) (ScreenPtr pScreen, void *driverPriv);
|
||||
/**
|
||||
* Returning a pixmap with non-NULL devPrivate.ptr implies a pixmap which is
|
||||
* not offscreen, which will never be accelerated and Prepare/FinishAccess won't
|
||||
* be called.
|
||||
*/
|
||||
Bool (*ModifyPixmapHeader) (PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData);
|
||||
|
||||
/* hooks for drivers with tiling support:
|
||||
* driver MUST fill out new_fb_pitch with valid pitch of pixmap
|
||||
*/
|
||||
void *(*CreatePixmap2) (ScreenPtr pScreen, int width, int height,
|
||||
int depth, int usage_hint, int bitsPerPixel,
|
||||
int *new_fb_pitch);
|
||||
/** @} */
|
||||
Bool (*SharePixmapBacking)(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p);
|
||||
|
||||
Bool (*SetSharedPixmapBacking)(PixmapPtr pPixmap, void *handle);
|
||||
|
||||
} ExaDriverRec, *ExaDriverPtr;
|
||||
|
||||
/** @name EXA driver flags
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* EXA_OFFSCREEN_PIXMAPS indicates to EXA that the driver can support
|
||||
* offscreen pixmaps.
|
||||
*/
|
||||
#define EXA_OFFSCREEN_PIXMAPS (1 << 0)
|
||||
|
||||
/**
|
||||
* EXA_OFFSCREEN_ALIGN_POT indicates to EXA that the driver needs pixmaps
|
||||
* to have a power-of-two pitch.
|
||||
*/
|
||||
#define EXA_OFFSCREEN_ALIGN_POT (1 << 1)
|
||||
|
||||
/**
|
||||
* EXA_TWO_BITBLT_DIRECTIONS indicates to EXA that the driver can only
|
||||
* support copies that are (left-to-right, top-to-bottom) or
|
||||
* (right-to-left, bottom-to-top).
|
||||
*/
|
||||
#define EXA_TWO_BITBLT_DIRECTIONS (1 << 2)
|
||||
|
||||
/**
|
||||
* EXA_HANDLES_PIXMAPS indicates to EXA that the driver can handle
|
||||
* all pixmap addressing and migration.
|
||||
*/
|
||||
#define EXA_HANDLES_PIXMAPS (1 << 3)
|
||||
|
||||
/**
|
||||
* EXA_SUPPORTS_PREPARE_AUX indicates to EXA that the driver can handle the
|
||||
* EXA_PREPARE_AUX* indices in the Prepare/FinishAccess hooks. If there are no
|
||||
* such hooks, this flag has no effect.
|
||||
*/
|
||||
#define EXA_SUPPORTS_PREPARE_AUX (1 << 4)
|
||||
|
||||
/**
|
||||
* EXA_SUPPORTS_OFFSCREEN_OVERLAPS indicates to EXA that the driver Copy hooks
|
||||
* can handle the source and destination occupying overlapping offscreen memory
|
||||
* areas. This allows the offscreen memory defragmentation code to defragment
|
||||
* areas where the defragmented position overlaps the fragmented position.
|
||||
*
|
||||
* Typically this is supported by traditional 2D engines but not by 3D engines.
|
||||
*/
|
||||
#define EXA_SUPPORTS_OFFSCREEN_OVERLAPS (1 << 5)
|
||||
|
||||
/**
|
||||
* EXA_MIXED_PIXMAPS will hide unacceleratable pixmaps from drivers and manage the
|
||||
* problem known software fallbacks like trapezoids. This only migrates pixmaps one way
|
||||
* into a driver pixmap and then pins it.
|
||||
*/
|
||||
#define EXA_MIXED_PIXMAPS (1 << 6)
|
||||
|
||||
/** @} */
|
||||
|
||||
/* in exa.c */
|
||||
extern _X_EXPORT ExaDriverPtr exaDriverAlloc(void);
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaDriverFini(ScreenPtr pScreen);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaMarkSync(ScreenPtr pScreen);
|
||||
extern _X_EXPORT void
|
||||
exaWaitSync(ScreenPtr pScreen);
|
||||
|
||||
extern _X_EXPORT unsigned long
|
||||
exaGetPixmapOffset(PixmapPtr pPix);
|
||||
|
||||
extern _X_EXPORT unsigned long
|
||||
exaGetPixmapPitch(PixmapPtr pPix);
|
||||
|
||||
extern _X_EXPORT unsigned long
|
||||
exaGetPixmapSize(PixmapPtr pPix);
|
||||
|
||||
extern _X_EXPORT void *exaGetPixmapDriverPrivate(PixmapPtr p);
|
||||
|
||||
/* in exa_offscreen.c */
|
||||
extern _X_EXPORT ExaOffscreenArea *exaOffscreenAlloc(ScreenPtr pScreen,
|
||||
int size, int align,
|
||||
Bool locked,
|
||||
ExaOffscreenSaveProc save,
|
||||
void *privData);
|
||||
|
||||
extern _X_EXPORT ExaOffscreenArea *exaOffscreenFree(ScreenPtr pScreen,
|
||||
ExaOffscreenArea * area);
|
||||
|
||||
extern _X_EXPORT void
|
||||
ExaOffscreenMarkUsed(PixmapPtr pPixmap);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaEnableDisableFBAccess(ScreenPtr pScreen, Bool enable);
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
exaDrawableIsOffscreen(DrawablePtr pDrawable);
|
||||
|
||||
/* in exa.c */
|
||||
extern _X_EXPORT void
|
||||
exaMoveInPixmap(PixmapPtr pPixmap);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaMoveOutPixmap(PixmapPtr pPixmap);
|
||||
|
||||
/* in exa_unaccel.c */
|
||||
extern _X_EXPORT CARD32
|
||||
exaGetPixmapFirstPixel(PixmapPtr pPixmap);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the given planemask covers all the significant bits in the
|
||||
* pixel values for pDrawable.
|
||||
*/
|
||||
#define EXA_PM_IS_SOLID(_pDrawable, _pm) \
|
||||
(((_pm) & FbFullMask((_pDrawable)->depth)) == \
|
||||
FbFullMask((_pDrawable)->depth))
|
||||
|
||||
#endif /* EXA_H */
|
||||
1297
exa/exa_accel.c
1297
exa/exa_accel.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,265 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
/* This file holds the classic exa specific implementation. */
|
||||
|
||||
static inline void *
|
||||
ExaGetPixmapAddress(PixmapPtr p)
|
||||
{
|
||||
ExaPixmapPriv(p);
|
||||
|
||||
if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
|
||||
return pExaPixmap->fb_ptr;
|
||||
else
|
||||
return pExaPixmap->sys_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*
|
||||
* If width and height are 0, this won't be a full-fledged pixmap and it will
|
||||
* get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
|
||||
* ModifyPixmapHeader() would break migration. These types of pixmaps are used
|
||||
* for scratch pixmaps, or to represent the visible screen.
|
||||
*/
|
||||
PixmapPtr
|
||||
exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint)
|
||||
{
|
||||
PixmapPtr pPixmap;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
BoxRec box;
|
||||
int bpp;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (w > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint);
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
|
||||
if (!pPixmap)
|
||||
return NULL;
|
||||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
/* Scratch pixmaps may have w/h equal to zero, and may not be
|
||||
* migrated.
|
||||
*/
|
||||
if (!w || !h)
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
else
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
|
||||
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
|
||||
pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
|
||||
|
||||
if (pExaPixmap->fb_pitch > 131071) {
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set up damage tracking */
|
||||
pExaPixmap->pDamage = DamageCreate(NULL, NULL,
|
||||
DamageReportNone, TRUE,
|
||||
pScreen, pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage == NULL) {
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
|
||||
/* This ensures that pending damage reflects the current operation. */
|
||||
/* This is used by exa to optimize migration. */
|
||||
DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
/* We set the initial pixmap as completely valid for a simple reason.
|
||||
* Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
|
||||
* could form single pixel rects as part of a region. Setting the complete region
|
||||
* as valid is a natural defragmentation of the region.
|
||||
*/
|
||||
box.x1 = 0;
|
||||
box.y1 = 0;
|
||||
box.x2 = w;
|
||||
box.y2 = h;
|
||||
RegionInit(&pExaPixmap->validSys, &box, 0);
|
||||
RegionInit(&pExaPixmap->validFB, &box, 0);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
/* During a fallback we must prepare access. */
|
||||
if (pExaScr->fallback_counter)
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
return pPixmap;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
ExaScreenPrivPtr pExaScr;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
Bool ret;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
pScreen = pPixmap->drawable.pScreen;
|
||||
pExaScr = ExaGetScreenPriv(pScreen);
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
if (pExaPixmap) {
|
||||
if (pPixData)
|
||||
pExaPixmap->sys_ptr = pPixData;
|
||||
|
||||
if (devKind > 0)
|
||||
pExaPixmap->sys_pitch = devKind;
|
||||
|
||||
/* Classic EXA:
|
||||
* - Framebuffer.
|
||||
* - Scratch pixmap with gpu memory.
|
||||
*/
|
||||
if (pExaScr->info->memoryBase && pPixData) {
|
||||
if ((CARD8 *) pPixData >= pExaScr->info->memoryBase &&
|
||||
((CARD8 *) pPixData - pExaScr->info->memoryBase) <
|
||||
pExaScr->info->memorySize) {
|
||||
pExaPixmap->fb_ptr = pPixData;
|
||||
pExaPixmap->fb_pitch = devKind;
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0 && bitsPerPixel > 0) {
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
}
|
||||
|
||||
/* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
|
||||
* gpu memory, so there's no need to track damage.
|
||||
*/
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind, pPixData);
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
|
||||
/* Always NULL this, we don't want lingering pointers. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
if (pPixmap->refcnt == 1) {
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaDestroyPixmap(pPixmap);
|
||||
|
||||
if (pExaPixmap->area) {
|
||||
DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
|
||||
(void *) pPixmap->drawable.id,
|
||||
ExaGetPixmapPriv(pPixmap)->area->offset,
|
||||
pPixmap->drawable.width, pPixmap->drawable.height));
|
||||
/* Free the offscreen area */
|
||||
exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area);
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
}
|
||||
RegionUninit(&pExaPixmap->validSys);
|
||||
RegionUninit(&pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
ret = pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
Bool ret;
|
||||
|
||||
if (pExaScr->info->PixmapIsOffscreen) {
|
||||
void *old_ptr = pPixmap->devPrivate.ptr;
|
||||
|
||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
||||
ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
|
||||
pPixmap->devPrivate.ptr = old_ptr;
|
||||
}
|
||||
else
|
||||
ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
230
exa/exa_driver.c
230
exa/exa_driver.c
|
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
/* This file holds the driver allocated pixmaps specific implementation. */
|
||||
|
||||
static inline void *
|
||||
ExaGetPixmapAddress(PixmapPtr p)
|
||||
{
|
||||
ExaPixmapPriv(p);
|
||||
|
||||
return pExaPixmap->sys_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*
|
||||
* Pixmaps are always marked as pinned, because exa has no control over them.
|
||||
*/
|
||||
PixmapPtr
|
||||
exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint)
|
||||
{
|
||||
PixmapPtr pPixmap;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
int bpp;
|
||||
size_t paddedWidth, datasize;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (w > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
|
||||
if (!pPixmap)
|
||||
return NULL;
|
||||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
/* Set this before driver hooks, to allow for driver pixmaps without gpu
|
||||
* memory to back it. These pixmaps have a valid pointer at all times.
|
||||
*/
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
if (pExaScr->info->CreatePixmap2) {
|
||||
int new_pitch = 0;
|
||||
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
|
||||
&new_pitch);
|
||||
paddedWidth = pExaPixmap->fb_pitch = new_pitch;
|
||||
}
|
||||
else {
|
||||
paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
|
||||
if (paddedWidth / 4 > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
if (paddedWidth < pExaPixmap->fb_pitch)
|
||||
paddedWidth = pExaPixmap->fb_pitch;
|
||||
datasize = h * paddedWidth;
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap(pScreen, datasize, 0);
|
||||
}
|
||||
|
||||
if (!pExaPixmap->driverPriv) {
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
|
||||
(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
|
||||
/* During a fallback we must prepare access. */
|
||||
if (pExaScr->fallback_counter)
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
return pPixmap;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
ExaScreenPrivPtr pExaScr;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
Bool ret;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
pScreen = pPixmap->drawable.pScreen;
|
||||
pExaScr = ExaGetScreenPriv(pScreen);
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
if (pExaPixmap) {
|
||||
if (pPixData)
|
||||
pExaPixmap->sys_ptr = pPixData;
|
||||
|
||||
if (devKind > 0)
|
||||
pExaPixmap->sys_pitch = devKind;
|
||||
|
||||
if (width > 0 && height > 0 && bitsPerPixel > 0) {
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
}
|
||||
}
|
||||
|
||||
if (pExaScr->info->ModifyPixmapHeader) {
|
||||
ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind,
|
||||
pPixData);
|
||||
/* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
|
||||
* If pPixmap->devPrivate.ptr is non-NULL, then we've got a
|
||||
* !has_gpu_copy pixmap. We need to store the pointer,
|
||||
* because PrepareAccess won't be called.
|
||||
*/
|
||||
if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
}
|
||||
if (ret == TRUE)
|
||||
goto out;
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind, pPixData);
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
|
||||
out:
|
||||
/* Always NULL this, we don't want lingering pointers. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_driver(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
if (pPixmap->refcnt == 1) {
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaDestroyPixmap(pPixmap);
|
||||
|
||||
if (pExaPixmap->driverPriv)
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
ret = pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
void *saved_ptr;
|
||||
Bool ret;
|
||||
|
||||
saved_ptr = pPixmap->devPrivate.ptr;
|
||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
||||
ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
|
||||
pPixmap->devPrivate.ptr = saved_ptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
839
exa/exa_glyphs.c
839
exa/exa_glyphs.c
|
|
@ -1,839 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
* Partly based on code Copyright © 2000 SuSE, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Owen Taylor <otaylor@fishsoup.net>
|
||||
* Based on code by: Keith Packard
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "glyphstr_priv.h"
|
||||
#include "mipict.h"
|
||||
|
||||
#if DEBUG_GLYPH_CACHE
|
||||
#define DBG_GLYPH_CACHE(a) ErrorF a
|
||||
#else
|
||||
#define DBG_GLYPH_CACHE(a)
|
||||
#endif
|
||||
|
||||
/* Width of the pixmaps we use for the caches; this should be less than
|
||||
* max texture size of the driver; this may need to actually come from
|
||||
* the driver.
|
||||
*/
|
||||
#define CACHE_PICTURE_WIDTH 1024
|
||||
|
||||
/* Maximum number of glyphs we buffer on the stack before flushing
|
||||
* rendering to the mask or destination surface.
|
||||
*/
|
||||
#define GLYPH_BUFFER_SIZE 256
|
||||
|
||||
typedef struct {
|
||||
PicturePtr mask;
|
||||
ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
|
||||
int count;
|
||||
} ExaGlyphBuffer, *ExaGlyphBufferPtr;
|
||||
|
||||
typedef enum {
|
||||
ExaGlyphSuccess, /* Glyph added to render buffer */
|
||||
ExaGlyphFail, /* out of memory, etc */
|
||||
ExaGlyphNeedFlush, /* would evict a glyph already in the buffer */
|
||||
} ExaGlyphCacheResult;
|
||||
|
||||
void
|
||||
exaGlyphsInit(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
int i = 0;
|
||||
|
||||
memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches));
|
||||
|
||||
pExaScr->glyphCaches[i].format = PICT_a8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
16;
|
||||
i++;
|
||||
pExaScr->glyphCaches[i].format = PICT_a8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
32;
|
||||
i++;
|
||||
pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
16;
|
||||
i++;
|
||||
pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
32;
|
||||
i++;
|
||||
|
||||
assert(i == EXA_NUM_GLYPH_CACHES);
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
pExaScr->glyphCaches[i].columns =
|
||||
CACHE_PICTURE_WIDTH / pExaScr->glyphCaches[i].glyphWidth;
|
||||
pExaScr->glyphCaches[i].size = 256;
|
||||
pExaScr->glyphCaches[i].hashSize = 557;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exaUnrealizeGlyphCaches(ScreenPtr pScreen, unsigned int format)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
|
||||
if (cache->format != format)
|
||||
continue;
|
||||
|
||||
if (cache->picture) {
|
||||
FreePicture((void *) cache->picture, (XID) 0);
|
||||
cache->picture = NULL;
|
||||
}
|
||||
|
||||
free(cache->hashEntries);
|
||||
cache->hashEntries = NULL;
|
||||
|
||||
free(cache->glyphs);
|
||||
cache->glyphs = NULL;
|
||||
cache->glyphCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
|
||||
|
||||
/* All caches for a single format share a single pixmap for glyph storage,
|
||||
* allowing mixing glyphs of different sizes without paying a penalty
|
||||
* for switching between mask pixmaps. (Note that for a size of font
|
||||
* right at the border between two sizes, we might be switching for almost
|
||||
* every glyph.)
|
||||
*
|
||||
* This function allocates the storage pixmap, and then fills in the
|
||||
* rest of the allocated structures for all caches with the given format.
|
||||
*/
|
||||
static Bool
|
||||
exaRealizeGlyphCaches(ScreenPtr pScreen, unsigned int format)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
int depth = PIXMAN_FORMAT_DEPTH(format);
|
||||
PictFormatPtr pPictFormat;
|
||||
PixmapPtr pPixmap;
|
||||
PicturePtr pPicture;
|
||||
CARD32 component_alpha;
|
||||
int height;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
pPictFormat = PictureMatchFormat(pScreen, depth, format);
|
||||
if (!pPictFormat)
|
||||
return FALSE;
|
||||
|
||||
/* Compute the total vertical size needed for the format */
|
||||
|
||||
height = 0;
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
int rows;
|
||||
|
||||
if (cache->format != format)
|
||||
continue;
|
||||
|
||||
cache->yOffset = height;
|
||||
|
||||
rows = (cache->size + cache->columns - 1) / cache->columns;
|
||||
height += rows * cache->glyphHeight;
|
||||
}
|
||||
|
||||
/* Now allocate the pixmap and picture */
|
||||
pPixmap = (*pScreen->CreatePixmap) (pScreen,
|
||||
CACHE_PICTURE_WIDTH, height, depth, 0);
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
component_alpha = NeedsComponent(pPictFormat->format);
|
||||
pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
|
||||
CPComponentAlpha, &component_alpha, serverClient,
|
||||
&error);
|
||||
|
||||
(*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
|
||||
|
||||
if (!pPicture)
|
||||
return FALSE;
|
||||
|
||||
/* And store the picture in all the caches for the format */
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
int j;
|
||||
|
||||
if (cache->format != format)
|
||||
continue;
|
||||
|
||||
cache->picture = pPicture;
|
||||
cache->picture->refcnt++;
|
||||
cache->hashEntries = xallocarray(cache->hashSize, sizeof(int));
|
||||
cache->glyphs = xallocarray(cache->size, sizeof(ExaCachedGlyphRec));
|
||||
cache->glyphCount = 0;
|
||||
|
||||
if (!cache->hashEntries || !cache->glyphs)
|
||||
goto bail;
|
||||
|
||||
for (j = 0; j < cache->hashSize; j++)
|
||||
cache->hashEntries[j] = -1;
|
||||
|
||||
cache->evictionPosition = rand() % cache->size;
|
||||
}
|
||||
|
||||
/* Each cache references the picture individually */
|
||||
FreePicture((void *) pPicture, (XID) 0);
|
||||
return TRUE;
|
||||
|
||||
bail:
|
||||
exaUnrealizeGlyphCaches(pScreen, format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
exaGlyphsFini(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
|
||||
if (cache->picture)
|
||||
exaUnrealizeGlyphCaches(pScreen, cache->format);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exaGlyphCacheHashLookup(ExaGlyphCachePtr cache, GlyphPtr pGlyph)
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
|
||||
|
||||
while (TRUE) { /* hash table can never be full */
|
||||
int entryPos = cache->hashEntries[slot];
|
||||
|
||||
if (entryPos == -1)
|
||||
return -1;
|
||||
|
||||
if (memcmp
|
||||
(pGlyph->sha1, cache->glyphs[entryPos].sha1,
|
||||
sizeof(pGlyph->sha1)) == 0) {
|
||||
return entryPos;
|
||||
}
|
||||
|
||||
slot--;
|
||||
if (slot < 0)
|
||||
slot = cache->hashSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphCacheHashInsert(ExaGlyphCachePtr cache, GlyphPtr pGlyph, int pos)
|
||||
{
|
||||
int slot;
|
||||
|
||||
memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
|
||||
|
||||
slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
|
||||
|
||||
while (TRUE) { /* hash table can never be full */
|
||||
if (cache->hashEntries[slot] == -1) {
|
||||
cache->hashEntries[slot] = pos;
|
||||
return;
|
||||
}
|
||||
|
||||
slot--;
|
||||
if (slot < 0)
|
||||
slot = cache->hashSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphCacheHashRemove(ExaGlyphCachePtr cache, int pos)
|
||||
{
|
||||
int slot;
|
||||
int emptiedSlot = -1;
|
||||
|
||||
slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
|
||||
|
||||
while (TRUE) { /* hash table can never be full */
|
||||
int entryPos = cache->hashEntries[slot];
|
||||
|
||||
if (entryPos == -1)
|
||||
return;
|
||||
|
||||
if (entryPos == pos) {
|
||||
cache->hashEntries[slot] = -1;
|
||||
emptiedSlot = slot;
|
||||
}
|
||||
else if (emptiedSlot != -1) {
|
||||
/* See if we can move this entry into the emptied slot, we can't
|
||||
* do that if if entry would have hashed between the current position
|
||||
* and the emptied slot. (taking wrapping into account). Bad positions
|
||||
* are:
|
||||
*
|
||||
* | XXXXXXXXXX |
|
||||
* i j
|
||||
*
|
||||
* |XXX XXXX|
|
||||
* j i
|
||||
*
|
||||
* i - slot, j - emptiedSlot
|
||||
*
|
||||
* (Knuth 6.4R)
|
||||
*/
|
||||
|
||||
int entrySlot =
|
||||
(*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
|
||||
|
||||
if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
|
||||
(emptiedSlot < slot &&
|
||||
(entrySlot < emptiedSlot || entrySlot >= slot)))) {
|
||||
cache->hashEntries[emptiedSlot] = entryPos;
|
||||
cache->hashEntries[slot] = -1;
|
||||
emptiedSlot = slot;
|
||||
}
|
||||
}
|
||||
|
||||
slot--;
|
||||
if (slot < 0)
|
||||
slot = cache->hashSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
|
||||
#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
|
||||
|
||||
/* The most efficient thing to way to upload the glyph to the screen
|
||||
* is to use the UploadToScreen() driver hook; this allows us to
|
||||
* pipeline glyph uploads and to avoid creating gpu backed pixmaps for
|
||||
* glyphs that we'll never use again.
|
||||
*
|
||||
* If we can't do it with UploadToScreen (because the glyph has a gpu copy,
|
||||
* etc), we fall back to CompositePicture.
|
||||
*
|
||||
* We need to damage the cache pixmap manually in either case because the damage
|
||||
* layer unwrapped the picture screen before calling exaGlyphs.
|
||||
*/
|
||||
static void
|
||||
exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
|
||||
ExaGlyphCachePtr cache, int x, int y, GlyphPtr pGlyph)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
PicturePtr pGlyphPicture = GetGlyphPicture(pGlyph, pScreen);
|
||||
PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;
|
||||
|
||||
ExaPixmapPriv(pGlyphPixmap);
|
||||
PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;
|
||||
|
||||
if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut ||
|
||||
pExaPixmap->accel_blocked)
|
||||
goto composite;
|
||||
|
||||
/* If the glyph pixmap is already uploaded, no point in doing
|
||||
* things this way */
|
||||
if (exaPixmapHasGpuCopy(pGlyphPixmap))
|
||||
goto composite;
|
||||
|
||||
/* UploadToScreen only works if bpp match */
|
||||
if (pGlyphPixmap->drawable.bitsPerPixel !=
|
||||
pCachePixmap->drawable.bitsPerPixel)
|
||||
goto composite;
|
||||
|
||||
if (pExaScr->do_migration) {
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
/* cache pixmap must have a gpu copy. */
|
||||
pixmaps[0].as_dst = TRUE;
|
||||
pixmaps[0].as_src = FALSE;
|
||||
pixmaps[0].pPix = pCachePixmap;
|
||||
pixmaps[0].pReg = NULL;
|
||||
exaDoMigration(pixmaps, 1, TRUE);
|
||||
}
|
||||
|
||||
if (!exaPixmapHasGpuCopy(pCachePixmap))
|
||||
goto composite;
|
||||
|
||||
/* x,y are in pixmap coordinates, no need for cache{X,Y}off */
|
||||
if (pExaScr->info->UploadToScreen(pCachePixmap,
|
||||
x,
|
||||
y,
|
||||
pGlyph->info.width,
|
||||
pGlyph->info.height,
|
||||
(char *) pExaPixmap->sys_ptr,
|
||||
pExaPixmap->sys_pitch))
|
||||
goto damage;
|
||||
|
||||
composite:
|
||||
CompositePicture(PictOpSrc,
|
||||
pGlyphPicture,
|
||||
None,
|
||||
cache->picture,
|
||||
0, 0, 0, 0, x, y, pGlyph->info.width, pGlyph->info.height);
|
||||
|
||||
damage:
|
||||
/* The cache pixmap isn't a window, so no need to offset coordinates. */
|
||||
exaPixmapDirty(pCachePixmap,
|
||||
x, y, x + cache->glyphWidth, y + cache->glyphHeight);
|
||||
}
|
||||
|
||||
static ExaGlyphCacheResult
|
||||
exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
|
||||
ExaGlyphCachePtr cache,
|
||||
ExaGlyphBufferPtr buffer,
|
||||
GlyphPtr pGlyph,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst)
|
||||
{
|
||||
ExaCompositeRectPtr rect;
|
||||
int pos;
|
||||
int x, y;
|
||||
|
||||
if (buffer->mask && buffer->mask != cache->picture)
|
||||
return ExaGlyphNeedFlush;
|
||||
|
||||
if (!cache->picture) {
|
||||
if (!exaRealizeGlyphCaches(pScreen, cache->format))
|
||||
return ExaGlyphFail;
|
||||
}
|
||||
|
||||
DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
|
||||
cache->glyphWidth, cache->glyphHeight,
|
||||
cache->format == PICT_a8 ? "A" : "ARGB",
|
||||
(long) *(CARD32 *) pGlyph->sha1));
|
||||
|
||||
pos = exaGlyphCacheHashLookup(cache, pGlyph);
|
||||
if (pos != -1) {
|
||||
DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
|
||||
x = CACHE_X(pos);
|
||||
y = CACHE_Y(pos);
|
||||
}
|
||||
else {
|
||||
if (cache->glyphCount < cache->size) {
|
||||
/* Space remaining; we fill from the start */
|
||||
pos = cache->glyphCount;
|
||||
x = CACHE_X(pos);
|
||||
y = CACHE_Y(pos);
|
||||
cache->glyphCount++;
|
||||
DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
|
||||
|
||||
exaGlyphCacheHashInsert(cache, pGlyph, pos);
|
||||
|
||||
}
|
||||
else {
|
||||
/* Need to evict an entry. We have to see if any glyphs
|
||||
* already in the output buffer were at this position in
|
||||
* the cache
|
||||
*/
|
||||
pos = cache->evictionPosition;
|
||||
x = CACHE_X(pos);
|
||||
y = CACHE_Y(pos);
|
||||
DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
|
||||
if (buffer->count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buffer->count; i++) {
|
||||
if (pSrc ?
|
||||
(buffer->rects[i].xMask == x &&
|
||||
buffer->rects[i].yMask ==
|
||||
y) : (buffer->rects[i].xSrc == x &&
|
||||
buffer->rects[i].ySrc == y)) {
|
||||
DBG_GLYPH_CACHE((" must flush buffer\n"));
|
||||
return ExaGlyphNeedFlush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, we're all set, swap in the new glyph */
|
||||
exaGlyphCacheHashRemove(cache, pos);
|
||||
exaGlyphCacheHashInsert(cache, pGlyph, pos);
|
||||
|
||||
/* And pick a new eviction position */
|
||||
cache->evictionPosition = rand() % cache->size;
|
||||
}
|
||||
|
||||
exaGlyphCacheUploadGlyph(pScreen, cache, x, y, pGlyph);
|
||||
}
|
||||
|
||||
buffer->mask = cache->picture;
|
||||
|
||||
rect = &buffer->rects[buffer->count];
|
||||
|
||||
if (pSrc) {
|
||||
rect->xSrc = xSrc;
|
||||
rect->ySrc = ySrc;
|
||||
rect->xMask = x;
|
||||
rect->yMask = y;
|
||||
}
|
||||
else {
|
||||
rect->xSrc = x;
|
||||
rect->ySrc = y;
|
||||
rect->xMask = 0;
|
||||
rect->yMask = 0;
|
||||
}
|
||||
|
||||
rect->pDst = pDst;
|
||||
rect->xDst = xDst;
|
||||
rect->yDst = yDst;
|
||||
rect->width = pGlyph->info.width;
|
||||
rect->height = pGlyph->info.height;
|
||||
|
||||
buffer->count++;
|
||||
|
||||
return ExaGlyphSuccess;
|
||||
}
|
||||
|
||||
#undef CACHE_X
|
||||
#undef CACHE_Y
|
||||
|
||||
static ExaGlyphCacheResult
|
||||
exaBufferGlyph(ScreenPtr pScreen,
|
||||
ExaGlyphBufferPtr buffer,
|
||||
GlyphPtr pGlyph,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
unsigned int format = (GetGlyphPicture(pGlyph, pScreen))->format;
|
||||
int width = pGlyph->info.width;
|
||||
int height = pGlyph->info.height;
|
||||
ExaCompositeRectPtr rect;
|
||||
PicturePtr mask;
|
||||
int i;
|
||||
|
||||
if (buffer->count == GLYPH_BUFFER_SIZE)
|
||||
return ExaGlyphNeedFlush;
|
||||
|
||||
if (PICT_FORMAT_BPP(format) == 1)
|
||||
format = PICT_a8;
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
|
||||
if (format == cache->format &&
|
||||
width <= cache->glyphWidth && height <= cache->glyphHeight) {
|
||||
ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen,
|
||||
&pExaScr->
|
||||
glyphCaches
|
||||
[i],
|
||||
buffer,
|
||||
pGlyph,
|
||||
pSrc,
|
||||
pDst,
|
||||
xSrc, ySrc,
|
||||
xMask, yMask,
|
||||
xDst, yDst);
|
||||
|
||||
switch (result) {
|
||||
case ExaGlyphFail:
|
||||
break;
|
||||
case ExaGlyphSuccess:
|
||||
case ExaGlyphNeedFlush:
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Couldn't find the glyph in the cache, use the glyph picture directly */
|
||||
|
||||
mask = GetGlyphPicture(pGlyph, pScreen);
|
||||
if (buffer->mask && buffer->mask != mask)
|
||||
return ExaGlyphNeedFlush;
|
||||
|
||||
buffer->mask = mask;
|
||||
|
||||
rect = &buffer->rects[buffer->count];
|
||||
rect->xSrc = xSrc;
|
||||
rect->ySrc = ySrc;
|
||||
rect->xMask = xMask;
|
||||
rect->yMask = yMask;
|
||||
rect->xDst = xDst;
|
||||
rect->yDst = yDst;
|
||||
rect->width = width;
|
||||
rect->height = height;
|
||||
|
||||
buffer->count++;
|
||||
|
||||
return ExaGlyphSuccess;
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphsToMask(PicturePtr pMask, ExaGlyphBufferPtr buffer)
|
||||
{
|
||||
exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask,
|
||||
buffer->count, buffer->rects);
|
||||
|
||||
buffer->count = 0;
|
||||
buffer->mask = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphsToDst(CARD8 op, PicturePtr pSrc, PicturePtr pDst, ExaGlyphBufferPtr buffer)
|
||||
{
|
||||
exaCompositeRects(op, pSrc, buffer->mask, pDst, buffer->count,
|
||||
buffer->rects);
|
||||
|
||||
buffer->count = 0;
|
||||
buffer->mask = NULL;
|
||||
}
|
||||
|
||||
/* Cut and paste from render/glyph.c - probably should export it instead */
|
||||
static void
|
||||
GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
int n;
|
||||
GlyphPtr glyph;
|
||||
int x, y;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
extents->x1 = MAXSHORT;
|
||||
extents->x2 = MINSHORT;
|
||||
extents->y1 = MAXSHORT;
|
||||
extents->y2 = MINSHORT;
|
||||
while (nlist--) {
|
||||
x += list->xOff;
|
||||
y += list->yOff;
|
||||
n = list->len;
|
||||
list++;
|
||||
while (n--) {
|
||||
glyph = *glyphs++;
|
||||
x1 = x - glyph->info.x;
|
||||
if (x1 < MINSHORT)
|
||||
x1 = MINSHORT;
|
||||
y1 = y - glyph->info.y;
|
||||
if (y1 < MINSHORT)
|
||||
y1 = MINSHORT;
|
||||
x2 = x1 + glyph->info.width;
|
||||
if (x2 > MAXSHORT)
|
||||
x2 = MAXSHORT;
|
||||
y2 = y1 + glyph->info.height;
|
||||
if (y2 > MAXSHORT)
|
||||
y2 = MAXSHORT;
|
||||
if (x1 < extents->x1)
|
||||
extents->x1 = x1;
|
||||
if (x2 > extents->x2)
|
||||
extents->x2 = x2;
|
||||
if (y1 < extents->y1)
|
||||
extents->y1 = y1;
|
||||
if (y2 > extents->y2)
|
||||
extents->y2 = y2;
|
||||
x += glyph->info.xOff;
|
||||
y += glyph->info.yOff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
|
||||
{
|
||||
PixmapPtr pMaskPixmap = 0;
|
||||
PicturePtr pMask = NULL;
|
||||
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
||||
int width = 0, height = 0;
|
||||
int x, y;
|
||||
int first_xOff = list->xOff, first_yOff = list->yOff;
|
||||
int n;
|
||||
GlyphPtr glyph;
|
||||
int error;
|
||||
BoxRec extents = { 0, 0, 0, 0 };
|
||||
CARD32 component_alpha;
|
||||
ExaGlyphBuffer buffer;
|
||||
|
||||
if (maskFormat) {
|
||||
ExaScreenPriv(pScreen);
|
||||
GCPtr pGC;
|
||||
xRectangle rect;
|
||||
|
||||
GlyphExtents(nlist, list, glyphs, &extents);
|
||||
|
||||
if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
|
||||
return;
|
||||
width = extents.x2 - extents.x1;
|
||||
height = extents.y2 - extents.y1;
|
||||
|
||||
if (maskFormat->depth == 1) {
|
||||
PictFormatPtr a8Format = PictureMatchFormat(pScreen, 8, PICT_a8);
|
||||
|
||||
if (a8Format)
|
||||
maskFormat = a8Format;
|
||||
}
|
||||
|
||||
pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
|
||||
maskFormat->depth,
|
||||
CREATE_PIXMAP_USAGE_SCRATCH);
|
||||
if (!pMaskPixmap)
|
||||
return;
|
||||
component_alpha = NeedsComponent(maskFormat->format);
|
||||
pMask = CreatePicture(0, &pMaskPixmap->drawable,
|
||||
maskFormat, CPComponentAlpha, &component_alpha,
|
||||
serverClient, &error);
|
||||
if (!pMask ||
|
||||
(!component_alpha && pExaScr->info->CheckComposite &&
|
||||
!(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask)))
|
||||
{
|
||||
PictFormatPtr argbFormat;
|
||||
|
||||
(*pScreen->DestroyPixmap) (pMaskPixmap);
|
||||
|
||||
if (!pMask)
|
||||
return;
|
||||
|
||||
/* The driver can't seem to composite to a8, let's try argb (but
|
||||
* without component-alpha) */
|
||||
FreePicture((void *) pMask, (XID) 0);
|
||||
|
||||
argbFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
|
||||
|
||||
if (argbFormat)
|
||||
maskFormat = argbFormat;
|
||||
|
||||
pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
|
||||
maskFormat->depth,
|
||||
CREATE_PIXMAP_USAGE_SCRATCH);
|
||||
if (!pMaskPixmap)
|
||||
return;
|
||||
|
||||
pMask = CreatePicture(0, &pMaskPixmap->drawable, maskFormat, 0, 0,
|
||||
serverClient, &error);
|
||||
if (!pMask) {
|
||||
(*pScreen->DestroyPixmap) (pMaskPixmap);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
|
||||
ValidateGC(&pMaskPixmap->drawable, pGC);
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
|
||||
FreeScratchGC(pGC);
|
||||
x = -extents.x1;
|
||||
y = -extents.y1;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
buffer.count = 0;
|
||||
buffer.mask = NULL;
|
||||
while (nlist--) {
|
||||
x += list->xOff;
|
||||
y += list->yOff;
|
||||
n = list->len;
|
||||
while (n--) {
|
||||
glyph = *glyphs++;
|
||||
|
||||
if (glyph->info.width > 0 && glyph->info.height > 0) {
|
||||
/* pGlyph->info.{x,y} compensate for empty space in the glyph. */
|
||||
if (maskFormat) {
|
||||
if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
|
||||
0, 0, 0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y) ==
|
||||
ExaGlyphNeedFlush) {
|
||||
exaGlyphsToMask(pMask, &buffer);
|
||||
exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
|
||||
0, 0, 0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
|
||||
xSrc + (x - glyph->info.x) - first_xOff,
|
||||
ySrc + (y - glyph->info.y) - first_yOff,
|
||||
0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y)
|
||||
== ExaGlyphNeedFlush) {
|
||||
exaGlyphsToDst(op, pSrc, pDst, &buffer);
|
||||
exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
|
||||
xSrc + (x - glyph->info.x) - first_xOff,
|
||||
ySrc + (y - glyph->info.y) - first_yOff,
|
||||
0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x += glyph->info.xOff;
|
||||
y += glyph->info.yOff;
|
||||
}
|
||||
list++;
|
||||
}
|
||||
|
||||
if (buffer.count) {
|
||||
if (maskFormat)
|
||||
exaGlyphsToMask(pMask, &buffer);
|
||||
else
|
||||
exaGlyphsToDst(op, pSrc, pDst, &buffer);
|
||||
}
|
||||
|
||||
if (maskFormat) {
|
||||
x = extents.x1;
|
||||
y = extents.y1;
|
||||
CompositePicture(op,
|
||||
pSrc,
|
||||
pMask,
|
||||
pDst,
|
||||
xSrc + x - first_xOff,
|
||||
ySrc + y - first_yOff, 0, 0, x, y, width, height);
|
||||
FreePicture((void *) pMask, (XID) 0);
|
||||
(*pScreen->DestroyPixmap) (pMaskPixmap);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,761 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Michel Dänzer <michel@tungstengraphics.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
#if DEBUG_MIGRATE
|
||||
#define DBG_MIGRATE(a) ErrorF a
|
||||
#else
|
||||
#define DBG_MIGRATE(a)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
|
||||
* and exaCopyDirtyToFb both needed to do this loop.
|
||||
*/
|
||||
static void
|
||||
exaMemcpyBox(PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
|
||||
CARD8 *dst, int dst_pitch)
|
||||
{
|
||||
int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
|
||||
int bytes = (pbox->x2 - pbox->x1) * cpp;
|
||||
|
||||
src += pbox->y1 * src_pitch + pbox->x1 * cpp;
|
||||
dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
|
||||
|
||||
for (i = pbox->y2 - pbox->y1; i; i--) {
|
||||
memcpy(dst, src, bytes);
|
||||
src += src_pitch;
|
||||
dst += dst_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the pixmap is dirty (has been modified in its current
|
||||
* location compared to the other), or lacks a private for tracking
|
||||
* dirtiness.
|
||||
*/
|
||||
static Bool
|
||||
exaPixmapIsDirty(PixmapPtr pPix)
|
||||
{
|
||||
ExaPixmapPriv(pPix);
|
||||
|
||||
if (pExaPixmap == NULL)
|
||||
EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
|
||||
|
||||
if (!pExaPixmap->pDamage)
|
||||
return FALSE;
|
||||
|
||||
return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
|
||||
!RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
|
||||
* to be considered "should be in framebuffer". That's just anything that has
|
||||
* had more acceleration than fallbacks, or has no score yet.
|
||||
*
|
||||
* Only valid if using a migration scheme that tracks score.
|
||||
*/
|
||||
static Bool
|
||||
exaPixmapShouldBeInFB(PixmapPtr pPix)
|
||||
{
|
||||
ExaPixmapPriv(pPix);
|
||||
|
||||
if (exaPixmapIsPinned(pPix))
|
||||
return TRUE;
|
||||
|
||||
return pExaPixmap->score >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* FB to system or vice versa. Both areas must be allocated.
|
||||
*/
|
||||
static void
|
||||
exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
|
||||
Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
|
||||
char *sys, int sys_pitch), int fallback_index,
|
||||
void (*sync) (ScreenPtr pScreen))
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
|
||||
RegionRec CopyReg;
|
||||
Bool save_use_gpu_copy;
|
||||
int save_pitch;
|
||||
BoxPtr pBox;
|
||||
int nbox;
|
||||
Bool access_prepared = FALSE;
|
||||
Bool need_sync = FALSE;
|
||||
|
||||
/* Damaged bits are valid in current copy but invalid in other one */
|
||||
if (pExaPixmap->use_gpu_copy) {
|
||||
RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
|
||||
RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
|
||||
}
|
||||
else {
|
||||
RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
|
||||
RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
|
||||
}
|
||||
|
||||
RegionEmpty(damage);
|
||||
|
||||
/* Copy bits valid in source but not in destination */
|
||||
RegionNull(&CopyReg);
|
||||
RegionSubtract(&CopyReg, pValidSrc, pValidDst);
|
||||
|
||||
if (migrate->as_dst) {
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
/* XXX: The pending damage region will be marked as damaged after the
|
||||
* operation, so it should serve as an upper bound for the region that
|
||||
* needs to be synchronized for the operation. Unfortunately, this
|
||||
* causes corruption in some cases, e.g. when starting compiz. See
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
|
||||
*/
|
||||
if (pExaScr->optimize_migration) {
|
||||
RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
|
||||
|
||||
#if DEBUG_MIGRATE
|
||||
if (RegionNil(pending_damage)) {
|
||||
static Bool firsttime = TRUE;
|
||||
|
||||
if (firsttime) {
|
||||
ErrorF("%s: Pending damage region empty!\n", __func__);
|
||||
firsttime = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Try to prevent destination valid region from growing too many
|
||||
* rects by filling it up to the extents of the union of the
|
||||
* destination valid region and the pending damage region.
|
||||
*/
|
||||
if (RegionNumRects(pValidDst) > 10) {
|
||||
BoxRec box;
|
||||
BoxPtr pValidExt, pDamageExt;
|
||||
RegionRec closure;
|
||||
|
||||
pValidExt = RegionExtents(pValidDst);
|
||||
pDamageExt = RegionExtents(pending_damage);
|
||||
|
||||
box.x1 = min(pValidExt->x1, pDamageExt->x1);
|
||||
box.y1 = min(pValidExt->y1, pDamageExt->y1);
|
||||
box.x2 = max(pValidExt->x2, pDamageExt->x2);
|
||||
box.y2 = max(pValidExt->y2, pDamageExt->y2);
|
||||
|
||||
RegionInit(&closure, &box, 0);
|
||||
RegionIntersect(&CopyReg, &CopyReg, &closure);
|
||||
}
|
||||
else
|
||||
RegionIntersect(&CopyReg, &CopyReg, pending_damage);
|
||||
}
|
||||
|
||||
/* The caller may provide a region to be subtracted from the calculated
|
||||
* dirty region. This is to avoid migration of bits that don't
|
||||
* contribute to the result of the operation.
|
||||
*/
|
||||
if (migrate->pReg)
|
||||
RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
|
||||
}
|
||||
else {
|
||||
/* The caller may restrict the region to be migrated for source pixmaps
|
||||
* to what's relevant for the operation.
|
||||
*/
|
||||
if (migrate->pReg)
|
||||
RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
|
||||
}
|
||||
|
||||
pBox = RegionRects(&CopyReg);
|
||||
nbox = RegionNumRects(&CopyReg);
|
||||
|
||||
save_use_gpu_copy = pExaPixmap->use_gpu_copy;
|
||||
save_pitch = pPixmap->devKind;
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
|
||||
while (nbox--) {
|
||||
pBox->x1 = max(pBox->x1, 0);
|
||||
pBox->y1 = max(pBox->y1, 0);
|
||||
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||
|
||||
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||
continue;
|
||||
|
||||
if (!transfer || !transfer(pPixmap,
|
||||
pBox->x1, pBox->y1,
|
||||
pBox->x2 - pBox->x1,
|
||||
pBox->y2 - pBox->y1,
|
||||
(char *) (pExaPixmap->sys_ptr
|
||||
+ pBox->y1 * pExaPixmap->sys_pitch
|
||||
+
|
||||
pBox->x1 *
|
||||
pPixmap->drawable.bitsPerPixel /
|
||||
8), pExaPixmap->sys_pitch)) {
|
||||
if (!access_prepared) {
|
||||
ExaDoPrepareAccess(pPixmap, fallback_index);
|
||||
access_prepared = TRUE;
|
||||
}
|
||||
if (fallback_index == EXA_PREPARE_DEST) {
|
||||
exaMemcpyBox(pPixmap, pBox,
|
||||
pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
|
||||
pPixmap->devPrivate.ptr, pPixmap->devKind);
|
||||
}
|
||||
else {
|
||||
exaMemcpyBox(pPixmap, pBox,
|
||||
pPixmap->devPrivate.ptr, pPixmap->devKind,
|
||||
pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
|
||||
}
|
||||
}
|
||||
else
|
||||
need_sync = TRUE;
|
||||
|
||||
pBox++;
|
||||
}
|
||||
|
||||
pExaPixmap->use_gpu_copy = save_use_gpu_copy;
|
||||
pPixmap->devKind = save_pitch;
|
||||
|
||||
/* Try to prevent source valid region from growing too many rects by
|
||||
* removing parts of it which are also in the destination valid region.
|
||||
* Removing anything beyond that would lead to data loss.
|
||||
*/
|
||||
if (RegionNumRects(pValidSrc) > 20)
|
||||
RegionSubtract(pValidSrc, pValidSrc, pValidDst);
|
||||
|
||||
/* The copied bits are now valid in destination */
|
||||
RegionUnion(pValidDst, pValidDst, &CopyReg);
|
||||
|
||||
RegionUninit(&CopyReg);
|
||||
|
||||
if (access_prepared)
|
||||
exaFinishAccess(&pPixmap->drawable, fallback_index);
|
||||
else if (need_sync && sync)
|
||||
sync(pPixmap->drawable.pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* the framebuffer memory copy to the system memory copy. Both areas must be
|
||||
* allocated.
|
||||
*/
|
||||
void
|
||||
exaCopyDirtyToSys(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
|
||||
pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
|
||||
exaWaitSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* the system memory copy to the framebuffer memory copy. Both areas must be
|
||||
* allocated.
|
||||
*/
|
||||
void
|
||||
exaCopyDirtyToFb(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
|
||||
pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a framebuffer copy of the pixmap if necessary, and then copies
|
||||
* any necessary pixmap data into the framebuffer copy and points the pixmap at
|
||||
* it.
|
||||
*
|
||||
* Note that when first allocated, a pixmap will have FALSE dirty flag.
|
||||
* This is intentional because pixmap data starts out undefined. So if we move
|
||||
* it in due to the first operation against it being accelerated, it will have
|
||||
* undefined framebuffer contents that we didn't have to upload. If we do
|
||||
* moveouts (and moveins) after the first movein, then we will only have to copy
|
||||
* back and forth if the pixmap was written to after the last synchronization of
|
||||
* the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
|
||||
* we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
|
||||
* all the data, since it's almost surely all valid now.
|
||||
*/
|
||||
static void
|
||||
exaDoMoveInPixmap(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
/* If we're VT-switched away, no touching card memory allowed. */
|
||||
if (pExaScr->swappedOut)
|
||||
return;
|
||||
|
||||
/* If we're not allowed to move, then fail. */
|
||||
if (exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
/* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
|
||||
* fragility in EXA, and <8bpp is probably not used enough any more to care
|
||||
* (at least, not in acceleratd paths).
|
||||
*/
|
||||
if (pPixmap->drawable.bitsPerPixel < 8)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->accel_blocked)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->area == NULL) {
|
||||
pExaPixmap->area =
|
||||
exaOffscreenAlloc(pScreen, pExaPixmap->fb_size,
|
||||
pExaScr->info->pixmapOffsetAlign, FALSE,
|
||||
exaPixmapSave, (void *) pPixmap);
|
||||
if (pExaPixmap->area == NULL)
|
||||
return;
|
||||
|
||||
pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
|
||||
pExaPixmap->area->offset;
|
||||
}
|
||||
|
||||
exaCopyDirtyToFb(migrate);
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap))
|
||||
return;
|
||||
|
||||
DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
|
||||
(ExaGetPixmapPriv(pPixmap)->area ?
|
||||
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height,
|
||||
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
|
||||
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
|
||||
void
|
||||
exaMoveInPixmap_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
|
||||
.pReg = NULL
|
||||
};
|
||||
|
||||
migrate.pPix = pPixmap;
|
||||
exaDoMoveInPixmap(&migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the current active location of the pixmap to system memory, copying
|
||||
* updated data out if necessary.
|
||||
*/
|
||||
static void
|
||||
exaDoMoveOutPixmap(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
exaCopyDirtyToSys(migrate);
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap)) {
|
||||
|
||||
DBG_MIGRATE(("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
|
||||
(void *) (ExaGetPixmapPriv(pPixmap)->area ?
|
||||
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height,
|
||||
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
|
||||
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaMoveOutPixmap_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
|
||||
.pReg = NULL
|
||||
};
|
||||
|
||||
migrate.pPix = pPixmap;
|
||||
exaDoMoveOutPixmap(&migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies out important pixmap data and removes references to framebuffer area.
|
||||
* Called when the memory manager decides it's time to kick the pixmap out of
|
||||
* framebuffer entirely.
|
||||
*/
|
||||
void
|
||||
exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area)
|
||||
{
|
||||
PixmapPtr pPixmap = area->privData;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaMoveOutPixmap(pPixmap);
|
||||
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
/* Mark all FB bits as invalid, so all valid system bits get copied to FB
|
||||
* next time */
|
||||
RegionEmpty(&pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the "greedy" migration scheme, pushes the pixmap toward being located in
|
||||
* framebuffer memory.
|
||||
*/
|
||||
static void
|
||||
exaMigrateTowardFb(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
|
||||
DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
|
||||
(void *) pPixmap));
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_MIGRATE(("UseScreen %p score %d\n",
|
||||
(void *) pPixmap, pExaPixmap->score));
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
|
||||
exaDoMoveInPixmap(migrate);
|
||||
pExaPixmap->score = 0;
|
||||
}
|
||||
|
||||
if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
|
||||
pExaPixmap->score++;
|
||||
|
||||
if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
|
||||
!exaPixmapHasGpuCopy(pPixmap)) {
|
||||
exaDoMoveInPixmap(migrate);
|
||||
}
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap)) {
|
||||
exaCopyDirtyToFb(migrate);
|
||||
ExaOffscreenMarkUsed(pPixmap);
|
||||
}
|
||||
else
|
||||
exaCopyDirtyToSys(migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the "greedy" migration scheme, pushes the pixmap toward being located in
|
||||
* system memory.
|
||||
*/
|
||||
static void
|
||||
exaMigrateTowardSys(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
DBG_MIGRATE(("UseMem: %p score %d\n", (void *) pPixmap,
|
||||
pExaPixmap->score));
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
|
||||
pExaPixmap->score = 0;
|
||||
|
||||
if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
|
||||
pExaPixmap->score--;
|
||||
|
||||
if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
|
||||
exaDoMoveOutPixmap(migrate);
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap)) {
|
||||
exaCopyDirtyToFb(migrate);
|
||||
ExaOffscreenMarkUsed(pPixmap);
|
||||
}
|
||||
else
|
||||
exaCopyDirtyToSys(migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap has both a framebuffer and system memory copy, this function
|
||||
* asserts that both of them are the same.
|
||||
*/
|
||||
static Bool
|
||||
exaAssertNotDirty(PixmapPtr pPixmap)
|
||||
{
|
||||
ExaPixmapPriv(pPixmap);
|
||||
CARD8 *dst, *src;
|
||||
RegionRec ValidReg;
|
||||
int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
|
||||
BoxPtr pBox;
|
||||
Bool ret = TRUE, save_use_gpu_copy;
|
||||
|
||||
if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
|
||||
return ret;
|
||||
|
||||
RegionNull(&ValidReg);
|
||||
RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys);
|
||||
nbox = RegionNumRects(&ValidReg);
|
||||
|
||||
if (!nbox)
|
||||
goto out;
|
||||
|
||||
pBox = RegionRects(&ValidReg);
|
||||
|
||||
dst_pitch = pExaPixmap->sys_pitch;
|
||||
src_pitch = pExaPixmap->fb_pitch;
|
||||
cpp = pPixmap->drawable.bitsPerPixel / 8;
|
||||
|
||||
save_use_gpu_copy = pExaPixmap->use_gpu_copy;
|
||||
save_pitch = pPixmap->devKind;
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
|
||||
if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
|
||||
goto skip;
|
||||
|
||||
while (nbox--) {
|
||||
int rowbytes;
|
||||
|
||||
pBox->x1 = max(pBox->x1, 0);
|
||||
pBox->y1 = max(pBox->y1, 0);
|
||||
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||
|
||||
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||
continue;
|
||||
|
||||
rowbytes = (pBox->x2 - pBox->x1) * cpp;
|
||||
src =
|
||||
(CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch +
|
||||
pBox->x1 * cpp;
|
||||
dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
|
||||
|
||||
for (y = pBox->y1; y < pBox->y2;
|
||||
y++, src += src_pitch, dst += dst_pitch) {
|
||||
if (memcmp(dst, src, rowbytes) != 0) {
|
||||
ret = FALSE;
|
||||
exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||
|
||||
pExaPixmap->use_gpu_copy = save_use_gpu_copy;
|
||||
pPixmap->devKind = save_pitch;
|
||||
|
||||
out:
|
||||
RegionUninit(&ValidReg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs migration of the pixmaps according to the operation information
|
||||
* provided in pixmaps and can_accel and the migration scheme chosen in the
|
||||
* config file.
|
||||
*/
|
||||
void
|
||||
exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
|
||||
{
|
||||
ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
int i, j;
|
||||
|
||||
/* If this debugging flag is set, check each pixmap for whether it is marked
|
||||
* as clean, and if so, actually check if that's the case. This should help
|
||||
* catch issues with failing to mark a drawable as dirty. While it will
|
||||
* catch them late (after the operation happened), it at least explains what
|
||||
* went wrong, and instrumenting the code to find what operation happened
|
||||
* to the pixmap last shouldn't be hard.
|
||||
*/
|
||||
if (pExaScr->checkDirtyCorrectness) {
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (!exaPixmapIsDirty(pixmaps[i].pPix) &&
|
||||
!exaAssertNotDirty(pixmaps[i].pPix))
|
||||
ErrorF("%s: Pixmap %d dirty but not marked as such!\n",
|
||||
__func__, i);
|
||||
}
|
||||
}
|
||||
/* If anything is pinned in system memory, we won't be able to
|
||||
* accelerate.
|
||||
*/
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (exaPixmapIsPinned(pixmaps[i].pPix) &&
|
||||
!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
|
||||
pixmaps[i].pPix->drawable.width,
|
||||
pixmaps[i].pPix->drawable.height));
|
||||
can_accel = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pExaScr->migration == ExaMigrationSmart) {
|
||||
/* If we've got something as a destination that we shouldn't cause to
|
||||
* become newly dirtied, take the unaccelerated route.
|
||||
*/
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB(pixmaps[i].pPix) &&
|
||||
!exaPixmapIsDirty(pixmaps[i].pPix)) {
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (!exaPixmapIsDirty(pixmaps[i].pPix))
|
||||
exaDoMoveOutPixmap(pixmaps + i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we aren't going to accelerate, then we migrate everybody toward
|
||||
* system memory, and kick out if it's free.
|
||||
*/
|
||||
if (!can_accel) {
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
exaMigrateTowardSys(pixmaps + i);
|
||||
if (!exaPixmapIsDirty(pixmaps[i].pPix))
|
||||
exaDoMoveOutPixmap(pixmaps + i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finally, the acceleration path. Move them all in. */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
exaMigrateTowardFb(pixmaps + i);
|
||||
exaDoMoveInPixmap(pixmaps + i);
|
||||
}
|
||||
}
|
||||
else if (pExaScr->migration == ExaMigrationGreedy) {
|
||||
/* If we can't accelerate, either because the driver can't or because one of
|
||||
* the pixmaps is pinned in system memory, then we migrate everybody toward
|
||||
* system memory.
|
||||
*
|
||||
* We also migrate toward system if all pixmaps involved are currently in
|
||||
* system memory -- this can mitigate thrashing when there are significantly
|
||||
* more pixmaps active than would fit in memory.
|
||||
*
|
||||
* If not, then we migrate toward FB so that hopefully acceleration can
|
||||
* happen.
|
||||
*/
|
||||
if (!can_accel) {
|
||||
for (i = 0; i < npixmaps; i++)
|
||||
exaMigrateTowardSys(pixmaps + i);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
/* Found one in FB, so move all to FB. */
|
||||
for (j = 0; j < npixmaps; j++)
|
||||
exaMigrateTowardFb(pixmaps + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nobody's in FB, so move all away from FB. */
|
||||
for (i = 0; i < npixmaps; i++)
|
||||
exaMigrateTowardSys(pixmaps + i);
|
||||
}
|
||||
else if (pExaScr->migration == ExaMigrationAlways) {
|
||||
/* Always move the pixmaps out if we can't accelerate. If we can
|
||||
* accelerate, try to move them all in. If that fails, then move them
|
||||
* back out.
|
||||
*/
|
||||
if (!can_accel) {
|
||||
for (i = 0; i < npixmaps; i++)
|
||||
exaDoMoveOutPixmap(pixmaps + i);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now, try to move them all into FB */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
exaDoMoveInPixmap(pixmaps + i);
|
||||
}
|
||||
|
||||
/* If we couldn't fit everything in, abort */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Yay, everything has a gpu copy, mark memory as used */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
ExaOffscreenMarkUsed(pixmaps[i].pPix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
|
||||
{
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
|
||||
pixmaps[0].as_dst = TRUE;
|
||||
pixmaps[0].as_src = FALSE;
|
||||
}
|
||||
else {
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
}
|
||||
pixmaps[0].pPix = pPixmap;
|
||||
pixmaps[0].pReg = pReg;
|
||||
|
||||
exaDoMigration(pixmaps, 1, FALSE);
|
||||
|
||||
(void) ExaDoPrepareAccess(pPixmap, index);
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
void
|
||||
exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
|
||||
int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
|
||||
int usage_hint = pPixmap->usage_hint;
|
||||
int paddedWidth = pExaPixmap->sys_pitch;
|
||||
|
||||
/* Already done. */
|
||||
if (pExaPixmap->driverPriv)
|
||||
return;
|
||||
|
||||
if (exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
/* Can't accel 1/4 bpp. */
|
||||
if (pExaPixmap->accel_blocked || bpp < 8)
|
||||
return;
|
||||
|
||||
if (pExaScr->info->CreatePixmap2) {
|
||||
int new_pitch = 0;
|
||||
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
|
||||
&new_pitch);
|
||||
paddedWidth = pExaPixmap->fb_pitch = new_pitch;
|
||||
}
|
||||
else {
|
||||
if (paddedWidth < pExaPixmap->fb_pitch)
|
||||
paddedWidth = pExaPixmap->fb_pitch;
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap(pScreen, paddedWidth * h, 0);
|
||||
}
|
||||
|
||||
if (!pExaPixmap->driverPriv)
|
||||
return;
|
||||
|
||||
(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If anything is pinned in system memory, we won't be able to
|
||||
* accelerate.
|
||||
*/
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (exaPixmapIsPinned(pixmaps[i].pPix) &&
|
||||
!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
can_accel = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can do nothing. */
|
||||
if (!can_accel)
|
||||
return;
|
||||
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
PixmapPtr pPixmap = pixmaps[i].pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
if (!pExaPixmap->driverPriv)
|
||||
exaCreateDriverPixmap_mixed(pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
/* This pitch is needed for proper acceleration. For some reason
|
||||
* there are pixmaps without pDamage and a bad fb_pitch value.
|
||||
* So setting devKind when only exaPixmapHasGpuCopy() is true
|
||||
* causes corruption. Pixmaps without pDamage are not migrated
|
||||
* and should have a valid devKind at all times, so that's why this
|
||||
* isn't causing problems. Pixmaps have their gpu pitch set the
|
||||
* first time in the MPH call from exaCreateDriverPixmap_mixed().
|
||||
*/
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
exaCopyDirtyToFb(pixmaps + i);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap == pPixmap &&
|
||||
!pixmaps[i].as_dst && !pixmaps[i].pReg)
|
||||
pExaScr->deferred_mixed_pixmap = NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaMoveInPixmap_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
pixmaps[0].pPix = pPixmap;
|
||||
pixmaps[0].pReg = NULL;
|
||||
|
||||
exaDoMigration(pixmaps, 1, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
|
||||
{
|
||||
PixmapPtr pPixmap = closure;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
/* Move back results of software rendering on system memory copy of mixed driver
|
||||
* pixmap (see exaPrepareAccessReg_mixed).
|
||||
*
|
||||
* Defer moving the destination back into the driver pixmap, to try and save
|
||||
* overhead on multiple subsequent software fallbacks.
|
||||
*/
|
||||
if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap &&
|
||||
pExaScr->deferred_mixed_pixmap != pPixmap)
|
||||
exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
|
||||
pExaScr->deferred_mixed_pixmap = pPixmap;
|
||||
}
|
||||
}
|
||||
|
||||
/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
|
||||
* use the DownloadFromScreen hook to retrieve contents to a copy in system
|
||||
* memory, perform software rendering on that and move back the results with the
|
||||
* UploadToScreen hook (see exaDamageReport_mixed).
|
||||
*/
|
||||
void
|
||||
exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
|
||||
{
|
||||
ExaPixmapPriv(pPixmap);
|
||||
Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
Bool success;
|
||||
|
||||
success = ExaDoPrepareAccess(pPixmap, index);
|
||||
|
||||
if (success && has_gpu_copy && pExaPixmap->pDamage) {
|
||||
/* You cannot do accelerated operations while a buffer is mapped. */
|
||||
exaFinishAccess(&pPixmap->drawable, index);
|
||||
/* Update the gpu view of both deferred destination pixmaps and of
|
||||
* source pixmaps that were migrated with a bounding region.
|
||||
*/
|
||||
exaMoveInPixmap_mixed(pPixmap);
|
||||
success = ExaDoPrepareAccess(pPixmap, index);
|
||||
|
||||
if (success) {
|
||||
/* We have a gpu pixmap that can be accessed, we don't need the cpu
|
||||
* copy anymore. Drivers that prefer DFS, should fail prepare
|
||||
* access.
|
||||
*/
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
|
||||
free(pExaPixmap->sys_ptr);
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
/* Do we need to allocate our system buffer? */
|
||||
if (!pExaPixmap->sys_ptr) {
|
||||
pExaPixmap->sys_ptr = xallocarray(pExaPixmap->sys_pitch,
|
||||
pPixmap->drawable.height);
|
||||
if (!pExaPixmap->sys_ptr)
|
||||
FatalError("EXA: malloc failed for size %d bytes\n",
|
||||
pExaPixmap->sys_pitch * pPixmap->drawable.height);
|
||||
}
|
||||
|
||||
if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
|
||||
pixmaps[0].as_dst = TRUE;
|
||||
pixmaps[0].as_src = FALSE;
|
||||
}
|
||||
else {
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
}
|
||||
pixmaps[0].pPix = pPixmap;
|
||||
pixmaps[0].pReg = pReg;
|
||||
|
||||
if (!pExaPixmap->pDamage &&
|
||||
(has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
|
||||
Bool as_dst = pixmaps[0].as_dst;
|
||||
|
||||
/* Set up damage tracking */
|
||||
pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
|
||||
DamageReportNonEmpty, TRUE,
|
||||
pPixmap->drawable.pScreen,
|
||||
pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
|
||||
/* This ensures that pending damage reflects the current
|
||||
* operation. This is used by exa to optimize migration.
|
||||
*/
|
||||
DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
|
||||
}
|
||||
|
||||
if (has_gpu_copy) {
|
||||
exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
|
||||
pPixmap->drawable.height);
|
||||
|
||||
/* We don't know which region of the destination will be damaged,
|
||||
* have to assume all of it
|
||||
*/
|
||||
if (as_dst) {
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
pixmaps[0].pReg = NULL;
|
||||
}
|
||||
exaCopyDirtyToSys(pixmaps);
|
||||
}
|
||||
|
||||
if (as_dst)
|
||||
exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
|
||||
pPixmap->drawable.height);
|
||||
}
|
||||
else if (has_gpu_copy)
|
||||
exaCopyDirtyToSys(pixmaps);
|
||||
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
}
|
||||
}
|
||||
328
exa/exa_mixed.c
328
exa/exa_mixed.c
|
|
@ -1,328 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
/* This file holds the driver allocated pixmaps + better initial placement code.
|
||||
*/
|
||||
|
||||
static inline void *
|
||||
ExaGetPixmapAddress(PixmapPtr p)
|
||||
{
|
||||
ExaPixmapPriv(p);
|
||||
|
||||
return pExaPixmap->sys_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*/
|
||||
PixmapPtr
|
||||
exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint)
|
||||
{
|
||||
PixmapPtr pPixmap;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
int bpp;
|
||||
size_t paddedWidth;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (w > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
|
||||
if (!pPixmap)
|
||||
return NULL;
|
||||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
|
||||
if (paddedWidth / 4 > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
/* We will allocate the system pixmap later if needed. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
pExaPixmap->sys_pitch = paddedWidth;
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
|
||||
|
||||
/* A scratch pixmap will become a driver pixmap right away. */
|
||||
if (!w || !h) {
|
||||
exaCreateDriverPixmap_mixed(pPixmap);
|
||||
pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
}
|
||||
else {
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
|
||||
if (w == 1 && h == 1) {
|
||||
pExaPixmap->sys_ptr = malloc(paddedWidth);
|
||||
|
||||
/* Set up damage tracking */
|
||||
pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
|
||||
DamageReportNonEmpty, TRUE,
|
||||
pPixmap->drawable.pScreen,
|
||||
pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
|
||||
/* This ensures that pending damage reflects the current
|
||||
* operation. This is used by exa to optimize migration.
|
||||
*/
|
||||
DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* During a fallback we must prepare access. */
|
||||
if (pExaScr->fallback_counter)
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
return pPixmap;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
|
||||
int bitsPerPixel, int devKind, void *pPixData)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
ExaScreenPrivPtr pExaScr;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
Bool ret, has_gpu_copy;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
pScreen = pPixmap->drawable.pScreen;
|
||||
pExaScr = ExaGetScreenPriv(pScreen);
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
if (pPixData) {
|
||||
if (pExaPixmap->driverPriv) {
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
}
|
||||
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
}
|
||||
|
||||
has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
|
||||
if (width <= 0)
|
||||
width = pPixmap->drawable.width;
|
||||
|
||||
if (height <= 0)
|
||||
height = pPixmap->drawable.height;
|
||||
|
||||
if (bitsPerPixel <= 0) {
|
||||
if (depth <= 0)
|
||||
bitsPerPixel = pPixmap->drawable.bitsPerPixel;
|
||||
else
|
||||
bitsPerPixel = BitsPerPixel(depth);
|
||||
}
|
||||
|
||||
if (depth <= 0)
|
||||
depth = pPixmap->drawable.depth;
|
||||
|
||||
if (width != pPixmap->drawable.width ||
|
||||
height != pPixmap->drawable.height ||
|
||||
depth != pPixmap->drawable.depth ||
|
||||
bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
|
||||
if (pExaPixmap->driverPriv) {
|
||||
if (devKind > 0)
|
||||
pExaPixmap->fb_pitch = devKind;
|
||||
else
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
RegionEmpty(&pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
/* Need to re-create system copy if there's also a GPU copy */
|
||||
if (has_gpu_copy) {
|
||||
if (pExaPixmap->sys_ptr) {
|
||||
free(pExaPixmap->sys_ptr);
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
RegionEmpty(&pExaPixmap->validSys);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap == pPixmap)
|
||||
pExaScr->deferred_mixed_pixmap = NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_gpu_copy) {
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
}
|
||||
else {
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
}
|
||||
|
||||
/* Only pass driver pixmaps to the driver. */
|
||||
if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
|
||||
ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind,
|
||||
pPixData);
|
||||
if (ret == TRUE)
|
||||
goto out;
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind, pPixData);
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
|
||||
out:
|
||||
if (has_gpu_copy) {
|
||||
pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->fb_pitch = pPixmap->devKind;
|
||||
}
|
||||
else {
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
}
|
||||
/* Always NULL this, we don't want lingering pointers. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
if (pPixmap->refcnt == 1) {
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaDestroyPixmap(pPixmap);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap == pPixmap)
|
||||
pExaScr->deferred_mixed_pixmap = NULL;
|
||||
|
||||
if (pExaPixmap->driverPriv)
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
if (pExaPixmap->pDamage) {
|
||||
free(pExaPixmap->sys_ptr);
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
ret = pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
void *saved_ptr;
|
||||
Bool ret;
|
||||
|
||||
if (!pExaPixmap->driverPriv)
|
||||
return FALSE;
|
||||
|
||||
saved_ptr = pPixmap->devPrivate.ptr;
|
||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
||||
ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
|
||||
pPixmap->devPrivate.ptr = saved_ptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret = FALSE;
|
||||
|
||||
exaMoveInPixmap(pPixmap);
|
||||
/* get the driver to give us a handle */
|
||||
if (pExaScr->info->SharePixmapBacking)
|
||||
ret = pExaScr->info->SharePixmapBacking(pPixmap, secondary, handle_p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret = FALSE;
|
||||
|
||||
if (pExaScr->info->SetSharedPixmapBacking)
|
||||
ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle);
|
||||
|
||||
if (ret == TRUE)
|
||||
exaMoveInPixmap(pPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,677 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2003 Anders Carlsson
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Anders Carlsson not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Anders Carlsson makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This allocator allocates blocks of memory by maintaining a list of areas.
|
||||
* When allocating, the contiguous block of areas with the minimum eviction
|
||||
* cost is found and evicted in order to make room for the new allocation.
|
||||
*/
|
||||
|
||||
#include "exa_priv.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
#define DBG_OFFSCREEN(a) ErrorF a
|
||||
#else
|
||||
#define DBG_OFFSCREEN(a)
|
||||
#endif
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
static void
|
||||
ExaOffscreenValidate(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *prev = 0, *area;
|
||||
|
||||
assert(pExaScr->info->offScreenAreas->base_offset ==
|
||||
pExaScr->info->offScreenBase);
|
||||
for (area = pExaScr->info->offScreenAreas; area; area = area->next) {
|
||||
assert(area->offset >= area->base_offset);
|
||||
assert(area->offset < (area->base_offset + area->size));
|
||||
if (prev)
|
||||
assert(prev->base_offset + prev->size == area->base_offset);
|
||||
prev = area;
|
||||
}
|
||||
assert(prev->base_offset + prev->size == pExaScr->info->memorySize);
|
||||
}
|
||||
#else
|
||||
#define ExaOffscreenValidate(s)
|
||||
#endif
|
||||
|
||||
static ExaOffscreenArea *
|
||||
ExaOffscreenKickOut(ScreenPtr pScreen, ExaOffscreenArea * area)
|
||||
{
|
||||
if (area->save)
|
||||
(*area->save) (pScreen, area);
|
||||
return exaOffscreenFree(pScreen, area);
|
||||
}
|
||||
|
||||
static void
|
||||
exaUpdateEvictionCost(ExaOffscreenArea * area, unsigned offScreenCounter)
|
||||
{
|
||||
unsigned age;
|
||||
|
||||
if (area->state == ExaOffscreenAvail)
|
||||
return;
|
||||
|
||||
age = offScreenCounter - area->last_use;
|
||||
|
||||
/* This is unlikely to happen, but could result in a division by zero... */
|
||||
if (age > (UINT_MAX / 2)) {
|
||||
age = UINT_MAX / 2;
|
||||
area->last_use = offScreenCounter - age;
|
||||
}
|
||||
|
||||
area->eviction_cost = area->size / age;
|
||||
}
|
||||
|
||||
static ExaOffscreenArea *
|
||||
exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align)
|
||||
{
|
||||
ExaOffscreenArea *begin, *end, *best;
|
||||
unsigned cost, best_cost;
|
||||
int avail, real_size;
|
||||
|
||||
best_cost = UINT_MAX;
|
||||
begin = end = pExaScr->info->offScreenAreas;
|
||||
avail = 0;
|
||||
cost = 0;
|
||||
best = 0;
|
||||
|
||||
while (end != NULL) {
|
||||
restart:
|
||||
while (begin != NULL && begin->state == ExaOffscreenLocked)
|
||||
begin = end = begin->next;
|
||||
|
||||
if (begin == NULL)
|
||||
break;
|
||||
|
||||
/* adjust size needed to account for alignment loss for this area */
|
||||
real_size = size + (begin->base_offset + begin->size - size) % align;
|
||||
|
||||
while (avail < real_size && end != NULL) {
|
||||
if (end->state == ExaOffscreenLocked) {
|
||||
/* Can't more room here, restart after this locked area */
|
||||
avail = 0;
|
||||
cost = 0;
|
||||
begin = end;
|
||||
goto restart;
|
||||
}
|
||||
avail += end->size;
|
||||
exaUpdateEvictionCost(end, pExaScr->offScreenCounter);
|
||||
cost += end->eviction_cost;
|
||||
end = end->next;
|
||||
}
|
||||
|
||||
/* Check the cost, update best */
|
||||
if (avail >= real_size && cost < best_cost) {
|
||||
best = begin;
|
||||
best_cost = cost;
|
||||
}
|
||||
|
||||
avail -= begin->size;
|
||||
cost -= begin->eviction_cost;
|
||||
begin = begin->next;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaOffscreenAlloc allocates offscreen memory
|
||||
*
|
||||
* @param pScreen current screen
|
||||
* @param size size in bytes of the allocation
|
||||
* @param align byte alignment requirement for the offset of the allocated area
|
||||
* @param locked whether the allocated area is locked and can't be kicked out
|
||||
* @param save callback for when the area is evicted from memory
|
||||
* @param privdata private data for the save callback.
|
||||
*
|
||||
* Allocates offscreen memory from the device associated with pScreen. size
|
||||
* and align determine where and how large the allocated area is, and locked
|
||||
* will mark whether it should be held in card memory. privdata may be any
|
||||
* pointer for the save callback when the area is removed.
|
||||
*
|
||||
* Note that locked areas do get evicted on VT switch unless the driver
|
||||
* requested version 2.1 or newer behavior. In that case, the save callback is
|
||||
* still called.
|
||||
*/
|
||||
ExaOffscreenArea *
|
||||
exaOffscreenAlloc(ScreenPtr pScreen, int size, int align,
|
||||
Bool locked, ExaOffscreenSaveProc save, void *privData)
|
||||
{
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
int real_size = 0, largest_avail = 0;
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
static int number = 0;
|
||||
|
||||
ErrorF("================= ============ allocating a new pixmap %d\n",
|
||||
++number);
|
||||
#endif
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
if (!align)
|
||||
align = 1;
|
||||
|
||||
if (!size) {
|
||||
DBG_OFFSCREEN(("Alloc 0x%x -> EMPTY\n", size));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* throw out requests that cannot fit */
|
||||
if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase)) {
|
||||
DBG_OFFSCREEN(("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size,
|
||||
pExaScr->info->memorySize -
|
||||
pExaScr->info->offScreenBase));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Try to find a free space that'll fit. */
|
||||
for (area = pExaScr->info->offScreenAreas; area; area = area->next) {
|
||||
/* skip allocated areas */
|
||||
if (area->state != ExaOffscreenAvail)
|
||||
continue;
|
||||
|
||||
/* adjust size to match alignment requirement */
|
||||
real_size = size + (area->base_offset + area->size - size) % align;
|
||||
|
||||
/* does it fit? */
|
||||
if (real_size <= area->size)
|
||||
break;
|
||||
|
||||
if (area->size > largest_avail)
|
||||
largest_avail = area->size;
|
||||
}
|
||||
|
||||
if (!area) {
|
||||
area = exaFindAreaToEvict(pExaScr, size, align);
|
||||
|
||||
if (!area) {
|
||||
DBG_OFFSCREEN(("Alloc 0x%x -> NOSPACE\n", size));
|
||||
/* Could not allocate memory */
|
||||
ExaOffscreenValidate(pScreen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* adjust size needed to account for alignment loss for this area */
|
||||
real_size = size + (area->base_offset + area->size - size) % align;
|
||||
|
||||
/*
|
||||
* Kick out first area if in use
|
||||
*/
|
||||
if (area->state != ExaOffscreenAvail)
|
||||
area = ExaOffscreenKickOut(pScreen, area);
|
||||
/*
|
||||
* Now get the system to merge the other needed areas together
|
||||
*/
|
||||
while (area->size < real_size) {
|
||||
assert(area->next);
|
||||
assert(area->next->state == ExaOffscreenRemovable);
|
||||
(void) ExaOffscreenKickOut(pScreen, area->next);
|
||||
}
|
||||
}
|
||||
|
||||
/* save extra space in new area */
|
||||
if (real_size < area->size) {
|
||||
ExaOffscreenArea *new_area = malloc(sizeof(ExaOffscreenArea));
|
||||
|
||||
if (!new_area)
|
||||
return NULL;
|
||||
new_area->base_offset = area->base_offset;
|
||||
|
||||
new_area->offset = new_area->base_offset;
|
||||
new_area->align = 0;
|
||||
new_area->size = area->size - real_size;
|
||||
new_area->state = ExaOffscreenAvail;
|
||||
new_area->save = NULL;
|
||||
new_area->last_use = 0;
|
||||
new_area->eviction_cost = 0;
|
||||
new_area->next = area;
|
||||
new_area->prev = area->prev;
|
||||
if (area->prev->next)
|
||||
area->prev->next = new_area;
|
||||
else
|
||||
pExaScr->info->offScreenAreas = new_area;
|
||||
area->prev = new_area;
|
||||
area->base_offset = new_area->base_offset + new_area->size;
|
||||
area->size = real_size;
|
||||
}
|
||||
else
|
||||
pExaScr->numOffscreenAvailable--;
|
||||
|
||||
/*
|
||||
* Mark this area as in use
|
||||
*/
|
||||
if (locked)
|
||||
area->state = ExaOffscreenLocked;
|
||||
else
|
||||
area->state = ExaOffscreenRemovable;
|
||||
area->privData = privData;
|
||||
area->save = save;
|
||||
area->last_use = pExaScr->offScreenCounter++;
|
||||
area->offset = (area->base_offset + align - 1);
|
||||
area->offset -= area->offset % align;
|
||||
area->align = align;
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
|
||||
DBG_OFFSCREEN(("Alloc 0x%x -> 0x%x (0x%x)\n", size,
|
||||
area->base_offset, area->offset));
|
||||
return area;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ejects all offscreen areas, and uninitializes the offscreen memory manager.
|
||||
*/
|
||||
void
|
||||
ExaOffscreenSwapOut(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
/* loop until a single free area spans the space */
|
||||
for (;;) {
|
||||
ExaOffscreenArea *area = pExaScr->info->offScreenAreas;
|
||||
|
||||
if (!area)
|
||||
break;
|
||||
if (area->state == ExaOffscreenAvail) {
|
||||
area = area->next;
|
||||
if (!area)
|
||||
break;
|
||||
}
|
||||
assert(area->state != ExaOffscreenAvail);
|
||||
(void) ExaOffscreenKickOut(pScreen, area);
|
||||
ExaOffscreenValidate(pScreen);
|
||||
}
|
||||
ExaOffscreenValidate(pScreen);
|
||||
ExaOffscreenFini(pScreen);
|
||||
}
|
||||
|
||||
/** Ejects all pixmaps managed by EXA. */
|
||||
static void
|
||||
ExaOffscreenEjectPixmaps(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
/* loop until a single free area spans the space */
|
||||
for (;;) {
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
for (area = pExaScr->info->offScreenAreas; area != NULL;
|
||||
area = area->next) {
|
||||
if (area->state == ExaOffscreenRemovable &&
|
||||
area->save == exaPixmapSave) {
|
||||
(void) ExaOffscreenKickOut(pScreen, area);
|
||||
ExaOffscreenValidate(pScreen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (area == NULL)
|
||||
break;
|
||||
}
|
||||
ExaOffscreenValidate(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaOffscreenSwapIn(ScreenPtr pScreen)
|
||||
{
|
||||
exaOffscreenInit(pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares EXA for disabling of FB access, or restoring it.
|
||||
*
|
||||
* In version 2.1, the disabling results in pixmaps being ejected, while other
|
||||
* allocations remain. With this plus the prevention of migration while
|
||||
* swappedOut is set, EXA by itself should not cause any access of the
|
||||
* framebuffer to occur while swapped out. Any remaining issues are the
|
||||
* responsibility of the driver.
|
||||
*
|
||||
* Prior to version 2.1, all allocations, including locked ones, are ejected
|
||||
* when access is disabled, and the allocator is torn down while swappedOut
|
||||
* is set. This is more drastic, and caused implementation difficulties for
|
||||
* many drivers that could otherwise handle the lack of FB access while
|
||||
* swapped out.
|
||||
*/
|
||||
void
|
||||
exaEnableDisableFBAccess(ScreenPtr pScreen, Bool enable)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
|
||||
return;
|
||||
|
||||
if (!enable && pExaScr->disableFbCount++ == 0) {
|
||||
if (pExaScr->info->exa_minor < 1)
|
||||
ExaOffscreenSwapOut(pScreen);
|
||||
else
|
||||
ExaOffscreenEjectPixmaps(pScreen);
|
||||
pExaScr->swappedOut = TRUE;
|
||||
}
|
||||
|
||||
if (enable && --pExaScr->disableFbCount == 0) {
|
||||
if (pExaScr->info->exa_minor < 1)
|
||||
ExaOffscreenSwapIn(pScreen);
|
||||
pExaScr->swappedOut = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* merge the next free area into this one */
|
||||
static void
|
||||
ExaOffscreenMerge(ExaScreenPrivPtr pExaScr, ExaOffscreenArea * area)
|
||||
{
|
||||
ExaOffscreenArea *next = area->next;
|
||||
|
||||
/* account for space */
|
||||
area->size += next->size;
|
||||
/* frob pointer */
|
||||
area->next = next->next;
|
||||
if (area->next)
|
||||
area->next->prev = area;
|
||||
else
|
||||
pExaScr->info->offScreenAreas->prev = area;
|
||||
free(next);
|
||||
|
||||
pExaScr->numOffscreenAvailable--;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaOffscreenFree frees an allocation.
|
||||
*
|
||||
* @param pScreen current screen
|
||||
* @param area offscreen area to free
|
||||
*
|
||||
* exaOffscreenFree frees an allocation created by exaOffscreenAlloc. Note that
|
||||
* the save callback of the area is not called, and it is up to the driver to
|
||||
* do any cleanup necessary as a result.
|
||||
*
|
||||
* @return pointer to the newly freed area. This behavior should not be relied
|
||||
* on.
|
||||
*/
|
||||
ExaOffscreenArea *
|
||||
exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea * area)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *next = area->next;
|
||||
ExaOffscreenArea *prev;
|
||||
|
||||
DBG_OFFSCREEN(("Free 0x%x -> 0x%x (0x%x)\n", area->size,
|
||||
area->base_offset, area->offset));
|
||||
ExaOffscreenValidate(pScreen);
|
||||
|
||||
area->state = ExaOffscreenAvail;
|
||||
area->save = NULL;
|
||||
area->last_use = 0;
|
||||
area->eviction_cost = 0;
|
||||
/*
|
||||
* Find previous area
|
||||
*/
|
||||
if (area == pExaScr->info->offScreenAreas)
|
||||
prev = NULL;
|
||||
else
|
||||
prev = area->prev;
|
||||
|
||||
pExaScr->numOffscreenAvailable++;
|
||||
|
||||
/* link with next area if free */
|
||||
if (next && next->state == ExaOffscreenAvail)
|
||||
ExaOffscreenMerge(pExaScr, area);
|
||||
|
||||
/* link with prev area if free */
|
||||
if (prev && prev->state == ExaOffscreenAvail) {
|
||||
area = prev;
|
||||
ExaOffscreenMerge(pExaScr, area);
|
||||
}
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
DBG_OFFSCREEN(("\tdone freeing\n"));
|
||||
return area;
|
||||
}
|
||||
|
||||
void
|
||||
ExaOffscreenMarkUsed(PixmapPtr pPixmap)
|
||||
{
|
||||
ExaPixmapPriv(pPixmap);
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
if (!pExaPixmap || !pExaPixmap->area)
|
||||
return;
|
||||
|
||||
pExaPixmap->area->last_use = pExaScr->offScreenCounter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defragment offscreen memory by compacting allocated areas at the end of it,
|
||||
* leaving the total amount of memory available as a single area at the
|
||||
* beginning (when there are no pinned allocations).
|
||||
*/
|
||||
_X_HIDDEN ExaOffscreenArea *
|
||||
ExaOffscreenDefragment(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *area, *largest_available = NULL;
|
||||
int largest_size = 0;
|
||||
PixmapPtr pDstPix;
|
||||
ExaPixmapPrivPtr pExaDstPix;
|
||||
|
||||
pDstPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, 0, 0);
|
||||
|
||||
if (!pDstPix)
|
||||
return NULL;
|
||||
|
||||
pExaDstPix = ExaGetPixmapPriv(pDstPix);
|
||||
pExaDstPix->use_gpu_copy = TRUE;
|
||||
|
||||
for (area = pExaScr->info->offScreenAreas->prev;
|
||||
area != pExaScr->info->offScreenAreas;) {
|
||||
ExaOffscreenArea *prev = area->prev;
|
||||
PixmapPtr pSrcPix;
|
||||
ExaPixmapPrivPtr pExaSrcPix;
|
||||
Bool save_use_gpu_copy;
|
||||
int save_pitch;
|
||||
|
||||
if (area->state != ExaOffscreenAvail ||
|
||||
prev->state == ExaOffscreenLocked ||
|
||||
(prev->state == ExaOffscreenRemovable &&
|
||||
prev->save != exaPixmapSave)) {
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev->state == ExaOffscreenAvail) {
|
||||
if (area == largest_available) {
|
||||
largest_available = prev;
|
||||
largest_size += prev->size;
|
||||
}
|
||||
area = prev;
|
||||
ExaOffscreenMerge(pExaScr, area);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (area->size > largest_size) {
|
||||
largest_available = area;
|
||||
largest_size = area->size;
|
||||
}
|
||||
|
||||
pSrcPix = prev->privData;
|
||||
pExaSrcPix = ExaGetPixmapPriv(pSrcPix);
|
||||
|
||||
pExaDstPix->fb_ptr = pExaScr->info->memoryBase +
|
||||
area->base_offset + area->size - prev->size + prev->base_offset -
|
||||
prev->offset;
|
||||
pExaDstPix->fb_ptr -= (unsigned long) pExaDstPix->fb_ptr % prev->align;
|
||||
|
||||
if (pExaDstPix->fb_ptr <= pExaSrcPix->fb_ptr) {
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(pExaScr->info->flags & EXA_SUPPORTS_OFFSCREEN_OVERLAPS) &&
|
||||
(pExaSrcPix->fb_ptr + prev->size) > pExaDstPix->fb_ptr) {
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
save_use_gpu_copy = pExaSrcPix->use_gpu_copy;
|
||||
save_pitch = pSrcPix->devKind;
|
||||
|
||||
pExaSrcPix->use_gpu_copy = TRUE;
|
||||
pSrcPix->devKind = pExaSrcPix->fb_pitch;
|
||||
|
||||
pDstPix->drawable.width = pSrcPix->drawable.width;
|
||||
pDstPix->devKind = pSrcPix->devKind;
|
||||
pDstPix->drawable.height = pSrcPix->drawable.height;
|
||||
pDstPix->drawable.depth = pSrcPix->drawable.depth;
|
||||
pDstPix->drawable.bitsPerPixel = pSrcPix->drawable.bitsPerPixel;
|
||||
|
||||
if (!pExaScr->info->PrepareCopy(pSrcPix, pDstPix, -1, -1, GXcopy, ~0)) {
|
||||
pExaSrcPix->use_gpu_copy = save_use_gpu_copy;
|
||||
pSrcPix->devKind = save_pitch;
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
pExaScr->info->Copy(pDstPix, 0, 0, 0, 0, pDstPix->drawable.width,
|
||||
pDstPix->drawable.height);
|
||||
pExaScr->info->DoneCopy(pDstPix);
|
||||
exaMarkSync(pScreen);
|
||||
|
||||
DBG_OFFSCREEN(("Before swap: prev=0x%08x-0x%08x-0x%08x area=0x%08x-0x%08x-0x%08x\n", prev->base_offset, prev->offset, prev->base_offset + prev->size, area->base_offset, area->offset, area->base_offset + area->size));
|
||||
|
||||
/* Calculate swapped area offsets and sizes */
|
||||
area->base_offset = prev->base_offset;
|
||||
area->offset = area->base_offset;
|
||||
prev->offset += pExaDstPix->fb_ptr - pExaSrcPix->fb_ptr;
|
||||
assert(prev->offset >= pExaScr->info->offScreenBase);
|
||||
assert(prev->offset < pExaScr->info->memorySize);
|
||||
prev->base_offset = prev->offset;
|
||||
if (area->next)
|
||||
prev->size = area->next->base_offset - prev->base_offset;
|
||||
else
|
||||
prev->size = pExaScr->info->memorySize - prev->base_offset;
|
||||
area->size = prev->base_offset - area->base_offset;
|
||||
|
||||
DBG_OFFSCREEN(("After swap: area=0x%08x-0x%08x-0x%08x prev=0x%08x-0x%08x-0x%08x\n", area->base_offset, area->offset, area->base_offset + area->size, prev->base_offset, prev->offset, prev->base_offset + prev->size));
|
||||
|
||||
/* Swap areas in list */
|
||||
if (area->next)
|
||||
area->next->prev = prev;
|
||||
else
|
||||
pExaScr->info->offScreenAreas->prev = prev;
|
||||
if (prev->prev->next)
|
||||
prev->prev->next = area;
|
||||
else
|
||||
pExaScr->info->offScreenAreas = area;
|
||||
prev->next = area->next;
|
||||
area->next = prev;
|
||||
area->prev = prev->prev;
|
||||
prev->prev = area;
|
||||
if (!area->prev->next)
|
||||
pExaScr->info->offScreenAreas = area;
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
if (prev->prev == prev || prev->next == prev)
|
||||
ErrorF("Whoops, prev points to itself!\n");
|
||||
|
||||
if (area->prev == area || area->next == area)
|
||||
ErrorF("Whoops, area points to itself!\n");
|
||||
#endif
|
||||
|
||||
pExaSrcPix->fb_ptr = pExaDstPix->fb_ptr;
|
||||
pExaSrcPix->use_gpu_copy = save_use_gpu_copy;
|
||||
pSrcPix->devKind = save_pitch;
|
||||
}
|
||||
|
||||
pDstPix->drawable.width = 0;
|
||||
pDstPix->drawable.height = 0;
|
||||
pDstPix->drawable.depth = 0;
|
||||
pDstPix->drawable.bitsPerPixel = 0;
|
||||
|
||||
(*pScreen->DestroyPixmap) (pDstPix);
|
||||
|
||||
if (area->state == ExaOffscreenAvail && area->size > largest_size)
|
||||
return area;
|
||||
|
||||
return largest_available;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaOffscreenInit initializes the offscreen memory manager.
|
||||
*
|
||||
* @param pScreen current screen
|
||||
*
|
||||
* exaOffscreenInit is called by exaDriverInit to set up the memory manager for
|
||||
* the screen, if any offscreen memory is available.
|
||||
*/
|
||||
Bool
|
||||
exaOffscreenInit(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
/* Allocate a big free area */
|
||||
area = malloc(sizeof(ExaOffscreenArea));
|
||||
|
||||
if (!area)
|
||||
return FALSE;
|
||||
|
||||
area->state = ExaOffscreenAvail;
|
||||
area->base_offset = pExaScr->info->offScreenBase;
|
||||
area->offset = area->base_offset;
|
||||
area->align = 0;
|
||||
area->size = pExaScr->info->memorySize - area->base_offset;
|
||||
area->save = NULL;
|
||||
area->next = NULL;
|
||||
area->prev = area;
|
||||
area->last_use = 0;
|
||||
area->eviction_cost = 0;
|
||||
|
||||
/* Add it to the free areas */
|
||||
pExaScr->info->offScreenAreas = area;
|
||||
pExaScr->offScreenCounter = 1;
|
||||
pExaScr->numOffscreenAvailable = 1;
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ExaOffscreenFini(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
/* just free all of the area records */
|
||||
while ((area = pExaScr->info->offScreenAreas)) {
|
||||
pExaScr->info->offScreenAreas = area->next;
|
||||
free(area);
|
||||
}
|
||||
}
|
||||
735
exa/exa_priv.h
735
exa/exa_priv.h
|
|
@ -1,735 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Zack Rusin, Trolltech
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EXAPRIV_H
|
||||
#define EXAPRIV_H
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "exa.h"
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xproto.h>
|
||||
#ifdef MITSHM
|
||||
#include "shmint.h"
|
||||
#endif
|
||||
#include "scrnintstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "servermd.h"
|
||||
#include "colormapst.h"
|
||||
#include "gcstruct.h"
|
||||
#include "input.h"
|
||||
#include "mipointer.h"
|
||||
#include "mi.h"
|
||||
#include "dix.h"
|
||||
#include "fb.h"
|
||||
#include "fboverlay.h"
|
||||
#include "fbpict.h"
|
||||
#include "glyphstr.h"
|
||||
#include "damage.h"
|
||||
|
||||
#define DEBUG_TRACE_FALL 0
|
||||
#define DEBUG_MIGRATE 0
|
||||
#define DEBUG_PIXMAP 0
|
||||
#define DEBUG_OFFSCREEN 0
|
||||
#define DEBUG_GLYPH_CACHE 0
|
||||
|
||||
#if DEBUG_TRACE_FALL
|
||||
#define EXA_FALLBACK(x) \
|
||||
do { \
|
||||
ErrorF("EXA fallback at %s: ", __FUNCTION__); \
|
||||
ErrorF x; \
|
||||
} while (0)
|
||||
|
||||
char
|
||||
exaDrawableLocation(DrawablePtr pDrawable);
|
||||
#else
|
||||
#define EXA_FALLBACK(x)
|
||||
#endif
|
||||
|
||||
#if DEBUG_PIXMAP
|
||||
#define DBG_PIXMAP(a) ErrorF a
|
||||
#else
|
||||
#define DBG_PIXMAP(a)
|
||||
#endif
|
||||
|
||||
#ifndef EXA_MAX_FB
|
||||
#define EXA_MAX_FB FB_OVERLAY_MAX
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define EXA_FatalErrorDebug(x) FatalError x
|
||||
#define EXA_FatalErrorDebugWithRet(x, ret) FatalError x
|
||||
#else
|
||||
#define EXA_FatalErrorDebug(x) ErrorF x
|
||||
#define EXA_FatalErrorDebugWithRet(x, ret) \
|
||||
do { \
|
||||
ErrorF x; \
|
||||
return ret; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is the list of migration heuristics supported by EXA. See
|
||||
* exaDoMigration() for what their implementations do.
|
||||
*/
|
||||
enum ExaMigrationHeuristic {
|
||||
ExaMigrationGreedy,
|
||||
ExaMigrationAlways,
|
||||
ExaMigrationSmart
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned char sha1[20];
|
||||
} ExaCachedGlyphRec, *ExaCachedGlyphPtr;
|
||||
|
||||
typedef struct {
|
||||
/* The identity of the cache, statically configured at initialization */
|
||||
unsigned int format;
|
||||
int glyphWidth;
|
||||
int glyphHeight;
|
||||
|
||||
int size; /* Size of cache; eventually this should be dynamically determined */
|
||||
|
||||
/* Hash table mapping from glyph sha1 to position in the glyph; we use
|
||||
* open addressing with a hash table size determined based on size and large
|
||||
* enough so that we always have a good amount of free space, so we can
|
||||
* use linear probing. (Linear probing is preferable to double hashing
|
||||
* here because it allows us to easily remove entries.)
|
||||
*/
|
||||
int *hashEntries;
|
||||
int hashSize;
|
||||
|
||||
ExaCachedGlyphPtr glyphs;
|
||||
int glyphCount; /* Current number of glyphs */
|
||||
|
||||
PicturePtr picture; /* Where the glyphs of the cache are stored */
|
||||
int yOffset; /* y location within the picture where the cache starts */
|
||||
int columns; /* Number of columns the glyphs are laid out in */
|
||||
int evictionPosition; /* Next random position to evict a glyph */
|
||||
} ExaGlyphCacheRec, *ExaGlyphCachePtr;
|
||||
|
||||
#define EXA_NUM_GLYPH_CACHES 4
|
||||
|
||||
#define EXA_FALLBACK_COPYWINDOW (1 << 0)
|
||||
#define EXA_ACCEL_COPYWINDOW (1 << 1)
|
||||
|
||||
typedef struct _ExaMigrationRec {
|
||||
Bool as_dst;
|
||||
Bool as_src;
|
||||
PixmapPtr pPix;
|
||||
RegionPtr pReg;
|
||||
} ExaMigrationRec, *ExaMigrationPtr;
|
||||
|
||||
typedef void (*EnableDisableFBAccessProcPtr) (ScreenPtr, Bool);
|
||||
typedef struct {
|
||||
ExaDriverPtr info;
|
||||
ScreenBlockHandlerProcPtr SavedBlockHandler;
|
||||
ScreenWakeupHandlerProcPtr SavedWakeupHandler;
|
||||
CreateGCProcPtr SavedCreateGC;
|
||||
CloseScreenProcPtr SavedCloseScreen;
|
||||
GetImageProcPtr SavedGetImage;
|
||||
GetSpansProcPtr SavedGetSpans;
|
||||
CreatePixmapProcPtr SavedCreatePixmap;
|
||||
DestroyPixmapProcPtr SavedDestroyPixmap;
|
||||
CopyWindowProcPtr SavedCopyWindow;
|
||||
ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
|
||||
BitmapToRegionProcPtr SavedBitmapToRegion;
|
||||
CreateScreenResourcesProcPtr SavedCreateScreenResources;
|
||||
ModifyPixmapHeaderProcPtr SavedModifyPixmapHeader;
|
||||
SharePixmapBackingProcPtr SavedSharePixmapBacking;
|
||||
SetSharedPixmapBackingProcPtr SavedSetSharedPixmapBacking;
|
||||
SourceValidateProcPtr SavedSourceValidate;
|
||||
CompositeProcPtr SavedComposite;
|
||||
TrianglesProcPtr SavedTriangles;
|
||||
GlyphsProcPtr SavedGlyphs;
|
||||
TrapezoidsProcPtr SavedTrapezoids;
|
||||
AddTrapsProcPtr SavedAddTraps;
|
||||
void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps,
|
||||
Bool can_accel);
|
||||
Bool (*pixmap_has_gpu_copy) (PixmapPtr pPixmap);
|
||||
void (*do_move_in_pixmap) (PixmapPtr pPixmap);
|
||||
void (*do_move_out_pixmap) (PixmapPtr pPixmap);
|
||||
void (*prepare_access_reg) (PixmapPtr pPixmap, int index, RegionPtr pReg);
|
||||
|
||||
Bool swappedOut;
|
||||
enum ExaMigrationHeuristic migration;
|
||||
Bool checkDirtyCorrectness;
|
||||
unsigned disableFbCount;
|
||||
Bool optimize_migration;
|
||||
unsigned offScreenCounter;
|
||||
unsigned numOffscreenAvailable;
|
||||
CARD32 lastDefragment;
|
||||
CARD32 nextDefragment;
|
||||
PixmapPtr deferred_mixed_pixmap;
|
||||
|
||||
/* Reference counting for accessed pixmaps */
|
||||
struct {
|
||||
PixmapPtr pixmap;
|
||||
int count;
|
||||
Bool retval;
|
||||
} access[EXA_NUM_PREPARE_INDICES];
|
||||
|
||||
/* Holds information on fallbacks that cannot be relayed otherwise. */
|
||||
unsigned int fallback_flags;
|
||||
unsigned int fallback_counter;
|
||||
|
||||
ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
|
||||
|
||||
/**
|
||||
* Regions affected by fallback composite source / mask operations.
|
||||
*/
|
||||
|
||||
RegionRec srcReg;
|
||||
RegionRec maskReg;
|
||||
PixmapPtr srcPix;
|
||||
PixmapPtr maskPix;
|
||||
|
||||
DevPrivateKeyRec pixmapPrivateKeyRec;
|
||||
DevPrivateKeyRec gcPrivateKeyRec;
|
||||
} ExaScreenPrivRec, *ExaScreenPrivPtr;
|
||||
|
||||
extern DevPrivateKeyRec exaScreenPrivateKeyRec;
|
||||
|
||||
#define exaScreenPrivateKey (&exaScreenPrivateKeyRec)
|
||||
|
||||
#define ExaGetScreenPriv(s) ((ExaScreenPrivPtr)dixGetPrivate(&(s)->devPrivates, exaScreenPrivateKey))
|
||||
#define ExaScreenPriv(s) ExaScreenPrivPtr pExaScr = ExaGetScreenPriv(s)
|
||||
|
||||
#define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixGetPrivateAddr(&(gc)->devPrivates, &ExaGetScreenPriv(gc->pScreen)->gcPrivateKeyRec))
|
||||
#define ExaGCPriv(gc) ExaGCPrivPtr pExaGC = ExaGetGCPriv(gc)
|
||||
|
||||
/*
|
||||
* Some macros to deal with function wrapping.
|
||||
*/
|
||||
#define wrap(priv, real, mem, func) {\
|
||||
priv->Saved##mem = real->mem; \
|
||||
real->mem = func; \
|
||||
}
|
||||
|
||||
#define unwrap(priv, real, mem) {\
|
||||
real->mem = priv->Saved##mem; \
|
||||
}
|
||||
|
||||
#ifdef HAVE_TYPEOF
|
||||
#define swap(priv, real, mem) {\
|
||||
typeof(real->mem) tmp = priv->Saved##mem; \
|
||||
priv->Saved##mem = real->mem; \
|
||||
real->mem = tmp; \
|
||||
}
|
||||
#else
|
||||
#define swap(priv, real, mem) {\
|
||||
const void *tmp = priv->Saved##mem; \
|
||||
priv->Saved##mem = real->mem; \
|
||||
real->mem = tmp; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define EXA_PRE_FALLBACK(_screen_) \
|
||||
ExaScreenPriv(_screen_); \
|
||||
pExaScr->fallback_counter++;
|
||||
|
||||
#define EXA_POST_FALLBACK(_screen_) \
|
||||
pExaScr->fallback_counter--;
|
||||
|
||||
#define EXA_PRE_FALLBACK_GC(_gc_) \
|
||||
ExaScreenPriv(_gc_->pScreen); \
|
||||
ExaGCPriv(_gc_); \
|
||||
pExaScr->fallback_counter++; \
|
||||
swap(pExaGC, _gc_, ops);
|
||||
|
||||
#define EXA_POST_FALLBACK_GC(_gc_) \
|
||||
pExaScr->fallback_counter--; \
|
||||
swap(pExaGC, _gc_, ops);
|
||||
|
||||
/** Align an offset to an arbitrary alignment */
|
||||
#define EXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
|
||||
(((offset) + (align) - 1) % (align)))
|
||||
/** Align an offset to a power-of-two alignment */
|
||||
#define EXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
#define EXA_PIXMAP_SCORE_MOVE_IN 10
|
||||
#define EXA_PIXMAP_SCORE_MAX 20
|
||||
#define EXA_PIXMAP_SCORE_MOVE_OUT -10
|
||||
#define EXA_PIXMAP_SCORE_MIN -20
|
||||
#define EXA_PIXMAP_SCORE_PINNED 1000
|
||||
#define EXA_PIXMAP_SCORE_INIT 1001
|
||||
|
||||
#define ExaGetPixmapPriv(p) ((ExaPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &ExaGetScreenPriv((p)->drawable.pScreen)->pixmapPrivateKeyRec))
|
||||
#define ExaPixmapPriv(p) ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv(p)
|
||||
|
||||
#define EXA_RANGE_PITCH (1 << 0)
|
||||
#define EXA_RANGE_WIDTH (1 << 1)
|
||||
#define EXA_RANGE_HEIGHT (1 << 2)
|
||||
|
||||
typedef struct {
|
||||
ExaOffscreenArea *area;
|
||||
int score; /**< score for the move-in vs move-out heuristic */
|
||||
Bool use_gpu_copy;
|
||||
|
||||
CARD8 *sys_ptr; /**< pointer to pixmap data in system memory */
|
||||
int sys_pitch; /**< pitch of pixmap in system memory */
|
||||
|
||||
CARD8 *fb_ptr; /**< pointer to pixmap data in framebuffer memory */
|
||||
int fb_pitch; /**< pitch of pixmap in framebuffer memory */
|
||||
unsigned int fb_size; /**< size of pixmap in framebuffer memory */
|
||||
|
||||
/**
|
||||
* Holds information about whether this pixmap can be used for
|
||||
* acceleration (== 0) or not (> 0).
|
||||
*
|
||||
* Contains a OR'ed combination of the following values:
|
||||
* EXA_RANGE_PITCH - set if the pixmap's pitch is out of range
|
||||
* EXA_RANGE_WIDTH - set if the pixmap's width is out of range
|
||||
* EXA_RANGE_HEIGHT - set if the pixmap's height is out of range
|
||||
*/
|
||||
unsigned int accel_blocked;
|
||||
|
||||
/**
|
||||
* The damage record contains the areas of the pixmap's current location
|
||||
* (framebuffer or system) that have been damaged compared to the other
|
||||
* location.
|
||||
*/
|
||||
DamagePtr pDamage;
|
||||
/**
|
||||
* The valid regions mark the valid bits (at least, as they're derived from
|
||||
* damage, which may be overreported) of a pixmap's system and FB copies.
|
||||
*/
|
||||
RegionRec validSys, validFB;
|
||||
/**
|
||||
* Driver private storage per EXA pixmap
|
||||
*/
|
||||
void *driverPriv;
|
||||
} ExaPixmapPrivRec, *ExaPixmapPrivPtr;
|
||||
|
||||
typedef struct {
|
||||
/* GC values from the layer below. */
|
||||
const GCOps *Savedops;
|
||||
const GCFuncs *Savedfuncs;
|
||||
} ExaGCPrivRec, *ExaGCPrivPtr;
|
||||
|
||||
typedef struct {
|
||||
PicturePtr pDst;
|
||||
INT16 xSrc;
|
||||
INT16 ySrc;
|
||||
INT16 xMask;
|
||||
INT16 yMask;
|
||||
INT16 xDst;
|
||||
INT16 yDst;
|
||||
INT16 width;
|
||||
INT16 height;
|
||||
} ExaCompositeRectRec, *ExaCompositeRectPtr;
|
||||
|
||||
/**
|
||||
* exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
|
||||
* to set EXA options or hook in screen functions to handle using EXA as the AA.
|
||||
*/
|
||||
void exaDDXDriverInit(ScreenPtr pScreen);
|
||||
|
||||
/* exa_unaccel.c */
|
||||
void
|
||||
exaPrepareAccessGC(GCPtr pGC);
|
||||
|
||||
void
|
||||
exaFinishAccessGC(GCPtr pGC);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
|
||||
DDXPointPtr ppt, int *pwidth, int fSorted);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
|
||||
int x, int y, int w, int h, int leftPad, int format,
|
||||
char *bits);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
|
||||
Bool upsidedown, Pixel bitplane, void *closure);
|
||||
|
||||
RegionPtr
|
||||
|
||||
ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty);
|
||||
|
||||
RegionPtr
|
||||
|
||||
ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty,
|
||||
unsigned long bitPlane);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
|
||||
DDXPointPtr pptInit);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int mode, int npt, DDXPointPtr ppt);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nsegInit, xSegment * pSegInit);
|
||||
|
||||
void
|
||||
ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nrect, xRectangle *prect);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPushPixels(GCPtr pGC, PixmapPtr pBitmap,
|
||||
DrawablePtr pDrawable, int w, int h, int x, int y);
|
||||
|
||||
void
|
||||
ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
||||
unsigned int format, unsigned long planeMask, char *d);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckGetSpans(DrawablePtr pDrawable,
|
||||
int wMax,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckAddTraps(PicturePtr pPicture,
|
||||
INT16 x_off, INT16 y_off, int ntrap, xTrap * traps);
|
||||
|
||||
/* exa_accel.c */
|
||||
|
||||
static inline Bool
|
||||
exaGCReadsDestination(DrawablePtr pDrawable, unsigned long planemask,
|
||||
unsigned int fillStyle, unsigned char alu,
|
||||
Bool clientClip)
|
||||
{
|
||||
return ((alu != GXcopy && alu != GXclear && alu != GXset &&
|
||||
alu != GXcopyInverted) || fillStyle == FillStippled ||
|
||||
clientClip != FALSE || !EXA_PM_IS_SOLID(pDrawable, planemask));
|
||||
}
|
||||
|
||||
void
|
||||
exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
|
||||
|
||||
Bool
|
||||
|
||||
exaFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
|
||||
DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu,
|
||||
Bool clientClip);
|
||||
|
||||
void
|
||||
|
||||
exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
||||
unsigned int format, unsigned long planeMask, char *d);
|
||||
|
||||
RegionPtr
|
||||
|
||||
exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
|
||||
int srcx, int srcy, int width, int height, int dstx, int dsty);
|
||||
|
||||
Bool
|
||||
|
||||
exaHWCopyNtoN(DrawablePtr pSrcDrawable,
|
||||
DrawablePtr pDstDrawable,
|
||||
GCPtr pGC,
|
||||
BoxPtr pbox,
|
||||
int nbox, int dx, int dy, Bool reverse, Bool upsidedown);
|
||||
|
||||
void
|
||||
|
||||
exaCopyNtoN(DrawablePtr pSrcDrawable,
|
||||
DrawablePtr pDstDrawable,
|
||||
GCPtr pGC,
|
||||
BoxPtr pbox,
|
||||
int nbox,
|
||||
int dx,
|
||||
int dy,
|
||||
Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
|
||||
|
||||
extern const GCOps exaOps;
|
||||
|
||||
void
|
||||
|
||||
ExaCheckComposite(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs);
|
||||
|
||||
/* exa_offscreen.c */
|
||||
void
|
||||
ExaOffscreenSwapOut(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ExaOffscreenSwapIn(ScreenPtr pScreen);
|
||||
|
||||
ExaOffscreenArea *ExaOffscreenDefragment(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
exaOffscreenInit(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ExaOffscreenFini(ScreenPtr pScreen);
|
||||
|
||||
/* exa.c */
|
||||
Bool
|
||||
ExaDoPrepareAccess(PixmapPtr pPixmap, int index);
|
||||
|
||||
void
|
||||
exaPrepareAccess(DrawablePtr pDrawable, int index);
|
||||
|
||||
void
|
||||
exaFinishAccess(DrawablePtr pDrawable, int index);
|
||||
|
||||
void
|
||||
exaDestroyPixmap(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2);
|
||||
|
||||
void
|
||||
|
||||
exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
|
||||
int *xp, int *yp);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy(PixmapPtr p);
|
||||
|
||||
PixmapPtr
|
||||
exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp);
|
||||
|
||||
PixmapPtr
|
||||
exaGetDrawablePixmap(DrawablePtr pDrawable);
|
||||
|
||||
void
|
||||
|
||||
exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
|
||||
int w, int h, int bpp);
|
||||
|
||||
void
|
||||
|
||||
exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
|
||||
int w, int h, int bpp);
|
||||
|
||||
void
|
||||
exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
Bool
|
||||
exaPixmapIsPinned(PixmapPtr pPix);
|
||||
|
||||
extern const GCFuncs exaGCFuncs;
|
||||
|
||||
/* exa_classic.c */
|
||||
PixmapPtr
|
||||
|
||||
exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint);
|
||||
|
||||
Bool
|
||||
|
||||
exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData);
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_classic(PixmapPtr pPixmap);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap);
|
||||
|
||||
/* exa_driver.c */
|
||||
PixmapPtr
|
||||
|
||||
exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint);
|
||||
|
||||
Bool
|
||||
|
||||
exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData);
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_driver(PixmapPtr pPixmap);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap);
|
||||
|
||||
/* exa_mixed.c */
|
||||
PixmapPtr
|
||||
|
||||
exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint);
|
||||
|
||||
Bool
|
||||
|
||||
exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
|
||||
int bitsPerPixel, int devKind, void *pPixData);
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_mixed(PixmapPtr pPixmap);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap);
|
||||
|
||||
/* exa_migration_mixed.c */
|
||||
void
|
||||
exaCreateDriverPixmap_mixed(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
void
|
||||
exaMoveInPixmap_mixed(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure);
|
||||
|
||||
void
|
||||
exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg);
|
||||
|
||||
Bool
|
||||
exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle);
|
||||
Bool
|
||||
exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p);
|
||||
|
||||
/* exa_render.c */
|
||||
Bool
|
||||
exaOpReadsDestination(CARD8 op);
|
||||
|
||||
void
|
||||
|
||||
exaComposite(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
|
||||
|
||||
void
|
||||
|
||||
exaCompositeRects(CARD8 op,
|
||||
PicturePtr Src,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst, int nrect, ExaCompositeRectPtr rects);
|
||||
|
||||
void
|
||||
|
||||
exaTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
|
||||
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
|
||||
int ntrap, xTrapezoid * traps);
|
||||
|
||||
void
|
||||
|
||||
exaTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
|
||||
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
|
||||
int ntri, xTriangle * tris);
|
||||
|
||||
/* exa_glyph.c */
|
||||
void
|
||||
exaGlyphsInit(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
exaGlyphsFini(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
|
||||
exaGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs);
|
||||
|
||||
/* exa_migration_classic.c */
|
||||
void
|
||||
exaCopyDirtyToSys(ExaMigrationPtr migrate);
|
||||
|
||||
void
|
||||
exaCopyDirtyToFb(ExaMigrationPtr migrate);
|
||||
|
||||
void
|
||||
exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
void
|
||||
exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area);
|
||||
|
||||
void
|
||||
exaMoveOutPixmap_classic(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaMoveInPixmap_classic(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg);
|
||||
|
||||
#endif /* EXAPRIV_H */
|
||||
1229
exa/exa_render.c
1229
exa/exa_render.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,733 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "exa_priv.h"
|
||||
|
||||
#include "mipict.h"
|
||||
|
||||
/*
|
||||
* These functions wrap the low-level fb rendering functions and
|
||||
* synchronize framebuffer/accelerated drawing by stalling until
|
||||
* the accelerator is idle
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calls exaPrepareAccess with EXA_PREPARE_SRC for the tile, if that is the
|
||||
* current fill style.
|
||||
*
|
||||
* Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
|
||||
* 1bpp and never in fb, so we don't worry about them.
|
||||
* We should worry about them for completeness sake and going forward.
|
||||
*/
|
||||
void
|
||||
exaPrepareAccessGC(GCPtr pGC)
|
||||
{
|
||||
if (pGC->stipple)
|
||||
exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
|
||||
if (pGC->fillStyle == FillTiled)
|
||||
exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes access to the tile in the GC, if used.
|
||||
*/
|
||||
void
|
||||
exaFinishAccessGC(GCPtr pGC)
|
||||
{
|
||||
if (pGC->fillStyle == FillTiled)
|
||||
exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
|
||||
if (pGC->stipple)
|
||||
exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
|
||||
}
|
||||
|
||||
#if DEBUG_TRACE_FALL
|
||||
char
|
||||
exaDrawableLocation(DrawablePtr pDrawable)
|
||||
{
|
||||
return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm';
|
||||
}
|
||||
#endif /* DEBUG_TRACE_FALL */
|
||||
|
||||
void
|
||||
ExaCheckFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
|
||||
DDXPointPtr ppt, int *pwidth, int fSorted)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
|
||||
int x, int y, int w, int h, int leftPad, int format,
|
||||
char *bits)
|
||||
{
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
|
||||
exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
|
||||
pGC->alu, pGC->clientClip != NULL))
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
else
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
|
||||
DamagePendingRegion(pExaPixmap->pDamage));
|
||||
pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
|
||||
bits);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
|
||||
Bool upsidedown, Pixel bitplane, void *closure)
|
||||
{
|
||||
RegionRec reg;
|
||||
int xoff, yoff;
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
|
||||
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
|
||||
|
||||
if (pExaScr->prepare_access_reg && RegionInitBoxes(®, pbox, nbox)) {
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc);
|
||||
|
||||
exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
|
||||
RegionTranslate(®, xoff + dx, yoff + dy);
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, ®);
|
||||
RegionUninit(®);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pSrc, EXA_PREPARE_SRC);
|
||||
|
||||
if (pExaScr->prepare_access_reg &&
|
||||
!exaGCReadsDestination(pDst, pGC->planemask, pGC->fillStyle,
|
||||
pGC->alu, pGC->clientClip != NULL) &&
|
||||
RegionInitBoxes(®, pbox, nbox)) {
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pDst);
|
||||
|
||||
exaGetDrawableDeltas(pDst, pPixmap, &xoff, &yoff);
|
||||
RegionTranslate(®, xoff, yoff);
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, ®);
|
||||
RegionUninit(®);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pDst, EXA_PREPARE_DEST);
|
||||
|
||||
/* This will eventually call fbCopyNtoN, with some calculation overhead. */
|
||||
while (nbox--) {
|
||||
pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx,
|
||||
pbox->y1 - pSrc->y + dy, pbox->x2 - pbox->x1,
|
||||
pbox->y2 - pbox->y1, pbox->x1 - pDst->x,
|
||||
pbox->y1 - pDst->y);
|
||||
pbox++;
|
||||
}
|
||||
exaFinishAccess(pSrc, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
static void
|
||||
ExaFallbackPrepareReg(DrawablePtr pDrawable,
|
||||
GCPtr pGC,
|
||||
int x, int y, int width, int height,
|
||||
int index, Bool checkReads)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (pExaScr->prepare_access_reg &&
|
||||
!(checkReads && exaGCReadsDestination(pDrawable, pGC->planemask,
|
||||
pGC->fillStyle, pGC->alu,
|
||||
pGC->clientClip != NULL))) {
|
||||
BoxRec box;
|
||||
RegionRec reg;
|
||||
int xoff, yoff;
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
|
||||
|
||||
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
|
||||
box.x1 = pDrawable->x + x + xoff;
|
||||
box.y1 = pDrawable->y + y + yoff;
|
||||
box.x2 = box.x1 + width;
|
||||
box.y2 = box.y1 + height;
|
||||
|
||||
RegionInit(®, &box, 1);
|
||||
pExaScr->prepare_access_reg(pPixmap, index, ®);
|
||||
RegionUninit(®);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pDrawable, index);
|
||||
}
|
||||
|
||||
RegionPtr
|
||||
ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty)
|
||||
{
|
||||
RegionPtr ret;
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
|
||||
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
|
||||
ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE);
|
||||
ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE);
|
||||
ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
|
||||
exaFinishAccess(pSrc, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
RegionPtr
|
||||
ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty,
|
||||
unsigned long bitPlane)
|
||||
{
|
||||
RegionPtr ret;
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
|
||||
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
|
||||
ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE);
|
||||
ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE);
|
||||
ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
|
||||
bitPlane);
|
||||
exaFinishAccess(pSrc, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
|
||||
DDXPointPtr pptInit)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int mode, int npt, DDXPointPtr ppt)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
|
||||
pDrawable, exaDrawableLocation(pDrawable),
|
||||
pGC->lineWidth, mode, npt));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nsegInit, xSegment * pSegInit)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
|
||||
exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nrect, xRectangle *prect)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
|
||||
exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPushPixels(GCPtr pGC, PixmapPtr pBitmap,
|
||||
DrawablePtr pDrawable, int w, int h, int x, int y)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
|
||||
exaDrawableLocation(&pBitmap->drawable),
|
||||
exaDrawableLocation(pDrawable)));
|
||||
ExaFallbackPrepareReg(pDrawable, pGC, x, y, w, h, EXA_PREPARE_DEST, TRUE);
|
||||
ExaFallbackPrepareReg(&pBitmap->drawable, pGC, 0, 0, w, h,
|
||||
EXA_PREPARE_SRC, FALSE);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(&pBitmap->drawable, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
|
||||
{
|
||||
DrawablePtr pDrawable = &pWin->drawable;
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
EXA_FALLBACK(("from %p\n", pWin));
|
||||
|
||||
/* Only need the source bits, the destination region will be overwritten */
|
||||
if (pExaScr->prepare_access_reg) {
|
||||
PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin);
|
||||
int xoff, yoff;
|
||||
|
||||
exaGetDrawableDeltas(&pWin->drawable, pPixmap, &xoff, &yoff);
|
||||
RegionTranslate(prgnSrc, xoff, yoff);
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, prgnSrc);
|
||||
RegionTranslate(prgnSrc, -xoff, -yoff);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
|
||||
swap(pExaScr, pScreen, CopyWindow);
|
||||
pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
|
||||
swap(pExaScr, pScreen, CopyWindow);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
||||
unsigned int format, unsigned long planeMask, char *d)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
|
||||
ExaFallbackPrepareReg(pDrawable, NULL, x, y, w, h, EXA_PREPARE_SRC, FALSE);
|
||||
swap(pExaScr, pScreen, GetImage);
|
||||
pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d);
|
||||
swap(pExaScr, pScreen, GetImage);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckGetSpans(DrawablePtr pDrawable,
|
||||
int wMax,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
swap(pExaScr, pScreen, GetSpans);
|
||||
pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
|
||||
swap(pExaScr, pScreen, GetSpans);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
static void
|
||||
ExaSrcValidate(DrawablePtr pDrawable,
|
||||
int x, int y, int width, int height, unsigned int subWindowMode)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);
|
||||
BoxRec box;
|
||||
RegionRec reg;
|
||||
RegionPtr dst;
|
||||
int xoff, yoff;
|
||||
|
||||
if (pExaScr->srcPix == pPix)
|
||||
dst = &pExaScr->srcReg;
|
||||
else if (pExaScr->maskPix == pPix)
|
||||
dst = &pExaScr->maskReg;
|
||||
else
|
||||
return;
|
||||
|
||||
exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
|
||||
|
||||
box.x1 = x + xoff;
|
||||
box.y1 = y + yoff;
|
||||
box.x2 = box.x1 + width;
|
||||
box.y2 = box.y1 + height;
|
||||
|
||||
RegionInit(®, &box, 1);
|
||||
RegionUnion(dst, dst, ®);
|
||||
RegionUninit(®);
|
||||
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
}
|
||||
|
||||
static Bool
|
||||
ExaPrepareCompositeReg(ScreenPtr pScreen,
|
||||
CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
|
||||
{
|
||||
RegionRec region;
|
||||
RegionPtr dstReg = NULL;
|
||||
RegionPtr srcReg = NULL;
|
||||
RegionPtr maskReg = NULL;
|
||||
PixmapPtr pSrcPix = NULL;
|
||||
PixmapPtr pMaskPix = NULL;
|
||||
PixmapPtr pDstPix;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
RegionNull(®ion);
|
||||
|
||||
if (pSrc->pDrawable) {
|
||||
pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
|
||||
RegionNull(&pExaScr->srcReg);
|
||||
srcReg = &pExaScr->srcReg;
|
||||
pExaScr->srcPix = pSrcPix;
|
||||
if (pSrc != pDst)
|
||||
RegionTranslate(pSrc->pCompositeClip,
|
||||
-pSrc->pDrawable->x, -pSrc->pDrawable->y);
|
||||
} else
|
||||
pExaScr->srcPix = NULL;
|
||||
|
||||
if (pMask && pMask->pDrawable) {
|
||||
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
|
||||
RegionNull(&pExaScr->maskReg);
|
||||
maskReg = &pExaScr->maskReg;
|
||||
pExaScr->maskPix = pMaskPix;
|
||||
if (pMask != pDst && pMask != pSrc)
|
||||
RegionTranslate(pMask->pCompositeClip,
|
||||
-pMask->pDrawable->x, -pMask->pDrawable->y);
|
||||
} else
|
||||
pExaScr->maskPix = NULL;
|
||||
|
||||
RegionTranslate(pDst->pCompositeClip,
|
||||
-pDst->pDrawable->x, -pDst->pDrawable->y);
|
||||
|
||||
pExaScr->SavedSourceValidate = ExaSrcValidate;
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
ret = miComputeCompositeRegion(®ion, pSrc, pMask, pDst,
|
||||
xSrc, ySrc, xMask, yMask,
|
||||
xDst, yDst, width, height);
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
|
||||
RegionTranslate(pDst->pCompositeClip,
|
||||
pDst->pDrawable->x, pDst->pDrawable->y);
|
||||
if (pSrc->pDrawable && pSrc != pDst)
|
||||
RegionTranslate(pSrc->pCompositeClip,
|
||||
pSrc->pDrawable->x, pSrc->pDrawable->y);
|
||||
if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
|
||||
RegionTranslate(pMask->pCompositeClip,
|
||||
pMask->pDrawable->x, pMask->pDrawable->y);
|
||||
|
||||
if (!ret) {
|
||||
if (srcReg)
|
||||
RegionUninit(srcReg);
|
||||
if (maskReg)
|
||||
RegionUninit(maskReg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't limit alphamaps readbacks for now until we've figured out how that
|
||||
* should be done.
|
||||
*/
|
||||
|
||||
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
|
||||
pExaScr->
|
||||
prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable),
|
||||
EXA_PREPARE_AUX_SRC, NULL);
|
||||
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
|
||||
pExaScr->
|
||||
prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable),
|
||||
EXA_PREPARE_AUX_MASK, NULL);
|
||||
|
||||
if (pSrcPix)
|
||||
pExaScr->prepare_access_reg(pSrcPix, EXA_PREPARE_SRC, srcReg);
|
||||
|
||||
if (pMaskPix)
|
||||
pExaScr->prepare_access_reg(pMaskPix, EXA_PREPARE_MASK, maskReg);
|
||||
|
||||
if (srcReg)
|
||||
RegionUninit(srcReg);
|
||||
if (maskReg)
|
||||
RegionUninit(maskReg);
|
||||
|
||||
pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
|
||||
if (!exaOpReadsDestination(op)) {
|
||||
int xoff;
|
||||
int yoff;
|
||||
|
||||
exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &xoff, &yoff);
|
||||
RegionTranslate(®ion, pDst->pDrawable->x + xoff,
|
||||
pDst->pDrawable->y + yoff);
|
||||
dstReg = ®ion;
|
||||
}
|
||||
|
||||
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
|
||||
pExaScr->
|
||||
prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
|
||||
EXA_PREPARE_AUX_DEST, dstReg);
|
||||
pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg);
|
||||
|
||||
RegionUninit(®ion);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckComposite(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
||||
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
|
||||
if (pExaScr->prepare_access_reg) {
|
||||
if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc,
|
||||
ySrc, xMask, yMask, xDst, yDst, width,
|
||||
height))
|
||||
goto out_no_clip;
|
||||
}
|
||||
else {
|
||||
|
||||
/* We need to prepare access to any separate alpha maps first,
|
||||
* in case the driver doesn't support EXA_PREPARE_AUX*,
|
||||
* in which case EXA_PREPARE_SRC may be used for moving them out.
|
||||
*/
|
||||
|
||||
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
|
||||
exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
|
||||
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
|
||||
exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
|
||||
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
|
||||
exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
exaPrepareAccess(pDst->pDrawable, EXA_PREPARE_DEST);
|
||||
|
||||
EXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
|
||||
|
||||
if (pSrc->pDrawable != NULL)
|
||||
exaPrepareAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
|
||||
if (pMask && pMask->pDrawable != NULL)
|
||||
exaPrepareAccess(pMask->pDrawable, EXA_PREPARE_MASK);
|
||||
}
|
||||
|
||||
swap(pExaScr, ps, Composite);
|
||||
ps->Composite(op,
|
||||
pSrc,
|
||||
pMask,
|
||||
pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
|
||||
swap(pExaScr, ps, Composite);
|
||||
if (pMask && pMask->pDrawable != NULL)
|
||||
exaFinishAccess(pMask->pDrawable, EXA_PREPARE_MASK);
|
||||
if (pSrc->pDrawable != NULL)
|
||||
exaFinishAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst->pDrawable, EXA_PREPARE_DEST);
|
||||
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
|
||||
exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
|
||||
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
|
||||
exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
|
||||
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
|
||||
exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
|
||||
|
||||
out_no_clip:
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid migration ping-pong when using a mask.
|
||||
*/
|
||||
void
|
||||
ExaCheckGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
|
||||
miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
|
||||
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckAddTraps(PicturePtr pPicture,
|
||||
INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
|
||||
{
|
||||
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
|
||||
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
|
||||
EXA_FALLBACK(("to pict %p (%c)\n", pPicture,
|
||||
exaDrawableLocation(pPicture->pDrawable)));
|
||||
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||
swap(pExaScr, ps, AddTraps);
|
||||
ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
|
||||
swap(pExaScr, ps, AddTraps);
|
||||
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
|
||||
* that happen to be 1x1. Pixmap must be at least 8bpp.
|
||||
*/
|
||||
CARD32
|
||||
exaGetPixmapFirstPixel(PixmapPtr pPixmap)
|
||||
{
|
||||
switch (pPixmap->drawable.bitsPerPixel) {
|
||||
case 32:
|
||||
{
|
||||
CARD32 pixel;
|
||||
|
||||
pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
|
||||
ZPixmap, ~0, (char *) &pixel);
|
||||
return pixel;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
CARD16 pixel;
|
||||
|
||||
pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
|
||||
ZPixmap, ~0, (char *) &pixel);
|
||||
return pixel;
|
||||
}
|
||||
case 8:
|
||||
case 4:
|
||||
case 1:
|
||||
{
|
||||
CARD8 pixel;
|
||||
|
||||
pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
|
||||
ZPixmap, ~0, (char *) &pixel);
|
||||
return pixel;
|
||||
}
|
||||
default:
|
||||
FatalError("%s called for invalid bpp %d\n", __func__,
|
||||
pPixmap->drawable.bitsPerPixel);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
srcs_exa = [
|
||||
'exa.c',
|
||||
'exa_classic.c',
|
||||
'exa_migration_classic.c',
|
||||
'exa_driver.c',
|
||||
'exa_mixed.c',
|
||||
'exa_migration_mixed.c',
|
||||
'exa_accel.c',
|
||||
'exa_glyphs.c',
|
||||
'exa_offscreen.c',
|
||||
'exa_render.c',
|
||||
'exa_unaccel.c',
|
||||
]
|
||||
|
||||
libxserver_exa = static_library('libxserver_exa',
|
||||
srcs_exa,
|
||||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
c_args: '-DHAVE_XORG_CONFIG_H'
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data('exa.h', install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
@ -54,7 +54,3 @@ libxserver_wfb = static_library('libxserver_wfb',
|
|||
pic: true,
|
||||
build_by_default: false,
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data(hdrs_fb, install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -520,6 +520,31 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
|||
return fd;
|
||||
}
|
||||
|
||||
static bool
|
||||
gbm_format_for_depth(CARD8 depth, uint32_t *format)
|
||||
{
|
||||
switch (depth) {
|
||||
case 15:
|
||||
*format = GBM_FORMAT_ARGB1555;
|
||||
return true;
|
||||
case 16:
|
||||
*format = GBM_FORMAT_RGB565;
|
||||
return true;
|
||||
case 24:
|
||||
*format = GBM_FORMAT_XRGB8888;
|
||||
return true;
|
||||
case 30:
|
||||
*format = GBM_FORMAT_ARGB2101010;
|
||||
return true;
|
||||
case 32:
|
||||
*format = GBM_FORMAT_ARGB8888;
|
||||
return true;
|
||||
default:
|
||||
ErrorF("unexpected depth: %d\n", depth);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
glamor_back_pixmap_from_fd(PixmapPtr pixmap,
|
||||
int fd,
|
||||
|
|
@ -536,17 +561,14 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap,
|
|||
|
||||
glamor_egl = glamor_egl_get_screen_private(scrn);
|
||||
|
||||
if (bpp != 32 || !(depth == 24 || depth == 32 || depth == 30) || width == 0 || height == 0)
|
||||
if (!gbm_format_for_depth(depth, &import_data.format) ||
|
||||
width == 0 || height == 0)
|
||||
return FALSE;
|
||||
|
||||
import_data.fd = fd;
|
||||
import_data.width = width;
|
||||
import_data.height = height;
|
||||
import_data.stride = stride;
|
||||
if (depth == 30)
|
||||
import_data.format = GBM_FORMAT_ARGB2101010;
|
||||
else
|
||||
import_data.format = GBM_FORMAT_ARGB8888;
|
||||
bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD, &import_data, 0);
|
||||
if (!bo)
|
||||
return FALSE;
|
||||
|
|
@ -558,23 +580,6 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gbm_format_for_depth(CARD8 depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 16:
|
||||
return GBM_FORMAT_RGB565;
|
||||
case 24:
|
||||
return GBM_FORMAT_XRGB8888;
|
||||
case 30:
|
||||
return GBM_FORMAT_ARGB2101010;
|
||||
default:
|
||||
ErrorF("unexpected depth: %d\n", depth);
|
||||
case 32:
|
||||
return GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
}
|
||||
|
||||
PixmapPtr
|
||||
glamor_pixmap_from_fds(ScreenPtr screen,
|
||||
CARD8 num_fds, const int *fds,
|
||||
|
|
@ -597,6 +602,10 @@ glamor_pixmap_from_fds(ScreenPtr screen,
|
|||
struct gbm_import_fd_modifier_data import_data = { 0 };
|
||||
struct gbm_bo *bo;
|
||||
|
||||
if (!gbm_format_for_depth(depth, &import_data.format) ||
|
||||
width == 0 || height == 0)
|
||||
goto error;
|
||||
|
||||
import_data.width = width;
|
||||
import_data.height = height;
|
||||
import_data.num_fds = num_fds;
|
||||
|
|
@ -606,7 +615,6 @@ glamor_pixmap_from_fds(ScreenPtr screen,
|
|||
import_data.strides[i] = strides[i];
|
||||
import_data.offsets[i] = offsets[i];
|
||||
}
|
||||
import_data.format = gbm_format_for_depth(depth);
|
||||
bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0);
|
||||
if (bo) {
|
||||
screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL);
|
||||
|
|
@ -622,6 +630,7 @@ glamor_pixmap_from_fds(ScreenPtr screen,
|
|||
}
|
||||
}
|
||||
|
||||
error:
|
||||
if (ret == FALSE) {
|
||||
screen->DestroyPixmap(pixmap);
|
||||
return NULL;
|
||||
|
|
@ -1087,7 +1096,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
Bool force_es = FALSE;
|
||||
const char *glvnd_vendor = NULL;
|
||||
|
||||
glamor_egl = calloc(sizeof(*glamor_egl), 1);
|
||||
glamor_egl = calloc(1, sizeof(*glamor_egl));
|
||||
if (glamor_egl == NULL)
|
||||
return FALSE;
|
||||
if (xf86GlamorEGLPrivateIndex == -1)
|
||||
|
|
|
|||
|
|
@ -140,12 +140,14 @@ egl_create_glx_drawable(ClientPtr client, __GLXscreen *screen,
|
|||
* - drawable type masks is suspicious
|
||||
*/
|
||||
static struct egl_config *
|
||||
translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
|
||||
translate_eglconfig(ScreenPtr pScreen, struct egl_screen *screen, EGLConfig hc,
|
||||
struct egl_config *chain, Bool direct_color,
|
||||
Bool double_buffer, Bool duplicate_for_composite,
|
||||
Bool srgb_only)
|
||||
{
|
||||
EGLint value;
|
||||
bool valid_depth;
|
||||
int i;
|
||||
struct egl_config *c = calloc(1, sizeof *c);
|
||||
|
||||
if (!c)
|
||||
|
|
@ -218,6 +220,19 @@ translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
|
|||
}
|
||||
#undef GET
|
||||
|
||||
/* Only expose this config if rgbBits matches a supported
|
||||
* depth value.
|
||||
*/
|
||||
valid_depth = false;
|
||||
for (i = 0; i < pScreen->numDepths && !valid_depth; i++) {
|
||||
if (pScreen->allowedDepths[i].depth == c->base.rgbBits)
|
||||
valid_depth = true;
|
||||
}
|
||||
if (!valid_depth) {
|
||||
free(c);
|
||||
return chain;
|
||||
}
|
||||
|
||||
/* derived state: config caveats */
|
||||
eglGetConfigAttrib(screen->display, hc, EGL_CONFIG_CAVEAT, &value);
|
||||
if (value == EGL_NONE)
|
||||
|
|
@ -340,13 +355,13 @@ egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen)
|
|||
for (j = 0; j < 3; j++) /* direct_color */
|
||||
for (k = 0; k < 2; k++) /* double_buffer */ {
|
||||
if (can_srgb)
|
||||
c = translate_eglconfig(screen, host_configs[i], c,
|
||||
c = translate_eglconfig(pScreen, screen, host_configs[i], c,
|
||||
/* direct_color */ j == 1,
|
||||
/* double_buffer */ k > 0,
|
||||
/* duplicate_for_composite */ j == 0,
|
||||
/* srgb_only */ true);
|
||||
|
||||
c = translate_eglconfig(screen, host_configs[i], c,
|
||||
c = translate_eglconfig(pScreen, screen, host_configs[i], c,
|
||||
/* direct_color */ j == 1,
|
||||
/* double_buffer */ k > 0,
|
||||
/* duplicate_for_composite */ j == 0,
|
||||
|
|
|
|||
|
|
@ -359,8 +359,6 @@ glamor_build_program(ScreenPtr screen,
|
|||
|
||||
vs_prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_prog_string);
|
||||
fs_prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_prog_string);
|
||||
free(vs_prog_string);
|
||||
free(fs_prog_string);
|
||||
glAttachShader(prog->prog, vs_prog);
|
||||
glDeleteShader(vs_prog);
|
||||
glAttachShader(prog->prog, fs_prog);
|
||||
|
|
@ -394,6 +392,8 @@ glamor_build_program(ScreenPtr screen,
|
|||
prog->atlas_uniform = glamor_get_uniform(prog, glamor_program_location_atlas, "atlas");
|
||||
|
||||
free(version_string);
|
||||
free(vs_prog_string);
|
||||
free(fs_prog_string);
|
||||
free(fs_vars);
|
||||
free(vs_vars);
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -37,8 +37,8 @@ glamor_upload_boxes(DrawablePtr drawable, BoxPtr in_boxes, int in_nbox,
|
|||
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
|
||||
glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
|
||||
int box_index;
|
||||
int bytes_per_pixel = drawable->bitsPerPixel >> 3;
|
||||
const struct glamor_format *f = glamor_format_for_pixmap(pixmap);
|
||||
int bytes_per_pixel = PICT_FORMAT_BPP(f->render_format) >> 3;
|
||||
char *tmp_bits = NULL;
|
||||
|
||||
if (glamor_drawable_effective_depth(drawable) == 24 && pixmap->drawable.depth == 32)
|
||||
|
|
@ -145,8 +145,8 @@ glamor_download_boxes(DrawablePtr drawable, BoxPtr in_boxes, int in_nbox,
|
|||
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
|
||||
glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
|
||||
int box_index;
|
||||
int bytes_per_pixel = drawable->bitsPerPixel >> 3;
|
||||
const struct glamor_format *f = glamor_format_for_pixmap(pixmap);
|
||||
int bytes_per_pixel = PICT_FORMAT_BPP(f->render_format) >> 3;
|
||||
|
||||
glamor_make_current(glamor_priv);
|
||||
|
||||
|
|
|
|||
|
|
@ -141,24 +141,22 @@ static const glamor_facet glamor_facet_xv_uyvy = {
|
|||
"in vec2 tcs;\n"
|
||||
),
|
||||
.fs_exec = (
|
||||
" vec3 uyv;\n"
|
||||
" vec4 frameOut = texture2D(sampler, tcs.st);\n"
|
||||
"\n"
|
||||
" vec4 prevPixel = texture2D(sampler, vec2(tcs.s - texelSize.x, tcs.t));\n"
|
||||
" vec4 nextPixel = texture2D(sampler, vec2(tcs.s + texelSize.x, tcs.t));\n"
|
||||
"\n"
|
||||
" float delta = 0.50;\n"
|
||||
"\n"
|
||||
" int even = int(mod(tcs.x / texelSize.x, 2.0));\n"
|
||||
"\n"
|
||||
" uyv.rgb = float(even)*vec3(frameOut.rg, nextPixel.r) + (1.0-float(even))*vec3(prevPixel.r, frameOut.gr);\n"
|
||||
"\n"
|
||||
" frameOut.r = uyv.g + 1.403*(uyv.r - delta);\n"
|
||||
" frameOut.g = uyv.g - 0.714*(uyv.r - delta) - 0.344*(uyv.b - delta);\n"
|
||||
" frameOut.b = uyv.g + 1.773*(uyv.b - delta);\n"
|
||||
" frameOut.a = 1.0;\n"
|
||||
" frag_color = frameOut;\n"
|
||||
),
|
||||
" vec4 temp1;\n"
|
||||
" vec2 xy = texture(sampler, tcs.st).xy;\n"
|
||||
" vec2 prev_xy = texture(sampler, vec2(tcs.s - texelSize.x, tcs.t)).xy;\n"
|
||||
" vec2 next_xy = texture(sampler, vec2(tcs.s + texelSize.x, tcs.t)).xy;\n"
|
||||
"\n"
|
||||
" vec3 sample_yuv;\n"
|
||||
" int odd = int(mod(tcs.x / texelSize.x, 2.0));\n"
|
||||
" int even = 1 - odd;\n"
|
||||
" sample_yuv.yxz = float(even)*vec3(xy, next_xy.x) + float(odd)*vec3(prev_xy.x, xy.yx);\n"
|
||||
"\n"
|
||||
" temp1.xyz = offsetyco.www * vec3(sample_yuv.x) + offsetyco.xyz;\n"
|
||||
" temp1.xyz = ucogamma.xyz * vec3(sample_yuv.y) + temp1.xyz;\n"
|
||||
" temp1.xyz = clamp(vco.xyz * vec3(sample_yuv.z) + temp1.xyz, 0.0, 1.0);\n"
|
||||
" temp1.w = 1.0;\n"
|
||||
" frag_color = temp1;\n"
|
||||
),
|
||||
};
|
||||
|
||||
static const glamor_facet glamor_facet_xv_rgb_raw = {
|
||||
|
|
@ -379,9 +377,16 @@ glamor_xv_query_image_attributes(int id,
|
|||
offsets[0] = 0;
|
||||
size *= *h;
|
||||
break;
|
||||
case FOURCC_RGB565:
|
||||
case FOURCC_UYVY:
|
||||
/* UYVU is single-plane really, all tranformation is processed inside a shader */
|
||||
size = ALIGN(*w, 2) * 2;
|
||||
if (pitches)
|
||||
pitches[0] = size;
|
||||
if (offsets)
|
||||
offsets[0] = 0;
|
||||
size *= *h;
|
||||
break;
|
||||
case FOURCC_RGB565:
|
||||
size = *w * 2;
|
||||
if (pitches)
|
||||
pitches[0] = size;
|
||||
|
|
@ -787,6 +792,15 @@ glamor_xv_put_image(glamor_port_private *port_priv,
|
|||
buf + s2offset, srcPitch);
|
||||
break;
|
||||
case FOURCC_UYVY:
|
||||
srcPitch = ALIGN(width, 2) * 2;
|
||||
full_box.x1 = 0;
|
||||
full_box.y1 = 0;
|
||||
full_box.x2 = width;
|
||||
full_box.y2 = height;
|
||||
glamor_upload_boxes(&port_priv->src_pix[0]->drawable, &full_box, 1,
|
||||
0, 0, 0, 0,
|
||||
buf, srcPitch);
|
||||
break;
|
||||
case FOURCC_RGB565:
|
||||
srcPitch = width * 2;
|
||||
full_box.x1 = 0;
|
||||
|
|
|
|||
|
|
@ -50,7 +50,3 @@ glamor = static_library('glamor',
|
|||
epoxy_dep,
|
||||
],
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data('glamor.h', install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ if build_glx
|
|||
endif
|
||||
|
||||
srcs_glxdri2 = []
|
||||
if build_dri2 or build_dri3
|
||||
if build_dri3
|
||||
srcs_glxdri2 = files('glxdri2.c')
|
||||
endif
|
||||
|
||||
|
|
@ -78,8 +78,4 @@ if build_glx
|
|||
dependency('gl', version: '>= 1.2'),
|
||||
],
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data(hdrs_vnd, install_dir : xorgsdkdir)
|
||||
endif
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,50 +0,0 @@
|
|||
.\" $RCSId: xc/programs/Xserver/hw/kdrive/Xkdrive.man,v 1.3 2001/01/24 00:06:10 dawes Exp $
|
||||
.\"
|
||||
.TH Xkdrive 1 @vendorversion@
|
||||
.SH NAME
|
||||
Xkdrive \- tiny X server
|
||||
.SH SYNOPSIS
|
||||
.B Xfbdev
|
||||
.RI [ :display ]
|
||||
.RI [ option ...]
|
||||
.SH DESCRIPTION
|
||||
.B Xkdrive
|
||||
is a family of X servers designed to be particularly small. This
|
||||
manual page describes the common functionality of the
|
||||
.B Xkdrive
|
||||
servers; for information on a specific X server, please refer to the
|
||||
relevant manual page.
|
||||
.SH OPTIONS
|
||||
In addition to the standard options accepted by all X servers (see
|
||||
Xserver(1)), all the
|
||||
.B Xkdrive
|
||||
servers accept the following options:
|
||||
.TP 8
|
||||
.B -dumb
|
||||
disable hardware acceleration.
|
||||
.TP 8
|
||||
.B -origin \fIX\fP,\fIY\fP
|
||||
Locates the next screen in the Xinerama virtual screen.
|
||||
.TP 8
|
||||
.B -screen \fIwidth\fBx\fIheight\fR[\fBx\fIdepth\fR[\fBx\fIfreq\fR]]\fR[\fB@\fIrotation\fR]\fB
|
||||
use a screen of the specified \fIwidth\fP, \fIheight\fP, screen \fIdepth\fP, \fIfrequency\fP, and \fIrotation\fP (0, 90, 180 and 270 are legal values).
|
||||
.TP 8
|
||||
.B -softCursor
|
||||
disable the hardware cursor.
|
||||
.TP 8
|
||||
.B -videoTest
|
||||
start the server, pause momentarily, and exit.
|
||||
.TP 8
|
||||
.B -zaphod
|
||||
disable switching screens by moving the pointer across a screen boundary.
|
||||
.TP 8
|
||||
.B -2button
|
||||
enable emulation of a middle mouse button by chording.
|
||||
.TP 8
|
||||
.B -3button
|
||||
disable emulation of a middle mouse button by chording.
|
||||
.SH SEE ALSO
|
||||
X(@miscmansuffix@), Xserver(1), xdm(1), xinit(1), Xvesa(1), Xfbdev(1).
|
||||
.SH AUTHORS
|
||||
The Xkdrive common core was written by Keith Packard,
|
||||
and is based on the Sample Implementation of X.
|
||||
1
hw/kdrive/ephyr/.gitignore
vendored
1
hw/kdrive/ephyr/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
Xephyr
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
Xephyr README
|
||||
=============
|
||||
|
||||
|
||||
What Is It ?
|
||||
============
|
||||
|
||||
Xephyr is a a kdrive server that outputs to a window on a pre-existing
|
||||
'host' X display. Think Xnest but with support for modern extensions
|
||||
like composite, damage and randr.
|
||||
|
||||
Unlike Xnest which is an X proxy, i.e. limited to the
|
||||
capabilities of the host X server, Xephyr is a real X server which
|
||||
uses the host X server window as "framebuffer" via fast SHM XImages.
|
||||
|
||||
It also has support for 'visually' debugging what the server is
|
||||
painting.
|
||||
|
||||
|
||||
How To Use
|
||||
==========
|
||||
|
||||
You probably want to run like;
|
||||
|
||||
Xephyr :1 -ac -screen 800x600 &
|
||||
|
||||
Then set DISPLAY=:1 and run whatever X apps you like.
|
||||
|
||||
Use 'xrandr' to change to orientation/size.
|
||||
|
||||
There is a '-parent' switch which works just like Xnest's ( for use
|
||||
with things like matchbox-nest - http://matchbox.handhelds.org ).
|
||||
|
||||
There is also a '-host-cursor' switch to set 'cursor acceleration' -
|
||||
The host's cursor is reused. This is only really there to aid
|
||||
debugging by avoiding server paints for the cursor. Performance
|
||||
improvement is negligible.
|
||||
|
||||
Send a SIGUSR1 to the server ( eg kill -USR1 `pidof Xephyr` ) to
|
||||
toggle the debugging mode. In this mode red rectangles are painted to
|
||||
screen areas getting painted before painting the actual content. The
|
||||
delay between this can be altered by setting a XEPHYR_PAUSE env var to
|
||||
a value in microseconds.
|
||||
|
||||
|
||||
Caveats
|
||||
=======
|
||||
|
||||
- Depth is limited to being the same as the host.
|
||||
*Update* As of 8/11/2004. Xephyr can now do 8bpp & 16bpp
|
||||
on 24bpp host.
|
||||
|
||||
- Rotated displays are currently updated via full blits. This
|
||||
is slower than a normal oprientated display. Debug mode will
|
||||
therefore not be of much use rotated.
|
||||
|
||||
- The '-host-cursor' cursor is static in its appearance.
|
||||
|
||||
- The build gets a warning about 'nanosleep'. I think the various '-D'
|
||||
build flags are causing this. I haven't figured as yet how to work
|
||||
around it. It doesn't appear to break anything however.
|
||||
|
||||
- Keyboard handling is basic but works.
|
||||
|
||||
- Mouse button 5 probably won't work.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Matthew Allum <mallum@o-hand.com> 2004
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* Xephyr - A kdrive X server that runs in a host X window.
|
||||
* Authored by Matthew Allum <mallum@o-hand.com>
|
||||
*
|
||||
* Copyright © 2004 Nokia
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Nokia not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Nokia makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _EPHYR_H_
|
||||
#define _EPHYR_H_
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
|
||||
#include "os.h" /* for OsSignal() */
|
||||
#include "kdrive.h"
|
||||
#include "hostx.h"
|
||||
#include "exa.h"
|
||||
|
||||
#ifdef RANDR
|
||||
#include "randrstr.h"
|
||||
#endif
|
||||
|
||||
#include "damage.h"
|
||||
|
||||
typedef struct _ephyrPriv {
|
||||
CARD8 *base;
|
||||
int bytes_per_line;
|
||||
} EphyrPriv;
|
||||
|
||||
typedef struct _ephyrFakexaPriv {
|
||||
ExaDriverPtr exa;
|
||||
Bool is_synced;
|
||||
|
||||
/* The following are arguments and other information from Prepare* calls
|
||||
* which are stored for use in the inner calls.
|
||||
*/
|
||||
int op;
|
||||
PicturePtr pSrcPicture, pMaskPicture, pDstPicture;
|
||||
void *saved_ptrs[3];
|
||||
PixmapPtr pDst, pSrc, pMask;
|
||||
GCPtr pGC;
|
||||
} EphyrFakexaPriv;
|
||||
|
||||
typedef struct _ephyrScrPriv {
|
||||
/* ephyr server info */
|
||||
Rotation randr;
|
||||
Bool shadow;
|
||||
DamagePtr pDamage;
|
||||
EphyrFakexaPriv *fakexa;
|
||||
|
||||
/* Host X window info */
|
||||
xcb_window_t win;
|
||||
xcb_window_t win_pre_existing; /* Set via -parent option like xnest */
|
||||
xcb_window_t peer_win; /* Used for GL; should be at most one */
|
||||
xcb_visualid_t vid;
|
||||
xcb_image_t *ximg;
|
||||
Bool win_explicit_position;
|
||||
int win_x, win_y;
|
||||
int win_width, win_height;
|
||||
int server_depth;
|
||||
const char *output; /* Set via -output option */
|
||||
unsigned char *fb_data; /* only used when host bpp != server bpp */
|
||||
xcb_shm_segment_info_t shminfo;
|
||||
size_t shmsize;
|
||||
|
||||
KdScreenInfo *screen;
|
||||
int mynum; /* Screen number */
|
||||
unsigned long cmap[256];
|
||||
|
||||
ScreenBlockHandlerProcPtr BlockHandler;
|
||||
|
||||
struct ephyr_glamor *glamor;
|
||||
} EphyrScrPriv;
|
||||
|
||||
extern KdCardFuncs ephyrFuncs;
|
||||
extern KdKeyboardInfo *ephyrKbd;
|
||||
extern KdPointerInfo *ephyrMouse;
|
||||
|
||||
extern miPointerScreenFuncRec ephyrPointerScreenFuncs;
|
||||
|
||||
Bool
|
||||
ephyrInitialize(KdCardInfo * card, EphyrPriv * priv);
|
||||
|
||||
Bool
|
||||
ephyrCardInit(KdCardInfo * card);
|
||||
|
||||
Bool
|
||||
ephyrScreenInitialize(KdScreenInfo *screen);
|
||||
|
||||
Bool
|
||||
ephyrInitScreen(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
ephyrFinishInitScreen(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
ephyrCreateResources(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrPreserve(KdCardInfo * card);
|
||||
|
||||
Bool
|
||||
ephyrEnable(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
ephyrDPMS(ScreenPtr pScreen, int mode);
|
||||
|
||||
void
|
||||
ephyrDisable(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrRestore(KdCardInfo * card);
|
||||
|
||||
void
|
||||
ephyrScreenFini(KdScreenInfo * screen);
|
||||
|
||||
void
|
||||
ephyrCloseScreen(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrCardFini(KdCardInfo * card);
|
||||
|
||||
void
|
||||
ephyrGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs);
|
||||
|
||||
void
|
||||
ephyrPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs);
|
||||
|
||||
Bool
|
||||
ephyrMapFramebuffer(KdScreenInfo * screen);
|
||||
|
||||
void *ephyrWindowLinear(ScreenPtr pScreen,
|
||||
CARD32 row,
|
||||
CARD32 offset, int mode, CARD32 *size, void *closure);
|
||||
|
||||
void
|
||||
ephyrSetScreenSizes(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
ephyrUnmapFramebuffer(KdScreenInfo * screen);
|
||||
|
||||
void
|
||||
ephyrUnsetInternalDamage(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
ephyrSetInternalDamage(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
ephyrCreateColormap(ColormapPtr pmap);
|
||||
|
||||
#ifdef RANDR
|
||||
Bool
|
||||
ephyrRandRGetInfo(ScreenPtr pScreen, Rotation * rotations);
|
||||
|
||||
Bool
|
||||
|
||||
ephyrRandRSetConfig(ScreenPtr pScreen,
|
||||
Rotation randr, int rate, RRScreenSizePtr pSize);
|
||||
Bool
|
||||
ephyrRandRInit(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrShadowUpdate(ScreenPtr pScreen, shadowBufPtr pBuf);
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ephyrUpdateModifierState(unsigned int state);
|
||||
|
||||
extern KdPointerDriver EphyrMouseDriver;
|
||||
|
||||
extern KdKeyboardDriver EphyrKeyboardDriver;
|
||||
|
||||
extern Bool ephyrCursorInit(ScreenPtr pScreen);
|
||||
|
||||
extern int ephyrBufferHeight(KdScreenInfo * screen);
|
||||
|
||||
/* ephyr_draw.c */
|
||||
|
||||
Bool
|
||||
ephyrDrawInit(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrDrawEnable(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrDrawDisable(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ephyrDrawFini(ScreenPtr pScreen);
|
||||
|
||||
/* hostx.c glamor support */
|
||||
Bool ephyr_glamor_init(ScreenPtr pScreen);
|
||||
Bool ephyr_glamor_create_screen_resources(ScreenPtr pScreen);
|
||||
void ephyr_glamor_enable(ScreenPtr pScreen);
|
||||
void ephyr_glamor_disable(ScreenPtr pScreen);
|
||||
void ephyr_glamor_fini(ScreenPtr pScreen);
|
||||
void ephyr_glamor_host_paint_rect(ScreenPtr pScreen);
|
||||
|
||||
/*ephyvideo.c*/
|
||||
|
||||
Bool ephyrInitVideo(ScreenPtr pScreen);
|
||||
|
||||
/* ephyr_glamor_xv.c */
|
||||
#ifdef GLAMOR
|
||||
void ephyr_glamor_xv_init(ScreenPtr screen);
|
||||
#else /* !GLAMOR */
|
||||
static inline void
|
||||
ephyr_glamor_xv_init(ScreenPtr screen)
|
||||
{
|
||||
}
|
||||
#endif /* !GLAMOR */
|
||||
|
||||
#endif
|
||||
|
|
@ -1,533 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "ephyr.h"
|
||||
#include "exa_priv.h"
|
||||
#include "fbpict.h"
|
||||
|
||||
#define EPHYR_TRACE_DRAW 0
|
||||
|
||||
#if EPHYR_TRACE_DRAW
|
||||
#define TRACE_DRAW() ErrorF("%s\n", __FUNCTION__);
|
||||
#else
|
||||
#define TRACE_DRAW() do { } while (0)
|
||||
#endif
|
||||
|
||||
/* Use some oddball alignments, to expose issues in alignment handling in EXA. */
|
||||
#define EPHYR_OFFSET_ALIGN 24
|
||||
#define EPHYR_PITCH_ALIGN 24
|
||||
|
||||
#define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024)
|
||||
#define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024)
|
||||
|
||||
/**
|
||||
* Forces a real devPrivate.ptr for hidden pixmaps, so that we can call down to
|
||||
* fb functions.
|
||||
*/
|
||||
static void
|
||||
ephyrPreparePipelinedAccess(PixmapPtr pPix, int index)
|
||||
{
|
||||
KdScreenPriv(pPix->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
assert(fakexa->saved_ptrs[index] == NULL);
|
||||
fakexa->saved_ptrs[index] = pPix->devPrivate.ptr;
|
||||
|
||||
if (pPix->devPrivate.ptr != NULL)
|
||||
return;
|
||||
|
||||
pPix->devPrivate.ptr = fakexa->exa->memoryBase + exaGetPixmapOffset(pPix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the original devPrivate.ptr of the pixmap from before we messed with
|
||||
* it.
|
||||
*/
|
||||
static void
|
||||
ephyrFinishPipelinedAccess(PixmapPtr pPix, int index)
|
||||
{
|
||||
KdScreenPriv(pPix->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
pPix->devPrivate.ptr = fakexa->saved_ptrs[index];
|
||||
fakexa->saved_ptrs[index] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a scratch GC for fbFill, and saves other parameters for the
|
||||
* ephyrSolid implementation.
|
||||
*/
|
||||
static Bool
|
||||
ephyrPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg)
|
||||
{
|
||||
ScreenPtr pScreen = pPix->drawable.pScreen;
|
||||
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
ChangeGCVal tmpval[3];
|
||||
|
||||
ephyrPreparePipelinedAccess(pPix, EXA_PREPARE_DEST);
|
||||
|
||||
fakexa->pDst = pPix;
|
||||
fakexa->pGC = GetScratchGC(pPix->drawable.depth, pScreen);
|
||||
|
||||
tmpval[0].val = alu;
|
||||
tmpval[1].val = pm;
|
||||
tmpval[2].val = fg;
|
||||
ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask | GCForeground,
|
||||
tmpval);
|
||||
|
||||
ValidateGC(&pPix->drawable, fakexa->pGC);
|
||||
|
||||
TRACE_DRAW();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does an fbFill of the rectangle to be drawn.
|
||||
*/
|
||||
static void
|
||||
ephyrSolid(PixmapPtr pPix, int x1, int y1, int x2, int y2)
|
||||
{
|
||||
ScreenPtr pScreen = pPix->drawable.pScreen;
|
||||
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
fbFill(&fakexa->pDst->drawable, fakexa->pGC, x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the scratch GC created in ephyrPrepareSolid.
|
||||
*/
|
||||
static void
|
||||
ephyrDoneSolid(PixmapPtr pPix)
|
||||
{
|
||||
ScreenPtr pScreen = pPix->drawable.pScreen;
|
||||
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
FreeScratchGC(fakexa->pGC);
|
||||
|
||||
ephyrFinishPipelinedAccess(pPix, EXA_PREPARE_DEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a scratch GC for fbCopyArea, and saves other parameters for the
|
||||
* ephyrCopy implementation.
|
||||
*/
|
||||
static Bool
|
||||
ephyrPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, int dx, int dy, int alu,
|
||||
Pixel pm)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->drawable.pScreen;
|
||||
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
ChangeGCVal tmpval[2];
|
||||
|
||||
ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
|
||||
ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
|
||||
|
||||
fakexa->pSrc = pSrc;
|
||||
fakexa->pDst = pDst;
|
||||
fakexa->pGC = GetScratchGC(pDst->drawable.depth, pScreen);
|
||||
|
||||
tmpval[0].val = alu;
|
||||
tmpval[1].val = pm;
|
||||
ChangeGC(NullClient, fakexa->pGC, GCFunction | GCPlaneMask, tmpval);
|
||||
|
||||
ValidateGC(&pDst->drawable, fakexa->pGC);
|
||||
|
||||
TRACE_DRAW();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does an fbCopyArea to take care of the requested copy.
|
||||
*/
|
||||
static void
|
||||
ephyrCopy(PixmapPtr pDst, int srcX, int srcY, int dstX, int dstY, int w, int h)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->drawable.pScreen;
|
||||
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
fbCopyArea(&fakexa->pSrc->drawable, &fakexa->pDst->drawable, fakexa->pGC,
|
||||
srcX, srcY, w, h, dstX, dstY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the scratch GC created in ephyrPrepareCopy.
|
||||
*/
|
||||
static void
|
||||
ephyrDoneCopy(PixmapPtr pDst)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->drawable.pScreen;
|
||||
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
FreeScratchGC(fakexa->pGC);
|
||||
|
||||
ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
|
||||
ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reports that we can always accelerate the given operation. This may not be
|
||||
* desirable from an EXA testing standpoint -- testing the fallback paths would
|
||||
* be useful, too.
|
||||
*/
|
||||
static Bool
|
||||
ephyrCheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
|
||||
PicturePtr pDstPicture)
|
||||
{
|
||||
/* Exercise the component alpha helper, so fail on this case like a normal
|
||||
* driver
|
||||
*/
|
||||
if (pMaskPicture && pMaskPicture->componentAlpha && op == PictOpOver)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves off the parameters for ephyrComposite.
|
||||
*/
|
||||
static Bool
|
||||
ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
|
||||
PicturePtr pDstPicture, PixmapPtr pSrc, PixmapPtr pMask,
|
||||
PixmapPtr pDst)
|
||||
{
|
||||
KdScreenPriv(pDst->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
|
||||
if (pSrc != NULL)
|
||||
ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
|
||||
if (pMask != NULL)
|
||||
ephyrPreparePipelinedAccess(pMask, EXA_PREPARE_MASK);
|
||||
|
||||
fakexa->op = op;
|
||||
fakexa->pSrcPicture = pSrcPicture;
|
||||
fakexa->pMaskPicture = pMaskPicture;
|
||||
fakexa->pDstPicture = pDstPicture;
|
||||
fakexa->pSrc = pSrc;
|
||||
fakexa->pMask = pMask;
|
||||
fakexa->pDst = pDst;
|
||||
|
||||
TRACE_DRAW();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does an fbComposite to complete the requested drawing operation.
|
||||
*/
|
||||
static void
|
||||
ephyrComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
|
||||
int dstX, int dstY, int w, int h)
|
||||
{
|
||||
KdScreenPriv(pDst->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
fbComposite(fakexa->op, fakexa->pSrcPicture, fakexa->pMaskPicture,
|
||||
fakexa->pDstPicture, srcX, srcY, maskX, maskY, dstX, dstY,
|
||||
w, h);
|
||||
}
|
||||
|
||||
static void
|
||||
ephyrDoneComposite(PixmapPtr pDst)
|
||||
{
|
||||
KdScreenPriv(pDst->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
if (fakexa->pMask != NULL)
|
||||
ephyrFinishPipelinedAccess(fakexa->pMask, EXA_PREPARE_MASK);
|
||||
if (fakexa->pSrc != NULL)
|
||||
ephyrFinishPipelinedAccess(fakexa->pSrc, EXA_PREPARE_SRC);
|
||||
ephyrFinishPipelinedAccess(fakexa->pDst, EXA_PREPARE_DEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does fake acceleration of DownloadFromScren using memcpy.
|
||||
*/
|
||||
static Bool
|
||||
ephyrDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h, char *dst,
|
||||
int dst_pitch)
|
||||
{
|
||||
KdScreenPriv(pSrc->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
unsigned char *src;
|
||||
int src_pitch, cpp;
|
||||
|
||||
if (pSrc->drawable.bitsPerPixel < 8)
|
||||
return FALSE;
|
||||
|
||||
ephyrPreparePipelinedAccess(pSrc, EXA_PREPARE_SRC);
|
||||
|
||||
cpp = pSrc->drawable.bitsPerPixel / 8;
|
||||
src_pitch = exaGetPixmapPitch(pSrc);
|
||||
src = fakexa->exa->memoryBase + exaGetPixmapOffset(pSrc);
|
||||
src += y * src_pitch + x * cpp;
|
||||
|
||||
for (; h > 0; h--) {
|
||||
memcpy(dst, src, w * cpp);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
|
||||
exaMarkSync(pSrc->drawable.pScreen);
|
||||
|
||||
ephyrFinishPipelinedAccess(pSrc, EXA_PREPARE_SRC);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does fake acceleration of UploadToScreen using memcpy.
|
||||
*/
|
||||
static Bool
|
||||
ephyrUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, char *src,
|
||||
int src_pitch)
|
||||
{
|
||||
KdScreenPriv(pDst->drawable.pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
unsigned char *dst;
|
||||
int dst_pitch, cpp;
|
||||
|
||||
if (pDst->drawable.bitsPerPixel < 8)
|
||||
return FALSE;
|
||||
|
||||
ephyrPreparePipelinedAccess(pDst, EXA_PREPARE_DEST);
|
||||
|
||||
cpp = pDst->drawable.bitsPerPixel / 8;
|
||||
dst_pitch = exaGetPixmapPitch(pDst);
|
||||
dst = fakexa->exa->memoryBase + exaGetPixmapOffset(pDst);
|
||||
dst += y * dst_pitch + x * cpp;
|
||||
|
||||
for (; h > 0; h--) {
|
||||
memcpy(dst, src, w * cpp);
|
||||
dst += dst_pitch;
|
||||
src += src_pitch;
|
||||
}
|
||||
|
||||
exaMarkSync(pDst->drawable.pScreen);
|
||||
|
||||
ephyrFinishPipelinedAccess(pDst, EXA_PREPARE_DEST);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
ephyrPrepareAccess(PixmapPtr pPix, int index)
|
||||
{
|
||||
/* Make sure we don't somehow end up with a pointer that is in framebuffer
|
||||
* and hasn't been readied for us.
|
||||
*/
|
||||
assert(pPix->devPrivate.ptr != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* In fakexa, we currently only track whether we have synced to the latest
|
||||
* "accelerated" drawing that has happened or not. It's not used for anything
|
||||
* yet.
|
||||
*/
|
||||
static int
|
||||
ephyrMarkSync(ScreenPtr pScreen)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
fakexa->is_synced = FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes that we're waiting on the latest marker. When EXA gets smarter and
|
||||
* starts using markers in a fine-grained way (for example, waiting on drawing
|
||||
* to required pixmaps to complete, rather than waiting for all drawing to
|
||||
* complete), we'll want to make the ephyrMarkSync/ephyrWaitMarker
|
||||
* implementation fine-grained as well.
|
||||
*/
|
||||
static void
|
||||
ephyrWaitMarker(ScreenPtr pScreen, int marker)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrFakexaPriv *fakexa = scrpriv->fakexa;
|
||||
|
||||
fakexa->is_synced = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function initializes EXA to use the fake acceleration implementation
|
||||
* which just falls through to software. The purpose is to have a reliable,
|
||||
* correct driver with which to test changes to the EXA core.
|
||||
*/
|
||||
Bool
|
||||
ephyrDrawInit(ScreenPtr pScreen)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = screen->driver;
|
||||
EphyrPriv *priv = screen->card->driver;
|
||||
EphyrFakexaPriv *fakexa;
|
||||
Bool success;
|
||||
|
||||
fakexa = calloc(1, sizeof(*fakexa));
|
||||
if (fakexa == NULL)
|
||||
return FALSE;
|
||||
|
||||
fakexa->exa = exaDriverAlloc();
|
||||
if (fakexa->exa == NULL) {
|
||||
free(fakexa);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
fakexa->exa->memoryBase = (CARD8 *) (priv->base);
|
||||
fakexa->exa->memorySize = priv->bytes_per_line * ephyrBufferHeight(screen);
|
||||
fakexa->exa->offScreenBase = priv->bytes_per_line * screen->height;
|
||||
|
||||
/* Since we statically link against EXA, we shouldn't have to be smart about
|
||||
* versioning.
|
||||
*/
|
||||
fakexa->exa->exa_major = 2;
|
||||
fakexa->exa->exa_minor = 0;
|
||||
|
||||
fakexa->exa->PrepareSolid = ephyrPrepareSolid;
|
||||
fakexa->exa->Solid = ephyrSolid;
|
||||
fakexa->exa->DoneSolid = ephyrDoneSolid;
|
||||
|
||||
fakexa->exa->PrepareCopy = ephyrPrepareCopy;
|
||||
fakexa->exa->Copy = ephyrCopy;
|
||||
fakexa->exa->DoneCopy = ephyrDoneCopy;
|
||||
|
||||
fakexa->exa->CheckComposite = ephyrCheckComposite;
|
||||
fakexa->exa->PrepareComposite = ephyrPrepareComposite;
|
||||
fakexa->exa->Composite = ephyrComposite;
|
||||
fakexa->exa->DoneComposite = ephyrDoneComposite;
|
||||
|
||||
fakexa->exa->DownloadFromScreen = ephyrDownloadFromScreen;
|
||||
fakexa->exa->UploadToScreen = ephyrUploadToScreen;
|
||||
|
||||
fakexa->exa->MarkSync = ephyrMarkSync;
|
||||
fakexa->exa->WaitMarker = ephyrWaitMarker;
|
||||
|
||||
fakexa->exa->PrepareAccess = ephyrPrepareAccess;
|
||||
|
||||
fakexa->exa->pixmapOffsetAlign = EPHYR_OFFSET_ALIGN;
|
||||
fakexa->exa->pixmapPitchAlign = EPHYR_PITCH_ALIGN;
|
||||
|
||||
fakexa->exa->maxX = 1023;
|
||||
fakexa->exa->maxY = 1023;
|
||||
|
||||
fakexa->exa->flags = EXA_OFFSCREEN_PIXMAPS;
|
||||
|
||||
success = exaDriverInit(pScreen, fakexa->exa);
|
||||
if (success) {
|
||||
ErrorF("Initialized fake EXA acceleration\n");
|
||||
scrpriv->fakexa = fakexa;
|
||||
}
|
||||
else {
|
||||
ErrorF("Failed to initialize EXA\n");
|
||||
free(fakexa->exa);
|
||||
free(fakexa);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
ephyrDrawEnable(ScreenPtr pScreen)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ephyrDrawDisable(ScreenPtr pScreen)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ephyrDrawFini(ScreenPtr pScreen)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* exaDDXDriverInit is required by the top-level EXA module, and is used by
|
||||
* the xorg DDX to hook in its EnableDisableFB wrapper. We don't need it, since
|
||||
* we won't be enabling/disabling the FB.
|
||||
*/
|
||||
void
|
||||
exaDDXDriverInit(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
pExaScr->migration = ExaMigrationSmart;
|
||||
pExaScr->checkDirtyCorrectness = TRUE;
|
||||
}
|
||||
|
|
@ -1,440 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file ephyr_glamor.c
|
||||
*
|
||||
* Glamor support and EGL setup.
|
||||
*/
|
||||
#define MESA_EGL_NO_X11_HEADERS
|
||||
#define EGL_NO_X11
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
#include <pixman.h>
|
||||
#include "glamor_context.h"
|
||||
#include "glamor_egl.h"
|
||||
#include "glamor_priv.h"
|
||||
#include "ephyr.h"
|
||||
#include "ephyr_glamor.h"
|
||||
#include "os.h"
|
||||
|
||||
/* until we need geometry shaders GL3.1 should suffice. */
|
||||
/* Xephyr has its own copy of this for build reasons */
|
||||
#define GLAMOR_GL_CORE_VER_MAJOR 3
|
||||
#define GLAMOR_GL_CORE_VER_MINOR 1
|
||||
/** @{
|
||||
*
|
||||
* global state for Xephyr with glamor, all of which is arguably a bug.
|
||||
*/
|
||||
Bool ephyr_glamor_gles2;
|
||||
Bool ephyr_glamor_skip_present;
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* Per-screen state for Xephyr with glamor.
|
||||
*/
|
||||
struct ephyr_glamor {
|
||||
EGLDisplay dpy;
|
||||
EGLContext ctx;
|
||||
xcb_window_t win;
|
||||
EGLSurface egl_win;
|
||||
|
||||
GLuint tex;
|
||||
|
||||
GLuint texture_shader;
|
||||
GLuint texture_shader_position_loc;
|
||||
GLuint texture_shader_texcoord_loc;
|
||||
|
||||
/* Size of the window that we're rendering to. */
|
||||
unsigned width, height;
|
||||
|
||||
GLuint vao, vbo;
|
||||
};
|
||||
|
||||
static void
|
||||
glamor_egl_make_current(struct glamor_context *glamor_ctx)
|
||||
{
|
||||
/* There's only a single global dispatch table in Mesa. EGL, GLX,
|
||||
* and AIGLX's direct dispatch table manipulation don't talk to
|
||||
* each other. We need to set the context to NULL first to avoid
|
||||
* EGL's no-op context change fast path when switching back to
|
||||
* EGL.
|
||||
*/
|
||||
eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
|
||||
if (!eglMakeCurrent(glamor_ctx->display,
|
||||
glamor_ctx->surface, glamor_ctx->surface,
|
||||
glamor_ctx->ctx)) {
|
||||
FatalError("Failed to make EGL context current\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
|
||||
{
|
||||
KdScreenPriv(screen);
|
||||
KdScreenInfo *kd_screen = pScreenPriv->screen;
|
||||
EphyrScrPriv *scrpriv = kd_screen->driver;
|
||||
struct ephyr_glamor *ephyr_glamor = scrpriv->glamor;
|
||||
|
||||
glamor_enable_dri3(screen);
|
||||
glamor_ctx->display = ephyr_glamor->dpy;
|
||||
glamor_ctx->ctx = ephyr_glamor->ctx;
|
||||
glamor_ctx->surface = ephyr_glamor->egl_win;
|
||||
glamor_ctx->make_current = glamor_egl_make_current;
|
||||
}
|
||||
|
||||
int
|
||||
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
||||
PixmapPtr pixmap,
|
||||
CARD16 *stride, CARD32 *size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
|
||||
uint32_t *offsets, uint32_t *strides,
|
||||
uint64_t *modifier)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
|
||||
CARD16 *stride, CARD32 *size)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static GLuint
|
||||
ephyr_glamor_build_glsl_prog(GLuint vs, GLuint fs)
|
||||
{
|
||||
GLint ok;
|
||||
GLuint prog;
|
||||
|
||||
prog = glCreateProgram();
|
||||
glAttachShader(prog, vs);
|
||||
glAttachShader(prog, fs);
|
||||
|
||||
glLinkProgram(prog);
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &ok);
|
||||
if (!ok) {
|
||||
GLchar *info;
|
||||
GLint size;
|
||||
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
|
||||
info = malloc(size);
|
||||
|
||||
glGetProgramInfoLog(prog, size, NULL, info);
|
||||
ErrorF("Failed to link: %s\n", info);
|
||||
FatalError("GLSL link failure\n");
|
||||
}
|
||||
|
||||
return prog;
|
||||
}
|
||||
|
||||
static void
|
||||
ephyr_glamor_setup_texturing_shader(struct ephyr_glamor *glamor)
|
||||
{
|
||||
const char *vs_source =
|
||||
"attribute vec2 texcoord;\n"
|
||||
"attribute vec2 position;\n"
|
||||
"varying vec2 t;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" t = texcoord;\n"
|
||||
" gl_Position = vec4(position, 0, 1);\n"
|
||||
"}\n";
|
||||
|
||||
const char *fs_source =
|
||||
"#ifdef GL_ES\n"
|
||||
"precision mediump float;\n"
|
||||
"#endif\n"
|
||||
"\n"
|
||||
"varying vec2 t;\n"
|
||||
"uniform sampler2D s; /* initially 0 */\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_FragColor = texture2D(s, t);\n"
|
||||
"}\n";
|
||||
|
||||
GLuint fs, vs, prog;
|
||||
|
||||
vs = glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source);
|
||||
fs = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source);
|
||||
prog = ephyr_glamor_build_glsl_prog(vs, fs);
|
||||
|
||||
glamor->texture_shader = prog;
|
||||
glamor->texture_shader_position_loc = glGetAttribLocation(prog, "position");
|
||||
assert(glamor->texture_shader_position_loc != -1);
|
||||
glamor->texture_shader_texcoord_loc = glGetAttribLocation(prog, "texcoord");
|
||||
assert(glamor->texture_shader_texcoord_loc != -1);
|
||||
}
|
||||
|
||||
#ifndef EGL_PLATFORM_XCB_EXT
|
||||
#define EGL_PLATFORM_XCB_EXT 0x31DC
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
#ifndef RTLD_DEFAULT
|
||||
#define RTLD_DEFAULT NULL
|
||||
#endif
|
||||
|
||||
/* (loud booing)
|
||||
*
|
||||
* keeping this as a static variable is bad form, we _could_ have zaphod heads
|
||||
* on different displays (for example). but other bits of Xephyr are already
|
||||
* broken for that case, and fixing that would entail fixing the rest of the
|
||||
* contortions with hostx.c anyway, so this works for now.
|
||||
*/
|
||||
static EGLDisplay edpy = EGL_NO_DISPLAY;
|
||||
|
||||
xcb_connection_t *
|
||||
ephyr_glamor_connect(void)
|
||||
{
|
||||
int major = 0, minor = 0;
|
||||
|
||||
/*
|
||||
* Try pure xcb first. If that doesn't work but we can find XOpenDisplay,
|
||||
* fall back to xlib. This lets us potentially not load libX11 at all, if
|
||||
* the EGL is also pure xcb.
|
||||
*/
|
||||
|
||||
if (epoxy_has_egl_extension(EGL_NO_DISPLAY, "EGL_EXT_platform_xcb")) {
|
||||
xcb_connection_t *conn = xcb_connect(NULL, NULL);
|
||||
EGLDisplay dpy = glamor_egl_get_display(EGL_PLATFORM_XCB_EXT, conn);
|
||||
|
||||
if (dpy == EGL_NO_DISPLAY) {
|
||||
xcb_disconnect(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
edpy = dpy;
|
||||
eglInitialize(dpy, &major, &minor);
|
||||
return conn;
|
||||
}
|
||||
|
||||
if (epoxy_has_egl_extension(EGL_NO_DISPLAY, "EGL_EXT_platform_x11") ||
|
||||
epoxy_has_egl_extension(EGL_NO_DISPLAY, "EGL_KHR_platform_x11)")) {
|
||||
void *lib = NULL;
|
||||
xcb_connection_t *ret = NULL;
|
||||
void *(*x_open_display)(void *) =
|
||||
(void *) dlsym(RTLD_DEFAULT, "XOpenDisplay");
|
||||
xcb_connection_t *(*x_get_xcb_connection)(void *) =
|
||||
(void *) dlsym(RTLD_DEFAULT, "XGetXCBConnection");
|
||||
|
||||
if (x_open_display == NULL)
|
||||
return NULL;
|
||||
|
||||
if (x_get_xcb_connection == NULL) {
|
||||
lib = dlopen("libX11-xcb.so.1", RTLD_LOCAL | RTLD_LAZY);
|
||||
x_get_xcb_connection =
|
||||
(void *) dlsym(lib, "XGetXCBConnection");
|
||||
}
|
||||
|
||||
if (x_get_xcb_connection == NULL)
|
||||
goto out;
|
||||
|
||||
void *xdpy = x_open_display(NULL);
|
||||
EGLDisplay dpy = glamor_egl_get_display(EGL_PLATFORM_X11_KHR, xdpy);
|
||||
if (dpy == EGL_NO_DISPLAY)
|
||||
goto out;
|
||||
|
||||
edpy = dpy;
|
||||
eglInitialize(dpy, &major, &minor);
|
||||
ret = x_get_xcb_connection(xdpy);
|
||||
out:
|
||||
if (lib)
|
||||
dlclose(lib);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ephyr_glamor_set_texture(struct ephyr_glamor *glamor, uint32_t tex)
|
||||
{
|
||||
glamor->tex = tex;
|
||||
}
|
||||
|
||||
static void
|
||||
ephyr_glamor_set_vertices(struct ephyr_glamor *glamor)
|
||||
{
|
||||
glVertexAttribPointer(glamor->texture_shader_position_loc,
|
||||
2, GL_FLOAT, FALSE, 0, (void *) 0);
|
||||
glVertexAttribPointer(glamor->texture_shader_texcoord_loc,
|
||||
2, GL_FLOAT, FALSE, 0, (void *) (sizeof (float) * 8));
|
||||
|
||||
glEnableVertexAttribArray(glamor->texture_shader_position_loc);
|
||||
glEnableVertexAttribArray(glamor->texture_shader_texcoord_loc);
|
||||
}
|
||||
|
||||
void
|
||||
ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
|
||||
struct pixman_region16 *damage)
|
||||
{
|
||||
GLint old_vao;
|
||||
|
||||
/* Skip presenting the output in this mode. Presentation is
|
||||
* expensive, and if we're just running the X Test suite headless,
|
||||
* nobody's watching.
|
||||
*/
|
||||
if (ephyr_glamor_skip_present)
|
||||
return;
|
||||
|
||||
eglMakeCurrent(glamor->dpy, glamor->egl_win, glamor->egl_win, glamor->ctx);
|
||||
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao);
|
||||
glBindVertexArray(glamor->vao);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glUseProgram(glamor->texture_shader);
|
||||
glViewport(0, 0, glamor->width, glamor->height);
|
||||
if (!ephyr_glamor_gles2)
|
||||
glDisable(GL_COLOR_LOGIC_OP);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, glamor->tex);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glBindVertexArray(old_vao);
|
||||
|
||||
eglSwapBuffers(glamor->dpy, glamor->egl_win);
|
||||
}
|
||||
|
||||
struct ephyr_glamor *
|
||||
ephyr_glamor_screen_init(xcb_window_t win, xcb_visualid_t vid)
|
||||
{
|
||||
static const float position[] = {
|
||||
-1, -1,
|
||||
1, -1,
|
||||
1, 1,
|
||||
-1, 1,
|
||||
0, 1,
|
||||
1, 1,
|
||||
1, 0,
|
||||
0, 0,
|
||||
};
|
||||
GLint old_vao;
|
||||
|
||||
EGLContext ctx;
|
||||
struct ephyr_glamor *glamor;
|
||||
EGLSurface egl_win;
|
||||
|
||||
glamor = calloc(1, sizeof(struct ephyr_glamor));
|
||||
if (!glamor) {
|
||||
FatalError("malloc");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const EGLint config_attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NATIVE_VISUAL_ID, vid,
|
||||
EGL_NONE,
|
||||
};
|
||||
EGLConfig config = EGL_NO_CONFIG_KHR;
|
||||
int num_configs = 0;
|
||||
|
||||
/* (loud booing (see above)) */
|
||||
glamor->dpy = edpy;
|
||||
|
||||
eglChooseConfig(glamor->dpy, config_attribs, &config, 1, &num_configs);
|
||||
if (num_configs != 1)
|
||||
FatalError("Unable to find an EGLConfig for vid %#x\n", vid);
|
||||
|
||||
egl_win = eglCreatePlatformWindowSurfaceEXT(glamor->dpy, config,
|
||||
&win, NULL);
|
||||
|
||||
if (ephyr_glamor_gles2)
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
else
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
|
||||
EGLint context_attribs[5];
|
||||
int i = 0;
|
||||
context_attribs[i++] = EGL_CONTEXT_MAJOR_VERSION;
|
||||
context_attribs[i++] = ephyr_glamor_gles2 ? 2 : 3;
|
||||
context_attribs[i++] = EGL_CONTEXT_MINOR_VERSION;
|
||||
context_attribs[i++] = ephyr_glamor_gles2 ? 0 : 1;
|
||||
context_attribs[i++] = EGL_NONE;
|
||||
|
||||
ctx = eglCreateContext(glamor->dpy, EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
|
||||
context_attribs);
|
||||
|
||||
if (ctx == NULL)
|
||||
FatalError("eglCreateContext failed\n");
|
||||
|
||||
if (!eglMakeCurrent(glamor->dpy, egl_win, egl_win, ctx))
|
||||
FatalError("eglMakeCurrent failed\n");
|
||||
|
||||
glamor->ctx = ctx;
|
||||
glamor->win = win;
|
||||
glamor->egl_win = egl_win;
|
||||
ephyr_glamor_setup_texturing_shader(glamor);
|
||||
|
||||
glGenVertexArrays(1, &glamor->vao);
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &old_vao);
|
||||
glBindVertexArray(glamor->vao);
|
||||
|
||||
glGenBuffers(1, &glamor->vbo);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, glamor->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof (position), position, GL_STATIC_DRAW);
|
||||
|
||||
ephyr_glamor_set_vertices(glamor);
|
||||
glBindVertexArray(old_vao);
|
||||
|
||||
return glamor;
|
||||
}
|
||||
|
||||
void
|
||||
ephyr_glamor_screen_fini(struct ephyr_glamor *glamor)
|
||||
{
|
||||
eglMakeCurrent(glamor->dpy,
|
||||
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
||||
EGL_NO_CONTEXT);
|
||||
eglDestroyContext(glamor->dpy, glamor->ctx);
|
||||
eglDestroySurface(glamor->dpy, glamor->egl_win);
|
||||
|
||||
free(glamor);
|
||||
}
|
||||
|
||||
void
|
||||
ephyr_glamor_set_window_size(struct ephyr_glamor *glamor,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
if (!glamor)
|
||||
return;
|
||||
|
||||
glamor->width = width;
|
||||
glamor->height = height;
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2013 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include "dix-config.h"
|
||||
|
||||
struct ephyr_glamor;
|
||||
struct pixman_region16;
|
||||
|
||||
xcb_connection_t *
|
||||
ephyr_glamor_connect(void);
|
||||
|
||||
void
|
||||
ephyr_glamor_set_texture(struct ephyr_glamor *ephyr_glamor, uint32_t tex);
|
||||
|
||||
struct ephyr_glamor *
|
||||
ephyr_glamor_screen_init(xcb_window_t win, xcb_visualid_t vid);
|
||||
|
||||
void
|
||||
ephyr_glamor_screen_fini(struct ephyr_glamor *glamor);
|
||||
|
||||
#ifdef GLAMOR
|
||||
void
|
||||
ephyr_glamor_set_window_size(struct ephyr_glamor *glamor,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
void
|
||||
ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
|
||||
struct pixman_region16 *damage);
|
||||
|
||||
#else /* !GLAMOR */
|
||||
|
||||
static inline void
|
||||
ephyr_glamor_set_window_size(struct ephyr_glamor *glamor,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
|
||||
struct pixman_region16 *damage)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* !GLAMOR */
|
||||
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2014 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "kdrive.h"
|
||||
#include "kxv.h"
|
||||
#include "ephyr.h"
|
||||
#include "glamor_priv.h"
|
||||
|
||||
#include <X11/extensions/Xv.h>
|
||||
#include "fourcc.h"
|
||||
|
||||
#define NUM_FORMATS 3
|
||||
|
||||
static KdVideoFormatRec Formats[NUM_FORMATS] = {
|
||||
{15, TrueColor}, {16, TrueColor}, {24, TrueColor}
|
||||
};
|
||||
|
||||
static void
|
||||
ephyr_glamor_xv_stop_video(KdScreenInfo *screen, void *data, Bool cleanup)
|
||||
{
|
||||
if (!cleanup)
|
||||
return;
|
||||
|
||||
glamor_xv_stop_video(data);
|
||||
}
|
||||
|
||||
static int
|
||||
ephyr_glamor_xv_set_port_attribute(KdScreenInfo *screen,
|
||||
Atom attribute, int value, void *data)
|
||||
{
|
||||
return glamor_xv_set_port_attribute(data, attribute, (INT32)value);
|
||||
}
|
||||
|
||||
static int
|
||||
ephyr_glamor_xv_get_port_attribute(KdScreenInfo *screen,
|
||||
Atom attribute, int *value, void *data)
|
||||
{
|
||||
return glamor_xv_get_port_attribute(data, attribute, (INT32 *)value);
|
||||
}
|
||||
|
||||
static void
|
||||
ephyr_glamor_xv_query_best_size(KdScreenInfo *screen,
|
||||
Bool motion,
|
||||
short vid_w, short vid_h,
|
||||
short drw_w, short drw_h,
|
||||
unsigned int *p_w, unsigned int *p_h,
|
||||
void *data)
|
||||
{
|
||||
*p_w = drw_w;
|
||||
*p_h = drw_h;
|
||||
}
|
||||
|
||||
static int
|
||||
ephyr_glamor_xv_query_image_attributes(KdScreenInfo *screen,
|
||||
int id,
|
||||
unsigned short *w, unsigned short *h,
|
||||
int *pitches, int *offsets)
|
||||
{
|
||||
return glamor_xv_query_image_attributes(id, w, h, pitches, offsets);
|
||||
}
|
||||
|
||||
static int
|
||||
ephyr_glamor_xv_put_image(KdScreenInfo *screen,
|
||||
DrawablePtr pDrawable,
|
||||
short src_x, short src_y,
|
||||
short drw_x, short drw_y,
|
||||
short src_w, short src_h,
|
||||
short drw_w, short drw_h,
|
||||
int id,
|
||||
unsigned char *buf,
|
||||
short width,
|
||||
short height,
|
||||
Bool sync,
|
||||
RegionPtr clipBoxes, void *data)
|
||||
{
|
||||
return glamor_xv_put_image(data, pDrawable,
|
||||
src_x, src_y,
|
||||
drw_x, drw_y,
|
||||
src_w, src_h,
|
||||
drw_w, drw_h,
|
||||
id, buf, width, height, sync, clipBoxes);
|
||||
}
|
||||
|
||||
void
|
||||
ephyr_glamor_xv_init(ScreenPtr screen)
|
||||
{
|
||||
KdVideoAdaptorRec *adaptor;
|
||||
glamor_port_private *port_privates;
|
||||
KdVideoEncodingRec encoding = {
|
||||
0,
|
||||
"XV_IMAGE",
|
||||
/* These sizes should probably be GL_MAX_TEXTURE_SIZE instead
|
||||
* of 2048, but our context isn't set up yet.
|
||||
*/
|
||||
2048, 2048,
|
||||
{1, 1}
|
||||
};
|
||||
int i;
|
||||
|
||||
glamor_xv_core_init(screen);
|
||||
|
||||
adaptor = xnfcalloc(1, sizeof(*adaptor));
|
||||
|
||||
adaptor->name = "glamor textured video";
|
||||
adaptor->type = XvWindowMask | XvInputMask | XvImageMask;
|
||||
adaptor->flags = 0;
|
||||
adaptor->nEncodings = 1;
|
||||
adaptor->pEncodings = &encoding;
|
||||
|
||||
adaptor->pFormats = Formats;
|
||||
adaptor->nFormats = NUM_FORMATS;
|
||||
|
||||
adaptor->nPorts = 16; /* Some absurd number */
|
||||
port_privates = xnfcalloc(adaptor->nPorts,
|
||||
sizeof(glamor_port_private));
|
||||
adaptor->pPortPrivates = xnfcalloc(adaptor->nPorts,
|
||||
sizeof(glamor_port_private *));
|
||||
for (i = 0; i < adaptor->nPorts; i++) {
|
||||
adaptor->pPortPrivates[i].ptr = &port_privates[i];
|
||||
glamor_xv_init_port(&port_privates[i]);
|
||||
}
|
||||
|
||||
adaptor->pAttributes = glamor_xv_attributes;
|
||||
adaptor->nAttributes = glamor_xv_num_attributes;
|
||||
|
||||
adaptor->pImages = glamor_xv_images;
|
||||
adaptor->nImages = glamor_xv_num_images;
|
||||
|
||||
adaptor->StopVideo = ephyr_glamor_xv_stop_video;
|
||||
adaptor->SetPortAttribute = ephyr_glamor_xv_set_port_attribute;
|
||||
adaptor->GetPortAttribute = ephyr_glamor_xv_get_port_attribute;
|
||||
adaptor->QueryBestSize = ephyr_glamor_xv_query_best_size;
|
||||
adaptor->PutImage = ephyr_glamor_xv_put_image;
|
||||
adaptor->QueryImageAttributes = ephyr_glamor_xv_query_image_attributes;
|
||||
|
||||
KdXVScreenInit(screen, adaptor, 1);
|
||||
}
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2014 Red Hat, Inc.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Author:
|
||||
* Adam Jackson <ajax@redhat.com>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "ephyr.h"
|
||||
#include "ephyrlog.h"
|
||||
#include "hostx.h"
|
||||
#include "cursorstr.h"
|
||||
#include <xcb/render.h>
|
||||
#include <xcb/xcb_renderutil.h>
|
||||
|
||||
static DevPrivateKeyRec ephyrCursorPrivateKey;
|
||||
|
||||
typedef struct _ephyrCursor {
|
||||
xcb_cursor_t cursor;
|
||||
} ephyrCursorRec, *ephyrCursorPtr;
|
||||
|
||||
static ephyrCursorPtr
|
||||
ephyrGetCursor(CursorPtr cursor)
|
||||
{
|
||||
return dixGetPrivateAddr(&cursor->devPrivates, &ephyrCursorPrivateKey);
|
||||
}
|
||||
|
||||
static void
|
||||
ephyrRealizeCoreCursor(EphyrScrPriv *scr, CursorPtr cursor)
|
||||
{
|
||||
ephyrCursorPtr hw = ephyrGetCursor(cursor);
|
||||
xcb_connection_t *conn = hostx_get_xcbconn();
|
||||
xcb_pixmap_t source, mask;
|
||||
xcb_image_t *image;
|
||||
xcb_gcontext_t gc;
|
||||
int w = cursor->bits->width, h = cursor->bits->height;
|
||||
uint32_t gcmask = XCB_GC_FUNCTION |
|
||||
XCB_GC_PLANE_MASK |
|
||||
XCB_GC_FOREGROUND |
|
||||
XCB_GC_BACKGROUND |
|
||||
XCB_GC_CLIP_MASK;
|
||||
uint32_t val[] = {
|
||||
XCB_GX_COPY, /* function */
|
||||
~0, /* planemask */
|
||||
1L, /* foreground */
|
||||
0L, /* background */
|
||||
None, /* clipmask */
|
||||
};
|
||||
|
||||
source = xcb_generate_id(conn);
|
||||
mask = xcb_generate_id(conn);
|
||||
xcb_create_pixmap(conn, 1, source, scr->win, w, h);
|
||||
xcb_create_pixmap(conn, 1, mask, scr->win, w, h);
|
||||
|
||||
gc = xcb_generate_id(conn);
|
||||
xcb_create_gc(conn, gc, source, gcmask, val);
|
||||
|
||||
image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_XY_BITMAP,
|
||||
1, NULL, ~0, NULL);
|
||||
image->data = cursor->bits->source;
|
||||
xcb_image_put(conn, source, gc, image, 0, 0, 0);
|
||||
xcb_image_destroy(image);
|
||||
|
||||
image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_XY_BITMAP,
|
||||
1, NULL, ~0, NULL);
|
||||
image->data = cursor->bits->mask;
|
||||
xcb_image_put(conn, mask, gc, image, 0, 0, 0);
|
||||
xcb_image_destroy(image);
|
||||
|
||||
xcb_free_gc(conn, gc);
|
||||
|
||||
hw->cursor = xcb_generate_id(conn);
|
||||
xcb_create_cursor(conn, hw->cursor, source, mask,
|
||||
cursor->foreRed, cursor->foreGreen, cursor->foreBlue,
|
||||
cursor->backRed, cursor->backGreen, cursor->backBlue,
|
||||
cursor->bits->xhot, cursor->bits->yhot);
|
||||
|
||||
xcb_free_pixmap(conn, source);
|
||||
xcb_free_pixmap(conn, mask);
|
||||
}
|
||||
|
||||
static xcb_render_pictformat_t
|
||||
get_argb_format(void)
|
||||
{
|
||||
static xcb_render_pictformat_t format;
|
||||
if (format == None) {
|
||||
xcb_connection_t *conn = hostx_get_xcbconn();
|
||||
xcb_render_query_pict_formats_cookie_t cookie;
|
||||
xcb_render_query_pict_formats_reply_t *formats;
|
||||
|
||||
cookie = xcb_render_query_pict_formats(conn);
|
||||
formats =
|
||||
xcb_render_query_pict_formats_reply(conn, cookie, NULL);
|
||||
|
||||
format =
|
||||
xcb_render_util_find_standard_format(formats,
|
||||
XCB_PICT_STANDARD_ARGB_32)->id;
|
||||
|
||||
free(formats);
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
static void
|
||||
ephyrRealizeARGBCursor(EphyrScrPriv *scr, CursorPtr cursor)
|
||||
{
|
||||
ephyrCursorPtr hw = ephyrGetCursor(cursor);
|
||||
xcb_connection_t *conn = hostx_get_xcbconn();
|
||||
xcb_gcontext_t gc;
|
||||
xcb_pixmap_t source;
|
||||
xcb_render_picture_t picture;
|
||||
xcb_image_t *image;
|
||||
int w = cursor->bits->width, h = cursor->bits->height;
|
||||
|
||||
/* dix' storage is PICT_a8r8g8b8 */
|
||||
source = xcb_generate_id(conn);
|
||||
xcb_create_pixmap(conn, 32, source, scr->win, w, h);
|
||||
|
||||
gc = xcb_generate_id(conn);
|
||||
xcb_create_gc(conn, gc, source, 0, NULL);
|
||||
image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
|
||||
32, NULL, ~0, NULL);
|
||||
image->data = (void *)cursor->bits->argb;
|
||||
xcb_image_put(conn, source, gc, image, 0, 0, 0);
|
||||
xcb_free_gc(conn, gc);
|
||||
xcb_image_destroy(image);
|
||||
|
||||
picture = xcb_generate_id(conn);
|
||||
xcb_render_create_picture(conn, picture, source, get_argb_format(),
|
||||
0, NULL);
|
||||
xcb_free_pixmap(conn, source);
|
||||
|
||||
hw->cursor = xcb_generate_id(conn);
|
||||
xcb_render_create_cursor(conn, hw->cursor, picture,
|
||||
cursor->bits->xhot, cursor->bits->yhot);
|
||||
|
||||
xcb_render_free_picture(conn, picture);
|
||||
}
|
||||
|
||||
static Bool
|
||||
can_argb_cursor(void)
|
||||
{
|
||||
static const xcb_render_query_version_reply_t *v;
|
||||
|
||||
if (!v)
|
||||
v = xcb_render_util_query_version(hostx_get_xcbconn());
|
||||
|
||||
return v->major_version == 0 && v->minor_version >= 5;
|
||||
}
|
||||
|
||||
static Bool
|
||||
ephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor)
|
||||
{
|
||||
KdScreenPriv(screen);
|
||||
KdScreenInfo *kscr = pScreenPriv->screen;
|
||||
EphyrScrPriv *scr = kscr->driver;
|
||||
|
||||
if (cursor->bits->argb && can_argb_cursor())
|
||||
ephyrRealizeARGBCursor(scr, cursor);
|
||||
else
|
||||
{
|
||||
ephyrRealizeCoreCursor(scr, cursor);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
ephyrUnrealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor)
|
||||
{
|
||||
ephyrCursorPtr hw = ephyrGetCursor(cursor);
|
||||
|
||||
if (hw->cursor) {
|
||||
xcb_free_cursor(hostx_get_xcbconn(), hw->cursor);
|
||||
hw->cursor = None;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ephyrSetCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor, int x,
|
||||
int y)
|
||||
{
|
||||
KdScreenPriv(screen);
|
||||
KdScreenInfo *kscr = pScreenPriv->screen;
|
||||
EphyrScrPriv *scr = kscr->driver;
|
||||
uint32_t attr = None;
|
||||
|
||||
if (cursor)
|
||||
attr = ephyrGetCursor(cursor)->cursor;
|
||||
else
|
||||
attr = hostx_get_empty_cursor();
|
||||
|
||||
xcb_change_window_attributes(hostx_get_xcbconn(), scr->win,
|
||||
XCB_CW_CURSOR, &attr);
|
||||
xcb_flush(hostx_get_xcbconn());
|
||||
}
|
||||
|
||||
static void
|
||||
ephyrMoveCursor(DeviceIntPtr dev, ScreenPtr screen, int x, int y)
|
||||
{
|
||||
}
|
||||
|
||||
static Bool
|
||||
ephyrDeviceCursorInitialize(DeviceIntPtr dev, ScreenPtr screen)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
ephyrDeviceCursorCleanup(DeviceIntPtr dev, ScreenPtr screen)
|
||||
{
|
||||
}
|
||||
|
||||
miPointerSpriteFuncRec EphyrPointerSpriteFuncs = {
|
||||
ephyrRealizeCursor,
|
||||
ephyrUnrealizeCursor,
|
||||
ephyrSetCursor,
|
||||
ephyrMoveCursor,
|
||||
ephyrDeviceCursorInitialize,
|
||||
ephyrDeviceCursorCleanup
|
||||
};
|
||||
|
||||
Bool
|
||||
ephyrCursorInit(ScreenPtr screen)
|
||||
{
|
||||
if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR,
|
||||
sizeof(ephyrCursorRec)))
|
||||
return FALSE;
|
||||
|
||||
miPointerInitialize(screen,
|
||||
&EphyrPointerSpriteFuncs,
|
||||
&ephyrPointerScreenFuncs, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1,396 +0,0 @@
|
|||
/*
|
||||
* Xephyr - A kdrive X server that runs in a host X window.
|
||||
* Authored by Matthew Allum <mallum@o-hand.com>
|
||||
*
|
||||
* Copyright © 2004 Nokia
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Nokia not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Nokia makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "ephyr.h"
|
||||
#include "ephyrlog.h"
|
||||
#include "glx_extinit.h"
|
||||
|
||||
extern Window EphyrPreExistingHostWin;
|
||||
extern Bool EphyrWantGrayScale;
|
||||
extern Bool EphyrWantResize;
|
||||
extern Bool EphyrWantNoHostGrab;
|
||||
extern Bool kdHasPointer;
|
||||
extern Bool kdHasKbd;
|
||||
extern Bool ephyr_glamor, ephyr_glamor_gles2, ephyr_glamor_skip_present;
|
||||
|
||||
extern Bool ephyrNoXV;
|
||||
|
||||
void processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id);
|
||||
void processOutputArg(const char *output, char *parent_id);
|
||||
void processScreenArg(const char *screen_size, char *parent_id);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
hostx_use_resname(basename(argv[0]), 0);
|
||||
return dix_main(argc, argv, envp);
|
||||
}
|
||||
|
||||
void
|
||||
InitCard(char *name)
|
||||
{
|
||||
EPHYR_DBG("mark");
|
||||
KdCardInfoAdd(&ephyrFuncs, 0);
|
||||
}
|
||||
|
||||
void
|
||||
InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
|
||||
{
|
||||
KdInitOutput(pScreenInfo, argc, argv);
|
||||
}
|
||||
|
||||
void
|
||||
InitInput(int argc, char **argv)
|
||||
{
|
||||
KdKeyboardInfo *ki;
|
||||
KdPointerInfo *pi;
|
||||
|
||||
KdAddKeyboardDriver(&EphyrKeyboardDriver);
|
||||
KdAddPointerDriver(&EphyrMouseDriver);
|
||||
|
||||
if (!kdHasKbd) {
|
||||
ki = KdNewKeyboard();
|
||||
if (!ki)
|
||||
FatalError("Couldn't create Xephyr keyboard\n");
|
||||
ki->driver = &EphyrKeyboardDriver;
|
||||
KdAddKeyboard(ki);
|
||||
}
|
||||
|
||||
if (!kdHasPointer) {
|
||||
pi = KdNewPointer();
|
||||
if (!pi)
|
||||
FatalError("Couldn't create Xephyr pointer\n");
|
||||
pi->driver = &EphyrMouseDriver;
|
||||
KdAddPointer(pi);
|
||||
}
|
||||
|
||||
KdInitInput();
|
||||
}
|
||||
|
||||
void
|
||||
CloseInput(void)
|
||||
{
|
||||
KdCloseInput();
|
||||
}
|
||||
|
||||
#if INPUTTHREAD
|
||||
/** This function is called in Xserver/os/inputthread.c when starting
|
||||
the input thread. */
|
||||
void
|
||||
ddxInputThreadInit(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DDXBEFORERESET
|
||||
void
|
||||
ddxBeforeReset(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ddxUseMsg(void)
|
||||
{
|
||||
KdUseMsg();
|
||||
|
||||
ErrorF("\nXephyr Option Usage:\n");
|
||||
ErrorF("-parent <XID> Use existing window as Xephyr root win\n");
|
||||
ErrorF("-sw-cursor Render cursors in software in Xephyr\n");
|
||||
ErrorF("-fullscreen Attempt to run Xephyr fullscreen\n");
|
||||
ErrorF("-output <NAME> Attempt to run Xephyr fullscreen (restricted to given output geometry)\n");
|
||||
ErrorF("-grayscale Simulate 8bit grayscale\n");
|
||||
ErrorF("-resizeable Make Xephyr windows resizeable\n");
|
||||
#ifdef GLAMOR
|
||||
ErrorF("-glamor Enable 2D acceleration using glamor\n");
|
||||
ErrorF("-glamor_gles2 Enable 2D acceleration using glamor (with GLES2 only)\n");
|
||||
ErrorF("-glamor-skip-present Skip presenting the output when using glamor (for internal testing optimization)\n");
|
||||
#endif
|
||||
ErrorF
|
||||
("-fakexa Simulate acceleration using software rendering\n");
|
||||
ErrorF("-verbosity <level> Set log verbosity level\n");
|
||||
ErrorF("-noxv do not use XV\n");
|
||||
ErrorF("-name [name] define the name in the WM_CLASS property\n");
|
||||
ErrorF
|
||||
("-title [title] set the window title in the WM_NAME property\n");
|
||||
ErrorF("-no-host-grab Disable grabbing the keyboard and mouse.\n");
|
||||
ErrorF("\n");
|
||||
}
|
||||
|
||||
void
|
||||
processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id)
|
||||
{
|
||||
KdCardInfo *card;
|
||||
|
||||
InitCard(0); /*Put each screen on a separate card */
|
||||
card = KdCardInfoLast();
|
||||
|
||||
if (card) {
|
||||
KdScreenInfo *screen;
|
||||
unsigned long p_id = 0;
|
||||
Bool use_geometry;
|
||||
|
||||
screen = KdScreenInfoAdd(card);
|
||||
KdParseScreen(screen, screen_size);
|
||||
screen->driver = calloc(1, sizeof(EphyrScrPriv));
|
||||
if (!screen->driver)
|
||||
FatalError("Couldn't alloc screen private\n");
|
||||
|
||||
if (parent_id) {
|
||||
p_id = strtol(parent_id, NULL, 0);
|
||||
}
|
||||
|
||||
use_geometry = (strchr(screen_size, '+') != NULL);
|
||||
EPHYR_DBG("screen number:%d\n", screen->mynum);
|
||||
hostx_add_screen(screen, p_id, screen->mynum, use_geometry, output);
|
||||
}
|
||||
else {
|
||||
ErrorF("No matching card found!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
processScreenArg(const char *screen_size, char *parent_id)
|
||||
{
|
||||
processScreenOrOutputArg(screen_size, NULL, parent_id);
|
||||
}
|
||||
|
||||
void
|
||||
processOutputArg(const char *output, char *parent_id)
|
||||
{
|
||||
processScreenOrOutputArg("100x100+0+0", output, parent_id);
|
||||
}
|
||||
|
||||
int
|
||||
ddxProcessArgument(int argc, char **argv, int i)
|
||||
{
|
||||
static char *parent = NULL;
|
||||
|
||||
EPHYR_DBG("mark argv[%d]='%s'", i, argv[i]);
|
||||
|
||||
if (!strcmp(argv[i], "-parent")) {
|
||||
if (i + 1 < argc) {
|
||||
int j;
|
||||
|
||||
/* If parent is specified and a screen argument follows, don't do
|
||||
* anything, let the -screen handling init the rest */
|
||||
for (j = i; j < argc; j++) {
|
||||
if (!strcmp(argv[j], "-screen")) {
|
||||
parent = argv[i + 1];
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
processScreenArg("100x100", argv[i + 1]);
|
||||
return 2;
|
||||
}
|
||||
|
||||
UseMsg();
|
||||
exit(1);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-screen")) {
|
||||
if ((i + 1) < argc) {
|
||||
processScreenArg(argv[i + 1], parent);
|
||||
parent = NULL;
|
||||
return 2;
|
||||
}
|
||||
|
||||
UseMsg();
|
||||
exit(1);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-output")) {
|
||||
if (i + 1 < argc) {
|
||||
processOutputArg(argv[i + 1], NULL);
|
||||
return 2;
|
||||
}
|
||||
|
||||
UseMsg();
|
||||
exit(1);
|
||||
}
|
||||
else if (!strcmp(argv[i], "-sw-cursor")) {
|
||||
hostx_use_sw_cursor();
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-host-cursor")) {
|
||||
/* Compatibility with the old command line argument, now the default. */
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-fullscreen")) {
|
||||
hostx_use_fullscreen();
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-grayscale")) {
|
||||
EphyrWantGrayScale = 1;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-resizeable")) {
|
||||
EphyrWantResize = 1;
|
||||
return 1;
|
||||
}
|
||||
#ifdef GLAMOR
|
||||
else if (!strcmp (argv[i], "-glamor")) {
|
||||
ephyr_glamor = TRUE;
|
||||
ephyrFuncs.initAccel = ephyr_glamor_init;
|
||||
ephyrFuncs.enableAccel = ephyr_glamor_enable;
|
||||
ephyrFuncs.disableAccel = ephyr_glamor_disable;
|
||||
ephyrFuncs.finiAccel = ephyr_glamor_fini;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp (argv[i], "-glamor_gles2")) {
|
||||
ephyr_glamor = TRUE;
|
||||
ephyr_glamor_gles2 = TRUE;
|
||||
ephyrFuncs.initAccel = ephyr_glamor_init;
|
||||
ephyrFuncs.enableAccel = ephyr_glamor_enable;
|
||||
ephyrFuncs.disableAccel = ephyr_glamor_disable;
|
||||
ephyrFuncs.finiAccel = ephyr_glamor_fini;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp (argv[i], "-glamor-skip-present")) {
|
||||
ephyr_glamor_skip_present = TRUE;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(argv[i], "-fakexa")) {
|
||||
ephyrFuncs.initAccel = ephyrDrawInit;
|
||||
ephyrFuncs.enableAccel = ephyrDrawEnable;
|
||||
ephyrFuncs.disableAccel = ephyrDrawDisable;
|
||||
ephyrFuncs.finiAccel = ephyrDrawFini;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-verbosity")) {
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
int verbosity = atoi(argv[i + 1]);
|
||||
|
||||
LogSetParameter(XLOG_VERBOSITY, verbosity);
|
||||
EPHYR_LOG("set verbosiry to %d\n", verbosity);
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
UseMsg();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "-noxv")) {
|
||||
ephyrNoXV = TRUE;
|
||||
EPHYR_LOG("no XVideo enabled\n");
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-name")) {
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
hostx_use_resname(argv[i + 1], 1);
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
UseMsg();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(argv[i], "-title")) {
|
||||
if (i + 1 < argc && argv[i + 1][0] != '-') {
|
||||
hostx_set_title(argv[i + 1]);
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
UseMsg();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (argv[i][0] == ':') {
|
||||
hostx_set_display_name(argv[i]);
|
||||
}
|
||||
/* Xnest compatibility */
|
||||
else if (!strcmp(argv[i], "-display")) {
|
||||
hostx_set_display_name(argv[i + 1]);
|
||||
return 2;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-sync") ||
|
||||
!strcmp(argv[i], "-full") ||
|
||||
!strcmp(argv[i], "-sss") || !strcmp(argv[i], "-install")) {
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-bw") ||
|
||||
!strcmp(argv[i], "-class") ||
|
||||
!strcmp(argv[i], "-geometry") || !strcmp(argv[i], "-scrns")) {
|
||||
return 2;
|
||||
}
|
||||
/* end Xnest compat */
|
||||
else if (!strcmp(argv[i], "-no-host-grab")) {
|
||||
EphyrWantNoHostGrab = 1;
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-sharevts") ||
|
||||
!strcmp(argv[i], "-novtswitch")) {
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-layout")) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return KdProcessArgument(argc, argv, i);
|
||||
}
|
||||
|
||||
void
|
||||
OsVendorInit(void)
|
||||
{
|
||||
EPHYR_DBG("mark");
|
||||
|
||||
if (SeatId)
|
||||
hostx_use_sw_cursor();
|
||||
|
||||
if (hostx_want_host_cursor())
|
||||
ephyrFuncs.initCursor = &ephyrCursorInit;
|
||||
|
||||
if (serverGeneration == 1) {
|
||||
if (!KdCardInfoLast()) {
|
||||
processScreenArg("640x480", NULL);
|
||||
}
|
||||
hostx_init();
|
||||
}
|
||||
}
|
||||
|
||||
KdCardFuncs ephyrFuncs = {
|
||||
ephyrCardInit, /* cardinit */
|
||||
ephyrScreenInitialize, /* scrinit */
|
||||
ephyrInitScreen, /* initScreen */
|
||||
ephyrFinishInitScreen, /* finishInitScreen */
|
||||
ephyrCreateResources, /* createRes */
|
||||
ephyrScreenFini, /* scrfini */
|
||||
ephyrCardFini, /* cardfini */
|
||||
|
||||
0, /* initCursor */
|
||||
|
||||
0, /* initAccel */
|
||||
0, /* enableAccel */
|
||||
0, /* disableAccel */
|
||||
0, /* finiAccel */
|
||||
|
||||
ephyrGetColors, /* getColors */
|
||||
ephyrPutColors, /* putColors */
|
||||
|
||||
ephyrCloseScreen, /* closeScreen */
|
||||
};
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Xephyr - A kdrive X server that runs in a host X window.
|
||||
* Authored by Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright © 2007 OpenedHand Ltd
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of OpenedHand Ltd not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. OpenedHand Ltd makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Dodji Seketeli <dodji@openedhand.com>
|
||||
*/
|
||||
#ifndef __EPHYRLOG_H__
|
||||
#define __EPHYRLOG_H__
|
||||
|
||||
#include <assert.h>
|
||||
#include "os.h"
|
||||
|
||||
#ifndef DEBUG
|
||||
/*we are not in debug mode*/
|
||||
#define EPHYR_LOG(...)
|
||||
#define EPHYR_LOG_ERROR(...)
|
||||
#endif /*!DEBUG */
|
||||
|
||||
#define ERROR_LOG_LEVEL 3
|
||||
#define INFO_LOG_LEVEL 4
|
||||
|
||||
#ifndef EPHYR_LOG
|
||||
#define EPHYR_LOG(...) \
|
||||
LogMessageVerb(X_NOTICE, INFO_LOG_LEVEL, "in %s:%d:%s: ",\
|
||||
__FILE__, __LINE__, __func__) ; \
|
||||
LogMessageVerb(X_NOTICE, INFO_LOG_LEVEL, __VA_ARGS__)
|
||||
#endif /*nomadik_log */
|
||||
|
||||
#ifndef EPHYR_LOG_ERROR
|
||||
#define EPHYR_LOG_ERROR(...) \
|
||||
LogMessageVerb(X_NOTICE, ERROR_LOG_LEVEL, "Error:in %s:%d:%s: ",\
|
||||
__FILE__, __LINE__, __func__) ; \
|
||||
LogMessageVerb(X_NOTICE, ERROR_LOG_LEVEL, __VA_ARGS__)
|
||||
#endif /*EPHYR_LOG_ERROR */
|
||||
|
||||
#ifndef EPHYR_RETURN_IF_FAIL
|
||||
#define EPHYR_RETURN_IF_FAIL(cond) \
|
||||
if (!(cond)) {EPHYR_LOG_ERROR("condition %s failed\n", #cond);return;}
|
||||
#endif /*nomadik_return_if_fail */
|
||||
|
||||
#ifndef EPHYR_RETURN_VAL_IF_FAIL
|
||||
#define EPHYR_RETURN_VAL_IF_FAIL(cond,val) \
|
||||
if (!(cond)) {EPHYR_LOG_ERROR("condition %s failed\n", #cond);return val;}
|
||||
#endif /*nomadik_return_val_if_fail */
|
||||
|
||||
#endif /*__EPHYRLOG_H__*/
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* Xephyr - A kdrive X server that runs in a host X window.
|
||||
* Authored by Matthew Allum <mallum@o-hand.com>
|
||||
*
|
||||
* Copyright © 2004 Nokia
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Nokia not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Nokia makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _XLIBS_STUFF_H_
|
||||
#define _XLIBS_STUFF_H_
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xmd.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/render.h>
|
||||
#include "ephyr.h"
|
||||
|
||||
#define EPHYR_WANT_DEBUG 0
|
||||
|
||||
#if (EPHYR_WANT_DEBUG)
|
||||
#define EPHYR_DBG(x, a...) \
|
||||
fprintf(stderr, __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a)
|
||||
#else
|
||||
#define EPHYR_DBG(x, a...) do {} while (0)
|
||||
#endif
|
||||
|
||||
typedef struct EphyrHostXVars EphyrHostXVars;
|
||||
|
||||
typedef struct {
|
||||
VisualID visualid;
|
||||
int screen;
|
||||
int depth;
|
||||
int class;
|
||||
unsigned long red_mask;
|
||||
unsigned long green_mask;
|
||||
unsigned long blue_mask;
|
||||
int colormap_size;
|
||||
int bits_per_rgb;
|
||||
} EphyrHostVisualInfo;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
int width, height;
|
||||
int visualid;
|
||||
} EphyrHostWindowAttributes;
|
||||
|
||||
typedef struct {
|
||||
int x, y, width, height;
|
||||
} EphyrBox;
|
||||
|
||||
typedef struct {
|
||||
short x1, y1, x2, y2;
|
||||
} EphyrRect;
|
||||
|
||||
int
|
||||
hostx_want_screen_geometry(KdScreenInfo *screen, int *width, int *height, int *x, int *y);
|
||||
|
||||
int
|
||||
hostx_want_host_cursor(void);
|
||||
|
||||
void
|
||||
hostx_use_sw_cursor(void);
|
||||
|
||||
xcb_cursor_t
|
||||
hostx_get_empty_cursor(void);
|
||||
|
||||
void
|
||||
hostx_get_output_geometry(const char *output,
|
||||
int *x, int *y,
|
||||
int *width, int *height);
|
||||
|
||||
void
|
||||
hostx_use_fullscreen(void);
|
||||
|
||||
int
|
||||
hostx_want_fullscreen(void);
|
||||
|
||||
int
|
||||
hostx_want_preexisting_window(KdScreenInfo *screen);
|
||||
|
||||
void
|
||||
hostx_use_preexisting_window(unsigned long win_id);
|
||||
|
||||
void
|
||||
hostx_use_resname(char *name, int fromcmd);
|
||||
|
||||
void
|
||||
hostx_set_title(char *name);
|
||||
|
||||
void
|
||||
hostx_handle_signal(int signum);
|
||||
|
||||
int
|
||||
hostx_init(void);
|
||||
|
||||
void
|
||||
hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry, const char *output);
|
||||
|
||||
void
|
||||
hostx_set_display_name(char *name);
|
||||
|
||||
void
|
||||
hostx_set_screen_number(KdScreenInfo *screen, int number);
|
||||
|
||||
void
|
||||
hostx_set_win_title(KdScreenInfo *screen, const char *extra_text);
|
||||
|
||||
int
|
||||
hostx_get_depth(void);
|
||||
|
||||
int
|
||||
hostx_get_server_depth(KdScreenInfo *screen);
|
||||
|
||||
int
|
||||
hostx_get_bpp(KdScreenInfo *screen);
|
||||
|
||||
void
|
||||
hostx_get_visual_masks(KdScreenInfo *screen,
|
||||
CARD32 *rmsk, CARD32 *gmsk, CARD32 *bmsk);
|
||||
void
|
||||
|
||||
hostx_set_cmap_entry(ScreenPtr pScreen, unsigned char idx,
|
||||
unsigned char r, unsigned char g, unsigned char b);
|
||||
|
||||
void *hostx_screen_init(KdScreenInfo *screen,
|
||||
int x, int y,
|
||||
int width, int height, int buffer_height,
|
||||
int *bytes_per_line, int *bits_per_pixel);
|
||||
|
||||
void
|
||||
hostx_paint_rect(KdScreenInfo *screen,
|
||||
int sx, int sy, int dx, int dy, int width, int height,
|
||||
Bool sync);
|
||||
|
||||
Bool
|
||||
hostx_load_keymap(KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr controls);
|
||||
|
||||
void
|
||||
hostx_size_set_from_configure(Bool);
|
||||
|
||||
xcb_connection_t *
|
||||
hostx_get_xcbconn(void);
|
||||
|
||||
xcb_generic_event_t *
|
||||
hostx_get_event(Bool queued_only);
|
||||
|
||||
Bool
|
||||
hostx_has_queued_event(void);
|
||||
|
||||
int
|
||||
hostx_get_screen(void);
|
||||
|
||||
int
|
||||
hostx_get_window(int a_screen_number);
|
||||
|
||||
int
|
||||
hostx_get_window_attributes(int a_window, EphyrHostWindowAttributes * a_attr);
|
||||
|
||||
int
|
||||
hostx_get_visuals_info(EphyrHostVisualInfo ** a_visuals, int *a_num_entries);
|
||||
|
||||
int hostx_create_window(int a_screen_number,
|
||||
EphyrBox * a_geometry,
|
||||
int a_visual_id, int *a_host_win /*out parameter */ );
|
||||
|
||||
int hostx_destroy_window(int a_win);
|
||||
|
||||
int hostx_set_window_geometry(int a_win, EphyrBox * a_geo);
|
||||
|
||||
int hostx_set_window_bounding_rectangles(int a_window,
|
||||
EphyrRect * a_rects, int a_num_rects);
|
||||
|
||||
int hostx_has_extension(xcb_extension_t *extension);
|
||||
|
||||
int hostx_get_fd(void);
|
||||
|
||||
#endif /*_XLIBS_STUFF_H_*/
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
.\"
|
||||
.\" Copyright (c) Matthieu Herrb <matthieu@herrb.eu>
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, and distribute this software for any
|
||||
.\" purpose with or without fee is hereby granted, provided that the above
|
||||
.\" copyright notice and this permission notice appear in all copies.
|
||||
.\"
|
||||
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.TH Xephyr @appmansuffix@ @vendorversion@
|
||||
.SH NAME
|
||||
Xephyr - X server outputting to a window on a pre-existing X display
|
||||
.SH SYNOPSIS
|
||||
.B Xephyr
|
||||
.RI [\fB:\fP display ]
|
||||
.RI [ option
|
||||
.IR ... ]
|
||||
.SH DESCRIPTION
|
||||
.B Xephyr
|
||||
is a kdrive server that outputs to a window on a pre-existing "host"
|
||||
X display.
|
||||
Think
|
||||
.I Xnest
|
||||
but with support for modern extensions like composite, damage and randr.
|
||||
.PP
|
||||
Unlike
|
||||
.I Xnest
|
||||
which is an X proxy, i.e. limited to the capabilities of the host X server,
|
||||
.B Xephyr
|
||||
is a real X server which
|
||||
uses the host X server window as "framebuffer" via fast SHM XImages.
|
||||
.PP
|
||||
It also has support for "visually" debugging what the server is
|
||||
painting.
|
||||
.SH OPTIONS
|
||||
The server accepts all the standard options of Xserver(@appmansuffix@)
|
||||
and the following additional options:
|
||||
.TP 8
|
||||
.BI -screen " width" x height
|
||||
sets the screen size.
|
||||
.TP 8
|
||||
.BI -parent " id"
|
||||
uses existing window
|
||||
.I id .
|
||||
If a
|
||||
.BI -screen
|
||||
argument follows a
|
||||
.BI -parent
|
||||
argument, this screen is embedded into the given window.
|
||||
.TP 8
|
||||
.B -host-cursor
|
||||
set 'cursor acceleration':
|
||||
The host's cursor is reused. This is only really there to aid
|
||||
debugging by avoiding server paints for the cursor. Performance
|
||||
improvement is negligible.
|
||||
.TP 8
|
||||
.B -resizeable
|
||||
Allow the Xephyr window to be resized, even if not embedded into a parent
|
||||
window. By default, the Xephyr window has a fixed size.
|
||||
.TP 8
|
||||
.B -no-host-grab
|
||||
Disable grabbing the keyboard and mouse.
|
||||
.SH "SIGNALS"
|
||||
Send a SIGUSR1 to the server (e.g. pkill -USR1 Xephyr) to
|
||||
toggle the debugging mode.
|
||||
In this mode red rectangles are painted to
|
||||
screen areas getting painted before painting the actual content.
|
||||
The
|
||||
delay between this can be altered by setting a XEPHYR_PAUSE env var to
|
||||
a value in micro seconds.
|
||||
.SH CAVEATS
|
||||
.PP
|
||||
.IP \(bu 2
|
||||
Rotated displays are currently updated via full blits. This
|
||||
is slower than a normal orientated display. Debug mode will
|
||||
therefore not be of much use rotated.
|
||||
.IP \(bu 2
|
||||
The '-host-cursor' cursor is static in its appearance.
|
||||
.IP \(bu 2
|
||||
The build gets a warning about 'nanosleep'. I think the various '-D'
|
||||
build flags are causing this. I haven't figured as yet how to work
|
||||
round it. It doesn't appear to break anything however.
|
||||
.IP \(bu 2
|
||||
Keyboard handling is basic but works.
|
||||
.IP \(bu 2
|
||||
Mouse button 5 probably won't work.
|
||||
.SH "SEE ALSO"
|
||||
X(@miscmansuffix@), Xserver(@appmansuffix@)
|
||||
.SH AUTHOR
|
||||
Matthew Allum <mallum@o-hand.com> 2004
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
srcs = [
|
||||
'ephyr.c',
|
||||
'ephyrinit.c',
|
||||
'ephyrcursor.c',
|
||||
'ephyr_draw.c',
|
||||
'hostx.c',
|
||||
]
|
||||
|
||||
xephyr_dep = [
|
||||
common_dep,
|
||||
dependency('xcb'),
|
||||
dependency('xcb-shape'),
|
||||
dependency('xcb-render'),
|
||||
dependency('xcb-renderutil'),
|
||||
dependency('xcb-aux'),
|
||||
dependency('xcb-image'),
|
||||
dependency('xcb-icccm'),
|
||||
dependency('xcb-shm', version : '>=1.9.3'),
|
||||
dependency('xcb-keysyms'),
|
||||
dependency('xcb-randr'),
|
||||
dependency('xcb-xkb'),
|
||||
]
|
||||
|
||||
xephyr_glamor = []
|
||||
if build_glamor
|
||||
srcs += 'ephyr_glamor.c'
|
||||
if build_xv
|
||||
srcs += 'ephyr_glamor_xv.c'
|
||||
endif
|
||||
xephyr_glamor += glamor
|
||||
xephyr_dep += epoxy_dep
|
||||
xephyr_dep += dependency('xcb-glx')
|
||||
endif
|
||||
|
||||
if build_xv
|
||||
srcs += 'ephyrvideo.c'
|
||||
xephyr_dep += dependency('xcb-xv')
|
||||
endif
|
||||
|
||||
xephyr_server = executable(
|
||||
'Xephyr',
|
||||
srcs,
|
||||
include_directories: [
|
||||
inc,
|
||||
include_directories('../src')
|
||||
],
|
||||
dependencies: xephyr_dep,
|
||||
link_with: [
|
||||
libxserver_main,
|
||||
libxserver_exa,
|
||||
xephyr_glamor,
|
||||
kdrive,
|
||||
libxserver_fb,
|
||||
libxserver,
|
||||
libxserver_config,
|
||||
libxserver_xkb_stubs,
|
||||
libxserver_xi_stubs,
|
||||
libxserver_glx,
|
||||
libglxvnd,
|
||||
],
|
||||
install: true,
|
||||
)
|
||||
|
||||
xephyr_man = configure_file(
|
||||
input: 'man/Xephyr.man',
|
||||
output: 'Xephyr.1',
|
||||
configuration: manpage_config,
|
||||
)
|
||||
install_man(xephyr_man)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
subdir('src')
|
||||
subdir('ephyr')
|
||||
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "kdrive.h"
|
||||
|
||||
/*
|
||||
* Put the entire colormap into the DAC
|
||||
*/
|
||||
|
||||
static void
|
||||
KdSetColormap(ScreenPtr pScreen)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
ColormapPtr pCmap = pScreenPriv->pInstalledmap;
|
||||
Pixel pixels[KD_MAX_PSEUDO_SIZE];
|
||||
xrgb colors[KD_MAX_PSEUDO_SIZE];
|
||||
xColorItem defs[KD_MAX_PSEUDO_SIZE];
|
||||
int i;
|
||||
|
||||
if (!pScreenPriv->card->cfuncs->putColors)
|
||||
return;
|
||||
if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
|
||||
return;
|
||||
|
||||
if (!pScreenPriv->enabled)
|
||||
return;
|
||||
|
||||
if (!pCmap)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Make DIX convert pixels into RGB values -- this handles
|
||||
* true/direct as well as pseudo/static visuals
|
||||
*/
|
||||
|
||||
for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
|
||||
pixels[i] = i;
|
||||
|
||||
QueryColors(pCmap, (1 << pScreenPriv->screen->fb.depth), pixels, colors,
|
||||
serverClient);
|
||||
|
||||
for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++) {
|
||||
defs[i].pixel = i;
|
||||
defs[i].red = colors[i].red;
|
||||
defs[i].green = colors[i].green;
|
||||
defs[i].blue = colors[i].blue;
|
||||
defs[i].flags = DoRed | DoGreen | DoBlue;
|
||||
}
|
||||
|
||||
(*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen,
|
||||
(1 << pScreenPriv->screen->fb.
|
||||
depth), defs);
|
||||
}
|
||||
|
||||
/*
|
||||
* When the hardware is enabled, save the hardware colors and store
|
||||
* the current colormap
|
||||
*/
|
||||
void
|
||||
KdEnableColormap(ScreenPtr pScreen)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
int i;
|
||||
|
||||
if (!pScreenPriv->card->cfuncs->putColors)
|
||||
return;
|
||||
|
||||
if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) {
|
||||
for (i = 0; i < (1 << pScreenPriv->screen->fb.depth); i++)
|
||||
pScreenPriv->systemPalette[i].pixel = i;
|
||||
(*pScreenPriv->card->cfuncs->getColors) (pScreen,
|
||||
(1 << pScreenPriv->screen->fb.
|
||||
depth),
|
||||
pScreenPriv->systemPalette);
|
||||
}
|
||||
KdSetColormap(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
KdDisableColormap(ScreenPtr pScreen)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
|
||||
if (!pScreenPriv->card->cfuncs->putColors)
|
||||
return;
|
||||
|
||||
if (pScreenPriv->screen->fb.depth <= KD_MAX_PSEUDO_DEPTH) {
|
||||
(*pScreenPriv->card->cfuncs->putColors) (pScreen,
|
||||
(1 << pScreenPriv->screen->fb.
|
||||
depth),
|
||||
pScreenPriv->systemPalette);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* KdInstallColormap
|
||||
*
|
||||
* This function is called when the server receives a request to install a
|
||||
* colormap or when the server needs to install one on its own, like when
|
||||
* there's no window manager running and the user has moved the pointer over
|
||||
* an X client window. It needs to build an identity Windows palette for the
|
||||
* colormap and realize it into the Windows system palette.
|
||||
*/
|
||||
void
|
||||
KdInstallColormap(ColormapPtr pCmap)
|
||||
{
|
||||
KdScreenPriv(pCmap->pScreen);
|
||||
|
||||
if (pCmap == pScreenPriv->pInstalledmap)
|
||||
return;
|
||||
|
||||
/* Tell X clients that the installed colormap is going away. */
|
||||
if (pScreenPriv->pInstalledmap)
|
||||
WalkTree(pScreenPriv->pInstalledmap->pScreen, TellLostMap,
|
||||
(void *) &(pScreenPriv->pInstalledmap->mid));
|
||||
|
||||
/* Take note of the new installed colorscreen-> */
|
||||
pScreenPriv->pInstalledmap = pCmap;
|
||||
|
||||
KdSetColormap(pCmap->pScreen);
|
||||
|
||||
/* Tell X clients of the new colormap */
|
||||
WalkTree(pCmap->pScreen, TellGainedMap, (void *) &(pCmap->mid));
|
||||
}
|
||||
|
||||
/*
|
||||
* KdUninstallColormap
|
||||
*
|
||||
* This function uninstalls a colormap by either installing
|
||||
* the default X colormap or erasing the installed colormap pointer.
|
||||
* The default X colormap itself cannot be uninstalled.
|
||||
*/
|
||||
void
|
||||
KdUninstallColormap(ColormapPtr pCmap)
|
||||
{
|
||||
KdScreenPriv(pCmap->pScreen);
|
||||
Colormap defMapID;
|
||||
ColormapPtr defMap;
|
||||
|
||||
/* ignore if not installed */
|
||||
if (pCmap != pScreenPriv->pInstalledmap)
|
||||
return;
|
||||
|
||||
/* ignore attempts to uninstall default colormap */
|
||||
defMapID = pCmap->pScreen->defColormap;
|
||||
if ((Colormap) pCmap->mid == defMapID)
|
||||
return;
|
||||
|
||||
/* install default */
|
||||
dixLookupResourceByType((void **) &defMap, defMapID, RT_COLORMAP,
|
||||
serverClient, DixInstallAccess);
|
||||
if (defMap)
|
||||
(*pCmap->pScreen->InstallColormap) (defMap);
|
||||
else {
|
||||
/* uninstall and clear colormap pointer */
|
||||
WalkTree(pCmap->pScreen, TellLostMap, (void *) &(pCmap->mid));
|
||||
pScreenPriv->pInstalledmap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
KdListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmaps)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
int n = 0;
|
||||
|
||||
if (pScreenPriv->pInstalledmap) {
|
||||
*pCmaps++ = pScreenPriv->pInstalledmap->mid;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* KdStoreColors
|
||||
*
|
||||
* This function is called whenever the server receives a request to store
|
||||
* color values into one or more entries in the currently installed X
|
||||
* colormap; it can be either the default colormap or a private colorscreen->
|
||||
*/
|
||||
void
|
||||
KdStoreColors(ColormapPtr pCmap, int ndef, xColorItem * pdefs)
|
||||
{
|
||||
KdScreenPriv(pCmap->pScreen);
|
||||
VisualPtr pVisual;
|
||||
xColorItem expanddefs[KD_MAX_PSEUDO_SIZE];
|
||||
|
||||
if (pCmap != pScreenPriv->pInstalledmap)
|
||||
return;
|
||||
|
||||
if (!pScreenPriv->card->cfuncs->putColors)
|
||||
return;
|
||||
|
||||
if (pScreenPriv->screen->fb.depth > KD_MAX_PSEUDO_DEPTH)
|
||||
return;
|
||||
|
||||
if (!pScreenPriv->enabled)
|
||||
return;
|
||||
|
||||
/* Check for DirectColor or TrueColor being simulated on a PseudoColor device. */
|
||||
pVisual = pCmap->pVisual;
|
||||
if ((pVisual->class | DynamicClass) == DirectColor) {
|
||||
/*
|
||||
* Expand DirectColor or TrueColor color values into a PseudoColor
|
||||
* format. Defer to the Color Framebuffer (CFB) code to do that.
|
||||
*/
|
||||
ndef = fbExpandDirectColors(pCmap, ndef, pdefs, expanddefs);
|
||||
pdefs = expanddefs;
|
||||
}
|
||||
|
||||
(*pScreenPriv->card->cfuncs->putColors) (pCmap->pScreen, ndef, pdefs);
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,438 +0,0 @@
|
|||
/*
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _KDRIVE_H_
|
||||
#define _KDRIVE_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xos.h>
|
||||
#include "scrnintstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "servermd.h"
|
||||
#include "colormapst.h"
|
||||
#include "gcstruct.h"
|
||||
#include "input.h"
|
||||
#include "mipointer.h"
|
||||
#include "mi.h"
|
||||
#include "dix.h"
|
||||
#include "fb.h"
|
||||
#include "fboverlay.h"
|
||||
#include "shadow.h"
|
||||
#include "randrstr.h"
|
||||
#include "globals.h"
|
||||
|
||||
#include "xkbstr.h"
|
||||
|
||||
#define KD_DPMS_NORMAL 0
|
||||
#define KD_DPMS_STANDBY 1
|
||||
#define KD_DPMS_SUSPEND 2
|
||||
#define KD_DPMS_POWERDOWN 3
|
||||
#define KD_DPMS_MAX KD_DPMS_POWERDOWN
|
||||
|
||||
#define Status int
|
||||
|
||||
typedef struct _KdCardInfo {
|
||||
struct _KdCardFuncs *cfuncs;
|
||||
void *closure;
|
||||
void *driver;
|
||||
struct _KdScreenInfo *screenList;
|
||||
int selected;
|
||||
struct _KdCardInfo *next;
|
||||
} KdCardInfo;
|
||||
|
||||
extern KdCardInfo *kdCardInfo;
|
||||
|
||||
/*
|
||||
* Configuration information per X screen
|
||||
*/
|
||||
typedef struct _KdFrameBuffer {
|
||||
CARD8 *frameBuffer;
|
||||
int depth;
|
||||
int bitsPerPixel;
|
||||
int pixelStride;
|
||||
int byteStride;
|
||||
Bool shadow;
|
||||
unsigned long visuals;
|
||||
Pixel redMask, greenMask, blueMask;
|
||||
void *closure;
|
||||
} KdFrameBuffer;
|
||||
|
||||
#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270)
|
||||
#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y)
|
||||
|
||||
typedef struct _KdScreenInfo {
|
||||
struct _KdScreenInfo *next;
|
||||
KdCardInfo *card;
|
||||
ScreenPtr pScreen;
|
||||
void *driver;
|
||||
Rotation randr; /* rotation and reflection */
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int rate;
|
||||
int width_mm;
|
||||
int height_mm;
|
||||
int subpixel_order;
|
||||
Bool dumb;
|
||||
Bool softCursor;
|
||||
int mynum;
|
||||
DDXPointRec origin;
|
||||
KdFrameBuffer fb;
|
||||
} KdScreenInfo;
|
||||
|
||||
typedef struct _KdCardFuncs {
|
||||
Bool (*cardinit) (KdCardInfo *); /* detect and map device */
|
||||
Bool (*scrinit) (KdScreenInfo *); /* initialize screen information */
|
||||
Bool (*initScreen) (ScreenPtr); /* initialize ScreenRec */
|
||||
Bool (*finishInitScreen) (ScreenPtr pScreen);
|
||||
Bool (*createRes) (ScreenPtr); /* create screen resources */
|
||||
void (*scrfini) (KdScreenInfo *); /* close down screen */
|
||||
void (*cardfini) (KdCardInfo *); /* close down */
|
||||
|
||||
Bool (*initCursor) (ScreenPtr); /* detect and map cursor */
|
||||
|
||||
Bool (*initAccel) (ScreenPtr);
|
||||
void (*enableAccel) (ScreenPtr);
|
||||
void (*disableAccel) (ScreenPtr);
|
||||
void (*finiAccel) (ScreenPtr);
|
||||
|
||||
void (*getColors) (ScreenPtr, int, xColorItem *);
|
||||
void (*putColors) (ScreenPtr, int, xColorItem *);
|
||||
|
||||
void (*closeScreen) (ScreenPtr); /* close ScreenRec */
|
||||
} KdCardFuncs;
|
||||
|
||||
#define KD_MAX_PSEUDO_DEPTH 8
|
||||
#define KD_MAX_PSEUDO_SIZE (1 << KD_MAX_PSEUDO_DEPTH)
|
||||
|
||||
typedef struct {
|
||||
KdScreenInfo *screen;
|
||||
KdCardInfo *card;
|
||||
|
||||
Bool enabled;
|
||||
Bool closed;
|
||||
int bytesPerPixel;
|
||||
|
||||
int dpmsState;
|
||||
|
||||
ColormapPtr pInstalledmap; /* current colormap */
|
||||
xColorItem systemPalette[KD_MAX_PSEUDO_SIZE]; /* saved windows colors */
|
||||
|
||||
CreateScreenResourcesProcPtr CreateScreenResources;
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
} KdPrivScreenRec, *KdPrivScreenPtr;
|
||||
|
||||
typedef enum _kdPointerState {
|
||||
start,
|
||||
button_1_pend,
|
||||
button_1_down,
|
||||
button_2_down,
|
||||
button_3_pend,
|
||||
button_3_down,
|
||||
synth_2_down_13,
|
||||
synth_2_down_3,
|
||||
synth_2_down_1,
|
||||
num_input_states
|
||||
} KdPointerState;
|
||||
|
||||
#define KD_MAX_BUTTON 32
|
||||
|
||||
#define KD_KEYBOARD 1
|
||||
#define KD_MOUSE 2
|
||||
#define KD_TOUCHSCREEN 3
|
||||
|
||||
typedef struct _KdPointerInfo KdPointerInfo;
|
||||
|
||||
typedef struct _KdPointerDriver {
|
||||
const char *name;
|
||||
Status(*Init) (KdPointerInfo *);
|
||||
Status(*Enable) (KdPointerInfo *);
|
||||
void (*Disable) (KdPointerInfo *);
|
||||
void (*Fini) (KdPointerInfo *);
|
||||
struct _KdPointerDriver *next;
|
||||
} KdPointerDriver;
|
||||
|
||||
struct _KdPointerInfo {
|
||||
DeviceIntPtr dixdev;
|
||||
char *name;
|
||||
char *path;
|
||||
char *protocol;
|
||||
InputOption *options;
|
||||
int inputClass;
|
||||
|
||||
CARD8 map[KD_MAX_BUTTON + 1];
|
||||
int nButtons;
|
||||
int nAxes;
|
||||
|
||||
Bool emulateMiddleButton;
|
||||
unsigned long emulationTimeout;
|
||||
int emulationDx, emulationDy;
|
||||
|
||||
Bool timeoutPending;
|
||||
KdPointerState mouseState;
|
||||
Bool eventHeld;
|
||||
struct {
|
||||
int type;
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int flags;
|
||||
int absrel;
|
||||
} heldEvent;
|
||||
unsigned char buttonState;
|
||||
Bool transformCoordinates;
|
||||
int pressureThreshold;
|
||||
|
||||
KdPointerDriver *driver;
|
||||
void *driverPrivate;
|
||||
|
||||
struct _KdPointerInfo *next;
|
||||
};
|
||||
|
||||
void KdAddPointerDriver(KdPointerDriver * driver);
|
||||
void KdRemovePointerDriver(KdPointerDriver * driver);
|
||||
KdPointerInfo *KdNewPointer(void);
|
||||
void KdFreePointer(KdPointerInfo *);
|
||||
int KdAddPointer(KdPointerInfo * ki);
|
||||
int KdAddConfigPointer(char *pointer);
|
||||
void KdRemovePointer(KdPointerInfo * ki);
|
||||
|
||||
#define KD_KEY_COUNT 248
|
||||
#define KD_MIN_KEYCODE 8
|
||||
#define KD_MAX_KEYCODE 255
|
||||
#define KD_MAX_WIDTH 4
|
||||
#define KD_MAX_LENGTH (KD_MAX_KEYCODE - KD_MIN_KEYCODE + 1)
|
||||
|
||||
typedef struct {
|
||||
KeySym modsym;
|
||||
int modbit;
|
||||
} KdKeySymModsRec;
|
||||
|
||||
typedef struct _KdKeyboardInfo KdKeyboardInfo;
|
||||
|
||||
typedef struct _KdKeyboardDriver {
|
||||
const char *name;
|
||||
Bool (*Init) (KdKeyboardInfo *);
|
||||
Bool (*Enable) (KdKeyboardInfo *);
|
||||
void (*Leds) (KdKeyboardInfo *, int);
|
||||
void (*Bell) (KdKeyboardInfo *, int, int, int);
|
||||
void (*Disable) (KdKeyboardInfo *);
|
||||
void (*Fini) (KdKeyboardInfo *);
|
||||
struct _KdKeyboardDriver *next;
|
||||
} KdKeyboardDriver;
|
||||
|
||||
struct _KdKeyboardInfo {
|
||||
struct _KdKeyboardInfo *next;
|
||||
DeviceIntPtr dixdev;
|
||||
void *closure;
|
||||
char *name;
|
||||
char *path;
|
||||
int inputClass;
|
||||
char *xkbRules;
|
||||
char *xkbModel;
|
||||
char *xkbLayout;
|
||||
char *xkbVariant;
|
||||
char *xkbOptions;
|
||||
int LockLed;
|
||||
|
||||
int minScanCode;
|
||||
int maxScanCode;
|
||||
|
||||
int leds;
|
||||
int bellPitch;
|
||||
int bellDuration;
|
||||
InputOption *options;
|
||||
|
||||
KdKeyboardDriver *driver;
|
||||
void *driverPrivate;
|
||||
};
|
||||
|
||||
void KdAddKeyboardDriver(KdKeyboardDriver * driver);
|
||||
void KdRemoveKeyboardDriver(KdKeyboardDriver * driver);
|
||||
KdKeyboardInfo *KdNewKeyboard(void);
|
||||
void KdFreeKeyboard(KdKeyboardInfo * ki);
|
||||
int KdAddConfigKeyboard(char *pointer);
|
||||
int KdAddKeyboard(KdKeyboardInfo * ki);
|
||||
void KdRemoveKeyboard(KdKeyboardInfo * ki);
|
||||
|
||||
typedef struct _KdPointerMatrix {
|
||||
int matrix[2][3];
|
||||
} KdPointerMatrix;
|
||||
|
||||
extern DevPrivateKeyRec kdScreenPrivateKeyRec;
|
||||
|
||||
#define kdScreenPrivateKey (&kdScreenPrivateKeyRec)
|
||||
|
||||
extern Bool kdEmulateMiddleButton;
|
||||
extern Bool kdDisableZaphod;
|
||||
|
||||
#define KdGetScreenPriv(pScreen) ((KdPrivScreenPtr) \
|
||||
dixLookupPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey))
|
||||
#define KdSetScreenPriv(pScreen,v) \
|
||||
dixSetPrivate(&(pScreen)->devPrivates, kdScreenPrivateKey, v)
|
||||
#define KdScreenPriv(pScreen) KdPrivScreenPtr pScreenPriv = KdGetScreenPriv(pScreen)
|
||||
|
||||
/* kcmap.c */
|
||||
void
|
||||
KdEnableColormap(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
KdDisableColormap(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
KdInstallColormap(ColormapPtr pCmap);
|
||||
|
||||
void
|
||||
KdUninstallColormap(ColormapPtr pCmap);
|
||||
|
||||
int
|
||||
KdListInstalledColormaps(ScreenPtr pScreen, Colormap * pCmaps);
|
||||
|
||||
void
|
||||
KdStoreColors(ColormapPtr pCmap, int ndef, xColorItem * pdefs);
|
||||
|
||||
/* kdrive.c */
|
||||
extern miPointerScreenFuncRec kdPointerScreenFuncs;
|
||||
|
||||
void
|
||||
KdDisableScreen(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
KdEnableScreen(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
KdEnableScreens(void);
|
||||
|
||||
void
|
||||
KdProcessSwitch(void);
|
||||
|
||||
Rotation KdAddRotation(Rotation a, Rotation b);
|
||||
|
||||
Rotation KdSubRotation(Rotation a, Rotation b);
|
||||
|
||||
void
|
||||
KdParseScreen(KdScreenInfo * screen, const char *arg);
|
||||
|
||||
const char *
|
||||
KdParseFindNext(const char *cur, const char *delim, char *save, char *last);
|
||||
|
||||
void
|
||||
KdUseMsg(void);
|
||||
|
||||
int
|
||||
KdProcessArgument(int argc, char **argv, int i);
|
||||
|
||||
void
|
||||
KdOsAddInputDrivers(void);
|
||||
|
||||
void
|
||||
KdInitCard(ScreenInfo * pScreenInfo, KdCardInfo * card, int argc, char **argv);
|
||||
|
||||
void
|
||||
KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv);
|
||||
|
||||
void
|
||||
KdSetSubpixelOrder(ScreenPtr pScreen, Rotation randr);
|
||||
|
||||
void
|
||||
KdBacktrace(int signum);
|
||||
|
||||
/* kinfo.c */
|
||||
KdCardInfo *KdCardInfoAdd(KdCardFuncs * funcs, void *closure);
|
||||
|
||||
KdCardInfo *KdCardInfoLast(void);
|
||||
|
||||
void
|
||||
KdCardInfoDispose(KdCardInfo * ci);
|
||||
|
||||
KdScreenInfo *KdScreenInfoAdd(KdCardInfo * ci);
|
||||
|
||||
void
|
||||
KdScreenInfoDispose(KdScreenInfo * si);
|
||||
|
||||
/* kinput.c */
|
||||
void
|
||||
KdInitInput(void);
|
||||
void
|
||||
KdCloseInput(void);
|
||||
|
||||
void
|
||||
KdEnqueueKeyboardEvent(KdKeyboardInfo * ki, unsigned char scan_code,
|
||||
unsigned char is_up);
|
||||
|
||||
#define KD_BUTTON_1 0x01
|
||||
#define KD_BUTTON_2 0x02
|
||||
#define KD_BUTTON_3 0x04
|
||||
#define KD_BUTTON_4 0x08
|
||||
#define KD_BUTTON_5 0x10
|
||||
#define KD_BUTTON_8 0x80
|
||||
#define KD_POINTER_DESKTOP 0x40000000
|
||||
#define KD_MOUSE_DELTA 0x80000000
|
||||
|
||||
void
|
||||
KdEnqueuePointerEvent(KdPointerInfo * pi, unsigned long flags, int rx, int ry,
|
||||
int rz);
|
||||
|
||||
void
|
||||
KdSetPointerMatrix(KdPointerMatrix *pointer);
|
||||
|
||||
void
|
||||
KdComputePointerMatrix(KdPointerMatrix *pointer, Rotation randr, int width,
|
||||
int height);
|
||||
|
||||
void
|
||||
KdBlockHandler(ScreenPtr pScreen, void *timeout);
|
||||
|
||||
void
|
||||
KdWakeupHandler(ScreenPtr pScreen, int result);
|
||||
|
||||
void
|
||||
KdDisableInput(void);
|
||||
|
||||
void
|
||||
KdEnableInput(void);
|
||||
|
||||
/* kshadow.c */
|
||||
Bool
|
||||
KdShadowFbAlloc(KdScreenInfo * screen, Bool rotate);
|
||||
|
||||
void
|
||||
KdShadowFbFree(KdScreenInfo * screen);
|
||||
|
||||
Bool
|
||||
|
||||
KdShadowSet(ScreenPtr pScreen, int randr, ShadowUpdateProc update,
|
||||
ShadowWindowProc window);
|
||||
|
||||
void
|
||||
KdShadowUnset(ScreenPtr pScreen);
|
||||
|
||||
/* function prototypes to be implemented by the drivers */
|
||||
void
|
||||
InitCard(char *name);
|
||||
|
||||
#endif /* _KDRIVE_H_ */
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
/*
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "kdrive.h"
|
||||
|
||||
KdCardInfo *kdCardInfo;
|
||||
|
||||
KdCardInfo *
|
||||
KdCardInfoAdd(KdCardFuncs * funcs, void *closure)
|
||||
{
|
||||
KdCardInfo *ci, **prev;
|
||||
|
||||
ci = calloc(1, sizeof(KdCardInfo));
|
||||
if (!ci)
|
||||
return 0;
|
||||
for (prev = &kdCardInfo; *prev; prev = &(*prev)->next);
|
||||
*prev = ci;
|
||||
ci->cfuncs = funcs;
|
||||
ci->closure = closure;
|
||||
ci->screenList = 0;
|
||||
ci->selected = 0;
|
||||
ci->next = 0;
|
||||
return ci;
|
||||
}
|
||||
|
||||
KdCardInfo *
|
||||
KdCardInfoLast(void)
|
||||
{
|
||||
KdCardInfo *ci;
|
||||
|
||||
if (!kdCardInfo)
|
||||
return 0;
|
||||
for (ci = kdCardInfo; ci->next; ci = ci->next);
|
||||
return ci;
|
||||
}
|
||||
|
||||
void
|
||||
KdCardInfoDispose(KdCardInfo * ci)
|
||||
{
|
||||
KdCardInfo **prev;
|
||||
|
||||
for (prev = &kdCardInfo; *prev; prev = &(*prev)->next)
|
||||
if (*prev == ci) {
|
||||
*prev = ci->next;
|
||||
free(ci);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
KdScreenInfo *
|
||||
KdScreenInfoAdd(KdCardInfo * ci)
|
||||
{
|
||||
KdScreenInfo *si, **prev;
|
||||
int n;
|
||||
|
||||
si = calloc(1, sizeof(KdScreenInfo));
|
||||
if (!si)
|
||||
return 0;
|
||||
for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++);
|
||||
*prev = si;
|
||||
si->next = 0;
|
||||
si->card = ci;
|
||||
si->mynum = n;
|
||||
return si;
|
||||
}
|
||||
|
||||
void
|
||||
KdScreenInfoDispose(KdScreenInfo * si)
|
||||
{
|
||||
KdCardInfo *ci = si->card;
|
||||
KdScreenInfo **prev;
|
||||
|
||||
for (prev = &ci->screenList; *prev; prev = &(*prev)->next) {
|
||||
if (*prev == si) {
|
||||
*prev = si->next;
|
||||
free(si);
|
||||
if (!ci->screenList)
|
||||
KdCardInfoDispose(ci);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KdPointerInfo *
|
||||
KdNewPointer(void)
|
||||
{
|
||||
KdPointerInfo *pi;
|
||||
int i;
|
||||
|
||||
pi = (KdPointerInfo *) calloc(1, sizeof(KdPointerInfo));
|
||||
if (!pi)
|
||||
return NULL;
|
||||
|
||||
pi->name = strdup("Generic Pointer");
|
||||
pi->path = NULL;
|
||||
pi->inputClass = KD_MOUSE;
|
||||
pi->driver = NULL;
|
||||
pi->driverPrivate = NULL;
|
||||
pi->next = NULL;
|
||||
pi->options = NULL;
|
||||
pi->nAxes = 3;
|
||||
pi->nButtons = KD_MAX_BUTTON;
|
||||
for (i = 1; i < KD_MAX_BUTTON; i++)
|
||||
pi->map[i] = i;
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
void
|
||||
KdFreePointer(KdPointerInfo * pi)
|
||||
{
|
||||
free(pi->name);
|
||||
free(pi->path);
|
||||
input_option_free_list(&pi->options);
|
||||
pi->next = NULL;
|
||||
free(pi);
|
||||
}
|
||||
|
||||
void
|
||||
KdFreeKeyboard(KdKeyboardInfo * ki)
|
||||
{
|
||||
free(ki->name);
|
||||
free(ki->path);
|
||||
free(ki->xkbRules);
|
||||
free(ki->xkbModel);
|
||||
free(ki->xkbLayout);
|
||||
free(ki->xkbVariant);
|
||||
free(ki->xkbOptions);
|
||||
input_option_free_list(&ki->options);
|
||||
ki->next = NULL;
|
||||
free(ki);
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "kdrive.h"
|
||||
|
||||
Bool
|
||||
KdShadowFbAlloc(KdScreenInfo * screen, Bool rotate)
|
||||
{
|
||||
int paddedWidth;
|
||||
void *buf;
|
||||
int width = rotate ? screen->height : screen->width;
|
||||
int height = rotate ? screen->width : screen->height;
|
||||
int bpp = screen->fb.bitsPerPixel;
|
||||
|
||||
/* use fb computation for width */
|
||||
paddedWidth = ((width * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
|
||||
buf = xallocarray(paddedWidth, height);
|
||||
if (!buf)
|
||||
return FALSE;
|
||||
if (screen->fb.shadow)
|
||||
free(screen->fb.frameBuffer);
|
||||
screen->fb.shadow = TRUE;
|
||||
screen->fb.frameBuffer = buf;
|
||||
screen->fb.byteStride = paddedWidth;
|
||||
screen->fb.pixelStride = paddedWidth * 8 / bpp;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
KdShadowFbFree(KdScreenInfo * screen)
|
||||
{
|
||||
if (screen->fb.shadow) {
|
||||
free(screen->fb.frameBuffer);
|
||||
screen->fb.frameBuffer = 0;
|
||||
screen->fb.shadow = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
KdShadowSet(ScreenPtr pScreen, int randr, ShadowUpdateProc update,
|
||||
ShadowWindowProc window)
|
||||
{
|
||||
KdScreenPriv(pScreen);
|
||||
KdScreenInfo *screen = pScreenPriv->screen;
|
||||
|
||||
shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
|
||||
if (screen->fb.shadow) {
|
||||
return shadowAdd(pScreen, pScreen->GetScreenPixmap(pScreen),
|
||||
update, window, randr, 0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
KdShadowUnset(ScreenPtr pScreen)
|
||||
{
|
||||
shadowRemove(pScreen, pScreen->GetScreenPixmap(pScreen));
|
||||
}
|
||||
1373
hw/kdrive/src/kxv.c
1373
hw/kdrive/src/kxv.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
|
||||
XFree86 Xv DDX written by Mark Vojkovich (markv@valinux.com)
|
||||
Adapted for KDrive by Pontus Lidman <pontus.lidman@nokia.com>
|
||||
|
||||
Copyright (C) 2000, 2001 - Nokia Home Communications
|
||||
Copyright (C) 1998, 1999 - The XFree86 Project Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
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, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, provided that the above
|
||||
copyright notice(s) and this permission notice appear in all copies of
|
||||
the Software and that both the above copyright notice(s) and this
|
||||
permission notice appear in supporting documentation.
|
||||
|
||||
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
|
||||
OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
|
||||
SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
|
||||
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
||||
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of a copyright holder
|
||||
shall not be used in advertising or otherwise to promote the sale, use
|
||||
or other dealings in this Software without prior written authorization
|
||||
of the copyright holder.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _XVDIX_H_
|
||||
#define _XVDIX_H_
|
||||
|
||||
#include "scrnintstr.h"
|
||||
#include "regionstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "mivalidate.h"
|
||||
#include "validate.h"
|
||||
#include "resource.h"
|
||||
#include "gcstruct.h"
|
||||
#include "dixstruct.h"
|
||||
|
||||
#include "../../Xext/xvdix.h"
|
||||
|
||||
#define VIDEO_OVERLAID_IMAGES 0x00000004
|
||||
#define VIDEO_OVERLAID_STILLS 0x00000008
|
||||
#define VIDEO_CLIP_TO_VIEWPORT 0x00000010
|
||||
|
||||
typedef int (*PutVideoFuncPtr) (KdScreenInfo * screen, DrawablePtr pDraw,
|
||||
short vid_x, short vid_y, short drw_x,
|
||||
short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
void *data);
|
||||
typedef int (*PutStillFuncPtr) (KdScreenInfo * screen, DrawablePtr pDraw,
|
||||
short vid_x, short vid_y, short drw_x,
|
||||
short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
void *data);
|
||||
typedef int (*GetVideoFuncPtr) (KdScreenInfo * screen, DrawablePtr pDraw,
|
||||
short vid_x, short vid_y, short drw_x,
|
||||
short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
void *data);
|
||||
typedef int (*GetStillFuncPtr) (KdScreenInfo * screen, DrawablePtr pDraw,
|
||||
short vid_x, short vid_y, short drw_x,
|
||||
short drw_y, short vid_w, short vid_h,
|
||||
short drw_w, short drw_h, RegionPtr clipBoxes,
|
||||
void *data);
|
||||
typedef void (*StopVideoFuncPtr) (KdScreenInfo * screen, void *data,
|
||||
Bool Exit);
|
||||
typedef int (*SetPortAttributeFuncPtr) (KdScreenInfo * screen, Atom attribute,
|
||||
int value, void *data);
|
||||
typedef int (*GetPortAttributeFuncPtr) (KdScreenInfo * screen, Atom attribute,
|
||||
int *value, void *data);
|
||||
typedef void (*QueryBestSizeFuncPtr) (KdScreenInfo * screen, Bool motion,
|
||||
short vid_w, short vid_h, short drw_w,
|
||||
short drw_h, unsigned int *p_w,
|
||||
unsigned int *p_h, void *data);
|
||||
typedef int (*PutImageFuncPtr) (KdScreenInfo * screen, DrawablePtr pDraw,
|
||||
short src_x, short src_y, short drw_x,
|
||||
short drw_y, short src_w, short src_h,
|
||||
short drw_w, short drw_h, int image,
|
||||
unsigned char *buf, short width, short height,
|
||||
Bool Sync, RegionPtr clipBoxes, void *data);
|
||||
typedef int (*ReputImageFuncPtr) (KdScreenInfo * screen, DrawablePtr pDraw,
|
||||
short drw_x, short drw_y, RegionPtr clipBoxes,
|
||||
void *data);
|
||||
typedef int (*QueryImageAttributesFuncPtr) (KdScreenInfo * screen, int image,
|
||||
unsigned short *width,
|
||||
unsigned short *height,
|
||||
int *pitches, int *offsets);
|
||||
|
||||
typedef enum {
|
||||
XV_OFF,
|
||||
XV_PENDING,
|
||||
XV_ON
|
||||
} XvStatus;
|
||||
|
||||
/*** this is what the driver needs to fill out ***/
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
const char *name;
|
||||
unsigned short width, height;
|
||||
XvRationalRec rate;
|
||||
} KdVideoEncodingRec, *KdVideoEncodingPtr;
|
||||
|
||||
typedef struct {
|
||||
char depth;
|
||||
short class;
|
||||
} KdVideoFormatRec, *KdVideoFormatPtr;
|
||||
|
||||
typedef struct {
|
||||
unsigned int type;
|
||||
int flags;
|
||||
const char *name;
|
||||
int nEncodings;
|
||||
KdVideoEncodingPtr pEncodings;
|
||||
int nFormats;
|
||||
KdVideoFormatPtr pFormats;
|
||||
int nPorts;
|
||||
DevUnion *pPortPrivates;
|
||||
int nAttributes;
|
||||
XvAttributePtr pAttributes;
|
||||
int nImages;
|
||||
XvImagePtr pImages;
|
||||
PutVideoFuncPtr PutVideo;
|
||||
PutStillFuncPtr PutStill;
|
||||
GetVideoFuncPtr GetVideo;
|
||||
GetStillFuncPtr GetStill;
|
||||
StopVideoFuncPtr StopVideo;
|
||||
SetPortAttributeFuncPtr SetPortAttribute;
|
||||
GetPortAttributeFuncPtr GetPortAttribute;
|
||||
QueryBestSizeFuncPtr QueryBestSize;
|
||||
PutImageFuncPtr PutImage;
|
||||
ReputImageFuncPtr ReputImage;
|
||||
QueryImageAttributesFuncPtr QueryImageAttributes;
|
||||
} KdVideoAdaptorRec, *KdVideoAdaptorPtr;
|
||||
|
||||
Bool
|
||||
KdXVScreenInit(ScreenPtr pScreen, KdVideoAdaptorPtr Adaptors, int num);
|
||||
|
||||
/*** These are DDX layer privates ***/
|
||||
|
||||
typedef struct {
|
||||
DestroyWindowProcPtr DestroyWindow;
|
||||
ClipNotifyProcPtr ClipNotify;
|
||||
WindowExposuresProcPtr WindowExposures;
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
} KdXVScreenRec, *KdXVScreenPtr;
|
||||
|
||||
typedef struct {
|
||||
int flags;
|
||||
PutVideoFuncPtr PutVideo;
|
||||
PutStillFuncPtr PutStill;
|
||||
GetVideoFuncPtr GetVideo;
|
||||
GetStillFuncPtr GetStill;
|
||||
StopVideoFuncPtr StopVideo;
|
||||
SetPortAttributeFuncPtr SetPortAttribute;
|
||||
GetPortAttributeFuncPtr GetPortAttribute;
|
||||
QueryBestSizeFuncPtr QueryBestSize;
|
||||
PutImageFuncPtr PutImage;
|
||||
ReputImageFuncPtr ReputImage;
|
||||
QueryImageAttributesFuncPtr QueryImageAttributes;
|
||||
} XvAdaptorRecPrivate, *XvAdaptorRecPrivatePtr;
|
||||
|
||||
typedef struct {
|
||||
KdScreenInfo *screen;
|
||||
DrawablePtr pDraw;
|
||||
unsigned char type;
|
||||
unsigned int subWindowMode;
|
||||
DDXPointRec clipOrg;
|
||||
RegionPtr clientClip;
|
||||
RegionPtr pCompositeClip;
|
||||
Bool FreeCompositeClip;
|
||||
XvAdaptorRecPrivatePtr AdaptorRec;
|
||||
XvStatus isOn;
|
||||
Bool moved;
|
||||
int vid_x, vid_y, vid_w, vid_h;
|
||||
int drw_x, drw_y, drw_w, drw_h;
|
||||
DevUnion DevPriv;
|
||||
} XvPortRecPrivate, *XvPortRecPrivatePtr;
|
||||
|
||||
typedef struct _KdXVWindowRec {
|
||||
XvPortRecPrivatePtr PortRec;
|
||||
struct _KdXVWindowRec *next;
|
||||
} KdXVWindowRec, *KdXVWindowPtr;
|
||||
|
||||
#endif /* _XVDIX_H_ */
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
srcs_kdrive = [
|
||||
'kcmap.c',
|
||||
'kdrive.c',
|
||||
'kinfo.c',
|
||||
'kinput.c',
|
||||
'kshadow.c',
|
||||
'../../../mi/miinitext.c',
|
||||
'../../../mi/miinitext.h',
|
||||
]
|
||||
|
||||
if build_xv
|
||||
srcs_kdrive += 'kxv.c'
|
||||
endif
|
||||
|
||||
kdrive = static_library('kdrive',
|
||||
srcs_kdrive,
|
||||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
link_with: libxserver_miext_shadow,
|
||||
)
|
||||
|
|
@ -1,27 +1,7 @@
|
|||
if get_option('xephyr')
|
||||
subdir('kdrive')
|
||||
endif
|
||||
|
||||
if get_option('xvfb')
|
||||
subdir('vfb')
|
||||
endif
|
||||
|
||||
if build_xnest
|
||||
subdir('xnest')
|
||||
endif
|
||||
|
||||
if build_xorg
|
||||
subdir('xfree86')
|
||||
endif
|
||||
|
||||
if build_xquartz
|
||||
subdir('xquartz')
|
||||
endif
|
||||
|
||||
if build_xwayland
|
||||
subdir('xwayland')
|
||||
endif
|
||||
|
||||
if build_xwin
|
||||
subdir('xwin')
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -1,124 +0,0 @@
|
|||
.\" $XdotOrg: xc/programs/Xserver/hw/vfb/Xvfb.man,v 1.3 2005/03/23 20:49:52 gisburn Exp $
|
||||
.\" $Xorg: Xvfb.man,v 1.4 2001/02/09 02:04:45 xorgcvs Exp $
|
||||
.\" Copyright 1993, 1998 The Open Group
|
||||
.\"
|
||||
.\" Permission to use, copy, modify, distribute, and sell this software and its
|
||||
.\" documentation for any purpose is hereby granted without fee, provided that
|
||||
.\" the above copyright notice appear in all copies and that both that
|
||||
.\" copyright notice and this permission notice appear in supporting
|
||||
.\" documentation.
|
||||
.\"
|
||||
.\" The above copyright notice and this permission notice 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 OPEN GROUP 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.
|
||||
.\"
|
||||
.\" Except as contained in this notice, the name of The Open Group shall
|
||||
.\" not be used in advertising or otherwise to promote the sale, use or
|
||||
.\" other dealings in this Software without prior written authorization
|
||||
.\" from The Open Group.
|
||||
.\"
|
||||
.\" $XFree86: xc/programs/Xserver/hw/vfb/Xvfb.man,v 1.9 2001/12/14 19:59:45 dawes Exp $
|
||||
.\"
|
||||
.TH XVFB 1 @xorgversion@
|
||||
.SH NAME
|
||||
Xvfb \- virtual framebuffer X server for X Version 11
|
||||
.SH SYNOPSIS
|
||||
.B Xvfb
|
||||
[ option ] ...
|
||||
.SH DESCRIPTION
|
||||
.I Xvfb
|
||||
is an X server that can run on machines with no display hardware
|
||||
and no physical input devices. It emulates a dumb framebuffer using
|
||||
virtual memory.
|
||||
.PP
|
||||
The primary use of this server was intended to be server testing. The
|
||||
fb code for any depth can be exercised with this server
|
||||
without the need for real hardware that supports the desired depths.
|
||||
The X community has found many other novel uses for \fIXvfb\fP,
|
||||
including testing clients against unusual depths and screen
|
||||
configurations, doing batch processing with \fIXvfb\fP as a background
|
||||
rendering engine, load testing, as an aid to porting the X server to a
|
||||
new platform, and providing an unobtrusive way to run applications
|
||||
that don't really need an X server but insist on having one anyway.
|
||||
.SH OPTIONS
|
||||
.PP
|
||||
In addition to the normal server options described in the \fIXserver(1)\fP
|
||||
manual page, \fIXvfb\fP accepts the following command line switches:
|
||||
.TP 4
|
||||
.B "\-screen \fIscreennum\fP \fIWxHxD\fP"
|
||||
This option creates screen \fIscreennum\fP and sets its width, height,
|
||||
and depth to W, H, and D respectively. By default, only screen 0 exists
|
||||
and has the dimensions 1280x1024x24.
|
||||
.TP 4
|
||||
.B "\-pixdepths \fIlist-of-depths\fP"
|
||||
This option specifies a list of pixmap depths that the server should
|
||||
support in addition to the depths implied by the supported screens.
|
||||
\fIlist-of-depths\fP is a space-separated list of integers that can
|
||||
have values from 1 to 32.
|
||||
.TP 4
|
||||
.B "\-fbdir \fIframebuffer-directory\fP"
|
||||
This option specifies the directory in which the memory mapped files
|
||||
containing the framebuffer memory should be created.
|
||||
See FILES.
|
||||
This option only exists on machines that have the mmap and msync system
|
||||
calls.
|
||||
.TP 4
|
||||
.B "\-shmem"
|
||||
This option specifies that the framebuffer should be put in shared memory.
|
||||
The shared memory ID for each screen will be printed by the server.
|
||||
The shared memory is in xwd format.
|
||||
This option only exists on machines that support the System V shared memory
|
||||
interface.
|
||||
.PP
|
||||
If neither \fB\-shmem\fP nor \fB\-fbdir\fP is specified,
|
||||
the framebuffer memory will be allocated with malloc().
|
||||
.TP 4
|
||||
.B "\-linebias \fIn\fP"
|
||||
This option specifies how to adjust the pixelization of thin lines.
|
||||
The value \fIn\fP is a bitmask of octants in which to prefer an axial
|
||||
step when the Bresenham error term is exactly zero. See the file
|
||||
Xserver/mi/miline.h for more information. This option is probably only useful
|
||||
to server developers to experiment with the range of line pixelization
|
||||
possible with the fb code.
|
||||
.TP 4
|
||||
.B "\-blackpixel \fIpixel-value\fP, \-whitepixel \fIpixel-value\fP"
|
||||
These options specify the black and white pixel values the server should use.
|
||||
.SH FILES
|
||||
The following files are created if the \-fbdir option is given.
|
||||
.TP 4
|
||||
\fIframebuffer-directory\fP/Xvfb_screen<n>
|
||||
Memory mapped file containing screen n's framebuffer memory, one file
|
||||
per screen. The file is in xwd format. Thus, taking a full-screen
|
||||
snapshot can be done with a file copy command, and the resulting
|
||||
snapshot will even contain the cursor image.
|
||||
.SH EXAMPLES
|
||||
.TP 8
|
||||
Xvfb :1 -screen 0 1600x1200x24
|
||||
The server will listen for connections as server number 1, and screen 0
|
||||
will be depth 24 1600x1200.
|
||||
.TP 8
|
||||
Xvfb :1 -screen 1 1600x1200x16
|
||||
The server will listen for connections as server number 1, screen 0 will have the
|
||||
default screen configuration (1280x1024x24), and screen 1 will be depth 16 1600x1200.
|
||||
.TP 8
|
||||
Xvfb -pixdepths 3 27 -fbdir /var/tmp
|
||||
The server will listen for connections as server number 0, will have the
|
||||
default screen configuration (one screen, 1280x1024x24),
|
||||
will also support pixmap
|
||||
depths of 3 and 27,
|
||||
and will use memory mapped files in /var/tmp for the framebuffer.
|
||||
.TP 8
|
||||
xwud -in /var/tmp/Xvfb_screen0
|
||||
Displays screen 0 of the server started by the preceding example.
|
||||
.SH "SEE ALSO"
|
||||
.PP
|
||||
X(@miscmansuffix@), Xserver(1), xwd(1), xwud(1), XWDFile.h
|
||||
.SH AUTHORS
|
||||
David P. Wiggins, The Open Group, Inc.
|
||||
|
|
@ -19,11 +19,5 @@ xvfb_server = executable(
|
|||
libxserver_glx,
|
||||
libglxvnd,
|
||||
],
|
||||
install: true,
|
||||
install: false,
|
||||
)
|
||||
|
||||
install_man(configure_file(
|
||||
input: 'man/Xvfb.man',
|
||||
output: 'Xvfb.1',
|
||||
configuration: manpage_config,
|
||||
))
|
||||
|
|
|
|||
6
hw/xfree86/.gitignore
vendored
6
hw/xfree86/.gitignore
vendored
|
|
@ -1,6 +0,0 @@
|
|||
Xorg
|
||||
Xorg.wrap
|
||||
Xorg.sh
|
||||
xorg.conf.example
|
||||
sdksyms.c
|
||||
sdksyms.dep
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Execute Xorg.wrap if it exists otherwise execute Xorg directly.
|
||||
# This allows distros to put the suid wrapper in a separate package.
|
||||
|
||||
basedir=@SUID_WRAPPER_DIR@
|
||||
if [ -x "$basedir"/Xorg.wrap ]; then
|
||||
exec "$basedir"/Xorg.wrap "$@"
|
||||
else
|
||||
exec "$basedir"/Xorg "$@"
|
||||
fi
|
||||
3
hw/xfree86/common/.gitignore
vendored
3
hw/xfree86/common/.gitignore
vendored
|
|
@ -1,3 +0,0 @@
|
|||
# Add & Override for this directory and its subdirectories
|
||||
xf86Build.h
|
||||
xf86DefModeSet.c
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,55 +0,0 @@
|
|||
|
||||
#ifndef __DGAPROC_H
|
||||
#define __DGAPROC_H
|
||||
|
||||
#include <X11/Xproto.h>
|
||||
#include "pixmap.h"
|
||||
|
||||
#define DGA_CONCURRENT_ACCESS 0x00000001
|
||||
#define DGA_FILL_RECT 0x00000002
|
||||
#define DGA_BLIT_RECT 0x00000004
|
||||
#define DGA_BLIT_RECT_TRANS 0x00000008
|
||||
#define DGA_PIXMAP_AVAILABLE 0x00000010
|
||||
|
||||
#define DGA_INTERLACED 0x00010000
|
||||
#define DGA_DOUBLESCAN 0x00020000
|
||||
|
||||
#define DGA_FLIP_IMMEDIATE 0x00000001
|
||||
#define DGA_FLIP_RETRACE 0x00000002
|
||||
|
||||
#define DGA_COMPLETED 0x00000000
|
||||
#define DGA_PENDING 0x00000001
|
||||
|
||||
#define DGA_NEED_ROOT 0x00000001
|
||||
|
||||
typedef struct {
|
||||
int num; /* A unique identifier for the mode (num > 0) */
|
||||
const char *name; /* name of mode given in the XF86Config */
|
||||
int VSync_num;
|
||||
int VSync_den;
|
||||
int flags; /* DGA_CONCURRENT_ACCESS, etc... */
|
||||
int imageWidth; /* linear accessible portion (pixels) */
|
||||
int imageHeight;
|
||||
int pixmapWidth; /* Xlib accessible portion (pixels) */
|
||||
int pixmapHeight; /* both fields ignored if no concurrent access */
|
||||
int bytesPerScanline;
|
||||
int byteOrder; /* MSBFirst, LSBFirst */
|
||||
int depth;
|
||||
int bitsPerPixel;
|
||||
unsigned long red_mask;
|
||||
unsigned long green_mask;
|
||||
unsigned long blue_mask;
|
||||
short visualClass;
|
||||
int viewportWidth;
|
||||
int viewportHeight;
|
||||
int xViewportStep; /* viewport position granularity */
|
||||
int yViewportStep;
|
||||
int maxViewportX; /* max viewport origin */
|
||||
int maxViewportY;
|
||||
int viewportFlags; /* types of page flipping possible */
|
||||
int offset;
|
||||
int reserved1;
|
||||
int reserved2;
|
||||
} XDGAModeRec, *XDGAModePtr;
|
||||
|
||||
#endif /* __DGAPROC_H */
|
||||
|
|
@ -1,168 +0,0 @@
|
|||
//
|
||||
// Extra modes to include as default modes in the X server.
|
||||
//
|
||||
// $XFree86: xc/programs/Xserver/hw/xfree86/etc/extramodes,v 1.5 2002/06/05 19:43:05 dawes Exp $
|
||||
//
|
||||
|
||||
# 832x624 @ 75Hz (74.55Hz) (fix if the official/Apple spec is different) hsync: 49.725kHz
|
||||
ModeLine "832x624" 57.284 832 864 928 1152 624 625 628 667 -Hsync -Vsync
|
||||
|
||||
# 1400x1050 @ 60Hz (VESA GTF) hsync: 65.5kHz
|
||||
ModeLine "1400x1050" 122.0 1400 1488 1640 1880 1050 1052 1064 1082 +hsync +vsync
|
||||
|
||||
# 1400x1050 @ 75Hz (VESA GTF) hsync: 82.2kHz
|
||||
ModeLine "1400x1050" 155.8 1400 1464 1784 1912 1050 1052 1064 1090 +hsync +vsync
|
||||
|
||||
# 1920x1440 @ 85Hz (VESA GTF) hsync: 128.5kHz
|
||||
Modeline "1920x1440" 341.35 1920 2072 2288 2656 1440 1441 1444 1512 -hsync +vsync
|
||||
|
||||
# 2048x1536 @ 60Hz (VESA GTF) hsync: 95.3kHz
|
||||
Modeline "2048x1536" 266.95 2048 2200 2424 2800 1536 1537 1540 1589 -hsync +vsync
|
||||
|
||||
# 2048x1536 @ 75Hz (VESA GTF) hsync: 120.2kHz
|
||||
Modeline "2048x1536" 340.48 2048 2216 2440 2832 1536 1537 1540 1603 -hsync +vsync
|
||||
|
||||
# 2048x1536 @ 85Hz (VESA GTF) hsync: 137.0kHz
|
||||
Modeline "2048x1536" 388.04 2048 2216 2440 2832 1536 1537 1540 1612 -hsync +vsync
|
||||
|
||||
### 16:9 modelines generated by cvt
|
||||
|
||||
# 640x360 59.32 Hz (CVT 0.23M9-R) hsync: 22.19 kHz; pclk: 17.75 MHz
|
||||
Modeline "640x360R" 17.75 640 688 720 800 360 363 368 374 +hsync -vsync
|
||||
|
||||
# 640x360 59.84 Hz (CVT 0.23M9) hsync: 22.50 kHz; pclk: 18.00 MHz
|
||||
Modeline "640x360" 18.00 640 664 720 800 360 363 368 376 -hsync +vsync
|
||||
|
||||
# 720x405 58.99 Hz (CVT 0.29M9-R) hsync: 24.72 kHz; pclk: 21.75 MHz
|
||||
Modeline "720x405R" 21.75 720 768 800 880 405 408 413 419 +hsync -vsync
|
||||
|
||||
# 720x405 59.51 Hz (CVT 0.29M9) hsync: 25.11 kHz; pclk: 22.50 MHz
|
||||
Modeline "720x405" 22.50 720 744 808 896 405 408 413 422 -hsync +vsync
|
||||
|
||||
# 864x486 59.57 Hz (CVT 0.42M9-R) hsync: 29.79 kHz; pclk: 30.50 MHz
|
||||
Modeline "864x486R" 30.50 864 912 944 1024 486 489 494 500 +hsync -vsync
|
||||
|
||||
# 864x486 59.92 Hz (CVT 0.42M9) hsync: 30.32 kHz; pclk: 32.50 MHz
|
||||
Modeline "864x486" 32.50 864 888 968 1072 486 489 494 506 -hsync +vsync
|
||||
|
||||
# 960x540 59.82 Hz (CVT 0.52M9-R) hsync: 33.26 kHz; pclk: 37.25 MHz
|
||||
Modeline "960x540R" 37.25 960 1008 1040 1120 540 543 548 556 +hsync -vsync
|
||||
|
||||
# 960x540 59.63 Hz (CVT 0.52M9) hsync: 33.51 kHz; pclk: 40.75 MHz
|
||||
Modeline "960x540" 40.75 960 992 1088 1216 540 543 548 562 -hsync +vsync
|
||||
|
||||
# 1024x576 59.82 Hz (CVT 0.59M9-R) hsync: 35.47 kHz; pclk: 42.00 MHz
|
||||
Modeline "1024x576R" 42.00 1024 1072 1104 1184 576 579 584 593 +hsync -vsync
|
||||
|
||||
# 1024x576 59.90 Hz (CVT 0.59M9) hsync: 35.88 kHz; pclk: 46.50 MHz
|
||||
Modeline "1024x576" 46.50 1024 1064 1160 1296 576 579 584 599 -hsync +vsync
|
||||
|
||||
# 1280x720 59.74 Hz (CVT 0.92M9-R) hsync: 44.27 kHz; pclk: 63.75 MHz
|
||||
Modeline "1280x720R" 63.75 1280 1328 1360 1440 720 723 728 741 +hsync -vsync
|
||||
|
||||
# 1280x720 59.86 Hz (CVT 0.92M9) hsync: 44.77 kHz; pclk: 74.50 MHz
|
||||
Modeline "1280x720" 74.50 1280 1344 1472 1664 720 723 728 748 -hsync +vsync
|
||||
|
||||
# 1368x768 59.85 Hz (CVT) hsync: 47.28 kHz; pclk: 72.25 MHz
|
||||
Modeline "1368x768R" 72.25 1368 1416 1448 1528 768 771 781 790 +hsync -vsync
|
||||
|
||||
# 1368x768 59.88 Hz (CVT) hsync: 47.79 kHz; pclk: 85.25 MHz
|
||||
Modeline "1368x768" 85.25 1368 1440 1576 1784 768 771 781 798 -hsync +vsync
|
||||
|
||||
# 1600x900 59.82 Hz (CVT 1.44M9-R) hsync: 55.40 kHz; pclk: 97.50 MHz
|
||||
Modeline "1600x900R" 97.50 1600 1648 1680 1760 900 903 908 926 +hsync -vsync
|
||||
|
||||
# 1600x900 59.95 Hz (CVT 1.44M9) hsync: 55.99 kHz; pclk: 118.25 MHz
|
||||
Modeline "1600x900" 118.25 1600 1696 1856 2112 900 903 908 934 -hsync +vsync
|
||||
|
||||
# 1920x1080 59.93 Hz (CVT 2.07M9-R) hsync: 66.59 kHz; pclk: 138.50 MHz
|
||||
Modeline "1920x1080R" 138.50 1920 1968 2000 2080 1080 1083 1088 1111 +hsync -vsync
|
||||
|
||||
# 1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.16 kHz; pclk: 173.00 MHz
|
||||
Modeline "1920x1080" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
|
||||
|
||||
# 2048x1152 59.91 Hz (CVT 2.36M9-R) hsync: 70.99 kHz; pclk: 156.75 MHz
|
||||
Modeline "2048x1152R" 156.75 2048 2096 2128 2208 1152 1155 1160 1185 +hsync -vsync
|
||||
|
||||
# 2048x1152 59.90 Hz (CVT 2.36M9) hsync: 71.58 kHz; pclk: 197.00 MHz
|
||||
Modeline "2048x1152" 197.00 2048 2184 2400 2752 1152 1155 1160 1195 -hsync +vsync
|
||||
|
||||
# 2560x1440 59.95 Hz (CVT 3.69M9-R) hsync: 88.79 kHz; pclk: 241.50 MHz
|
||||
Modeline "2560x1440R" 241.50 2560 2608 2640 2720 1440 1443 1448 1481 +hsync -vsync
|
||||
|
||||
# 2560x1440 59.96 Hz (CVT 3.69M9) hsync: 89.52 kHz; pclk: 312.25 MHz
|
||||
Modeline "2560x1440" 312.25 2560 2752 3024 3488 1440 1443 1448 1493 -hsync +vsync
|
||||
|
||||
# 2880x1620 59.97 Hz (CVT 4.67M9-R) hsync: 99.92 kHz; pclk: 303.75 MHz
|
||||
Modeline "2880x1620R" 303.75 2880 2928 2960 3040 1620 1623 1628 1666 +hsync -vsync
|
||||
|
||||
# 2880x1620 59.96 Hz (CVT 4.67M9) hsync: 100.67 kHz; pclk: 396.25 MHz
|
||||
Modeline "2880x1620" 396.25 2880 3096 3408 3936 1620 1623 1628 1679 -hsync +vsync
|
||||
|
||||
# 3200x1800 59.94 Hz (CVT 5.76M9-R) hsync: 111.01 kHz; pclk: 373.00 MHz
|
||||
Modeline "3200x1800R" 373.00 3200 3248 3280 3360 1800 1803 1808 1852 +hsync -vsync
|
||||
|
||||
# 3200x1800 59.96 Hz (CVT 5.76M9) hsync: 111.82 kHz; pclk: 492.00 MHz
|
||||
Modeline "3200x1800" 492.00 3200 3456 3800 4400 1800 1803 1808 1865 -hsync +vsync
|
||||
|
||||
# 3840x2160 59.97 Hz (CVT 8.29M9-R) hsync: 133.25 kHz; pclk: 533.00 MHz
|
||||
Modeline "3840x2160R" 533.00 3840 3888 3920 4000 2160 2163 2168 2222 +hsync -vsync
|
||||
|
||||
# 3840x2160 59.98 Hz (CVT 8.29M9) hsync: 134.18 kHz; pclk: 712.75 MHz
|
||||
Modeline "3840x2160" 712.75 3840 4160 4576 5312 2160 2163 2168 2237 -hsync +vsync
|
||||
|
||||
# 4096x2304 59.98 Hz (CVT 9.44M9-R) hsync: 142.15 kHz; pclk: 605.00 MHz
|
||||
Modeline "4096x2304R" 605.00 4096 4144 4176 4256 2304 2307 2312 2370 +hsync -vsync
|
||||
|
||||
# 4096x2304 59.99 Hz (CVT 9.44M9) hsync: 143.13 kHz; pclk: 813.00 MHz
|
||||
Modeline "4096x2304" 813.00 4096 4440 4888 5680 2304 2307 2312 2386 -hsync +vsync
|
||||
|
||||
# 5120x2880 59.99 Hz (CVT 14.75M9-R) hsync: 177.70 kHz; pclk: 938.25 MHz
|
||||
Modeline "5120x2880R" 938.25 5120 5168 5200 5280 2880 2883 2888 2962 +hsync -vsync
|
||||
|
||||
# 5120x2880 59.99 Hz (CVT 14.75M9) hsync: 178.88 kHz; pclk: 1276.50 MHz
|
||||
Modeline "5120x2880" 1276.50 5120 5560 6128 7136 2880 2883 2888 2982 -hsync +vsync
|
||||
|
||||
# 7680x4320 59.99 Hz (CVT 33.18M9-R) hsync: 266.55 kHz; pclk: 2089.75 MHz
|
||||
Modeline "7680x4320R" 2089.75 7680 7728 7760 7840 4320 4323 4328 4443 +hsync -vsync
|
||||
|
||||
# 7680x4320 59.99 Hz (CVT 33.18M9) hsync: 268.22 kHz; pclk: 2892.50 MHz
|
||||
Modeline "7680x4320" 2892.50 7680 8376 9232 10784 4320 4323 4328 4471 -hsync +vsync
|
||||
|
||||
# 15360x8640 59.99 Hz (CVT 132.71M9-R) hsync: 533.10 kHz; pclk: 8273.75 MHz
|
||||
Modeline "15360x8640R" 8273.75 15360 15408 15440 15520 8640 8643 8648 8886 +hsync -vsync
|
||||
|
||||
# 15360x8640 60.00 Hz (CVT 132.71M9) hsync: 536.27 kHz; pclk: 11669.25 MHz
|
||||
Modeline "15360x8640" 11669.25 15360 16824 18560 21760 8640 8643 8648 8938 -hsync +vsync
|
||||
|
||||
## 16:10 modelines generated by cvt
|
||||
|
||||
# 1280x800 59.91 Hz (CVT 1.02MA-R) hsync: 49.31 kHz; pclk: 71.00 MHz
|
||||
Modeline "1280x800R" 71.00 1280 1328 1360 1440 800 803 809 823 +hsync -vsync
|
||||
|
||||
# 1280x800 59.81 Hz (CVT 1.02MA) hsync: 49.70 kHz; pclk: 83.50 MHz
|
||||
Modeline "1280x800" 83.50 1280 1352 1480 1680 800 803 809 831 -hsync +vsync
|
||||
|
||||
# 1400x900 59.88 Hz (CVT) hsync: 55.45 kHz; pclk: 86.50 MHz
|
||||
Modeline "1400x900R" 86.50 1400 1448 1480 1560 900 903 913 926 +hsync -vsync
|
||||
|
||||
# 1400x900 59.96 Hz (CVT) hsync: 56.01 kHz; pclk: 103.50 MHz
|
||||
Modeline "1400x900" 103.50 1400 1480 1624 1848 900 903 913 934 -hsync +vsync
|
||||
|
||||
# 1680x1050 59.88 Hz (CVT 1.76MA-R) hsync: 64.67 kHz; pclk: 119.00 MHz
|
||||
Modeline "1680x1050R" 119.00 1680 1728 1760 1840 1050 1053 1059 1080 +hsync -vsync
|
||||
|
||||
# 1680x1050 59.95 Hz (CVT 1.76MA) hsync: 65.29 kHz; pclk: 146.25 MHz
|
||||
Modeline "1680x1050" 146.25 1680 1784 1960 2240 1050 1053 1059 1089 -hsync +vsync
|
||||
|
||||
# 1920x1200 59.95 Hz (CVT 2.30MA-R) hsync: 74.04 kHz; pclk: 154.00 MHz
|
||||
Modeline "1920x1200R" 154.00 1920 1968 2000 2080 1200 1203 1209 1235 +hsync -vsync
|
||||
|
||||
# 1920x1200 59.88 Hz (CVT 2.30MA) hsync: 74.56 kHz; pclk: 193.25 MHz
|
||||
Modeline "1920x1200" 193.25 1920 2056 2256 2592 1200 1203 1209 1245 -hsync +vsync
|
||||
|
||||
# 2560x1600 59.97 Hz (CVT 4.10MA-R) hsync: 98.71 kHz; pclk: 268.50 MHz
|
||||
Modeline "2560x1600R" 268.50 2560 2608 2640 2720 1600 1603 1609 1646 +hsync -vsync
|
||||
|
||||
# 2560x1600 59.99 Hz (CVT 4.10MA) hsync: 99.46 kHz; pclk: 348.50 MHz
|
||||
Modeline "2560x1600" 348.50 2560 2760 3032 3504 1600 1603 1609 1658 -hsync +vsync
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue