New upstream version 22.1.8
This commit is contained in:
parent
48258f0cc7
commit
decbdc3bfd
|
@ -26,7 +26,7 @@ gcc-core,\
|
|||
meson,\
|
||||
ninja,\
|
||||
pkg-config,\
|
||||
python3,\
|
||||
python38,\
|
||||
windowsdriproto,\
|
||||
xorgproto,\
|
||||
libepoxy-devel,\
|
||||
|
@ -58,10 +58,11 @@ libxcb-render-util-devel,\
|
|||
libxcb-shape-devel,\
|
||||
libxcb-util-devel,\
|
||||
libxcb-xkb-devel,\
|
||||
libxcvt-devel,\
|
||||
libxkbfile-devel,\
|
||||
font-util,\
|
||||
khronos-opengl-registry,\
|
||||
python3-lxml,\
|
||||
python38-lxml,\
|
||||
xkbcomp-devel,\
|
||||
xkeyboard-config,\
|
||||
xtrans"
|
||||
|
@ -72,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 -Dxvfb=true 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"'
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
#
|
||||
# X.Org module default exclusion patterns
|
||||
# The next section if for module specific patterns
|
||||
#
|
||||
# Do not edit the following section
|
||||
# GNU Build System (Autotools)
|
||||
aclocal.m4
|
||||
autom4te.cache/
|
||||
autoscan.log
|
||||
ChangeLog
|
||||
compile
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config-ml.in
|
||||
config.py
|
||||
config.status
|
||||
config.status.lineno
|
||||
config.sub
|
||||
configure
|
||||
configure.scan
|
||||
depcomp
|
||||
.deps/
|
||||
INSTALL
|
||||
install-sh
|
||||
.libs/
|
||||
libtool
|
||||
libtool.m4
|
||||
ltmain.sh
|
||||
lt~obsolete.m4
|
||||
ltoptions.m4
|
||||
ltsugar.m4
|
||||
ltversion.m4
|
||||
Makefile
|
||||
Makefile.in
|
||||
mdate-sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
*.pc
|
||||
py-compile
|
||||
stamp-h?
|
||||
symlink-tree
|
||||
test-driver
|
||||
texinfo.tex
|
||||
ylwrap
|
||||
|
||||
# Do not edit the following section
|
||||
# Edit Compile Debug Document Distribute
|
||||
*~
|
||||
*.[0-9]
|
||||
*.[0-9]x
|
||||
*.bak
|
||||
*.bin
|
||||
core
|
||||
*.dll
|
||||
*.exe
|
||||
*-ISO*.bdf
|
||||
*-JIS*.bdf
|
||||
*-KOI8*.bdf
|
||||
*.kld
|
||||
*.ko
|
||||
*.ko.cmd
|
||||
*.lai
|
||||
*.l[oa]
|
||||
*.[oa]
|
||||
*.obj
|
||||
*.patch
|
||||
*.so
|
||||
*.pcf.gz
|
||||
*.pdb
|
||||
*.tar.bz2
|
||||
*.tar.gz
|
||||
#
|
||||
# Add & Override patterns for xserver
|
||||
#
|
||||
# Edit the following section as needed
|
||||
# For example, !report.pc overrides *.pc. See 'man gitignore'
|
||||
#
|
||||
doltcompile
|
||||
doltlibtool
|
||||
xserver.ent
|
|
@ -0,0 +1,74 @@
|
|||
# FDO_DISTRIBUTION_TAG is the tag of the docker image used for the build jobs.
|
||||
# If the image doesn't exist yet, the docker-image stage generates it.
|
||||
#
|
||||
# In order to generate a new image, one should generally change the tag.
|
||||
# While removing the image from the registry would also work, that's not
|
||||
# recommended except for ephemeral images during development: Replacing an
|
||||
# image after a significant amount of time might pull in newer versions of
|
||||
# gcc/clang or other packages, which might break the build with older commits
|
||||
# using the same tag.
|
||||
variables:
|
||||
FDO_UPSTREAM_REPO: xorg/xserver
|
||||
FDO_DISTRIBUTION_VERSION: buster-slim
|
||||
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/debian-install.sh'
|
||||
FDO_DISTRIBUTION_TAG: "2021-12-13-no-mingw"
|
||||
|
||||
include:
|
||||
- project: 'freedesktop/ci-templates'
|
||||
ref: 4f06663cd1507136a0f8440925a2521098adb298
|
||||
file: '/templates/debian.yml'
|
||||
|
||||
stages:
|
||||
- docker-image
|
||||
- build-and-test
|
||||
|
||||
.ci-run-policy:
|
||||
# Retry jobs after runner system failures
|
||||
retry:
|
||||
max: 2
|
||||
when:
|
||||
- runner_system_failure
|
||||
# Cancel CI run if a newer commit is pushed to the same branch
|
||||
interruptible: true
|
||||
|
||||
debian-buster:
|
||||
extends:
|
||||
- .fdo.container-build@debian
|
||||
- .ci-run-policy
|
||||
stage: docker-image
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
|
||||
.common-build-and-test:
|
||||
extends:
|
||||
- .fdo.distribution-image@debian
|
||||
- .ci-run-policy
|
||||
stage: build-and-test
|
||||
artifacts:
|
||||
when: on_failure
|
||||
paths:
|
||||
- build/test/piglit-results/
|
||||
variables:
|
||||
CCACHE_COMPILERCHECK: content
|
||||
CCACHE_DIR: /cache/xserver/cache
|
||||
LC_ALL: C.UTF-8
|
||||
before_script:
|
||||
- export CCACHE_BASEDIR="$PWD"
|
||||
- export PATH="/usr/lib/ccache:$PATH"
|
||||
- ccache --show-stats
|
||||
after_script:
|
||||
- ccache --show-stats
|
||||
|
||||
meson:
|
||||
extends: .common-build-and-test
|
||||
script:
|
||||
- meson -Dc_args="-fno-common" -Dprefix=/usr -Dxvfb=false -Dwerror=true $MESON_EXTRA_OPTIONS build/
|
||||
- ninja -j${FDO_CI_CONCURRENT:-4} -C build/ dist
|
||||
- PIGLIT_DIR=/root/piglit XTEST_DIR=/root/xts ninja -j${FDO_CI_CONCURRENT:-4} -C build/ test
|
||||
- .gitlab-ci/manpages-check
|
||||
|
||||
meson-noglamor:
|
||||
extends: meson
|
||||
variables:
|
||||
MESON_EXTRA_OPTIONS: >
|
||||
-Dglamor=false
|
|
@ -0,0 +1,181 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
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
|
||||
xauth
|
||||
xvfb
|
||||
"
|
||||
|
||||
apt-get install -y \
|
||||
$EPHEMERAL \
|
||||
autoconf \
|
||||
automake \
|
||||
bison \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
ccache \
|
||||
flex \
|
||||
git \
|
||||
libaudit-dev \
|
||||
libbsd-dev \
|
||||
libcairo2 \
|
||||
libdbus-1-dev \
|
||||
libdmx-dev \
|
||||
libdrm-dev \
|
||||
libegl1-mesa-dev \
|
||||
libepoxy-dev \
|
||||
libevdev2 \
|
||||
libexpat1 \
|
||||
libffi-dev \
|
||||
libgbm-dev \
|
||||
libgcrypt-dev \
|
||||
libgl1-mesa-dev \
|
||||
libgles2 \
|
||||
libglx-mesa0 \
|
||||
libinput10 \
|
||||
libnvidia-egl-wayland-dev \
|
||||
libpciaccess-dev \
|
||||
libpixman-1-dev \
|
||||
libselinux1-dev \
|
||||
libsystemd-dev \
|
||||
libtool \
|
||||
libudev-dev \
|
||||
libunwind-dev \
|
||||
libx11-dev \
|
||||
libx11-xcb-dev \
|
||||
libxau-dev \
|
||||
libxaw7-dev \
|
||||
libxcb-glx0-dev \
|
||||
libxcb-icccm4-dev \
|
||||
libxcb-image0-dev \
|
||||
libxcb-keysyms1-dev \
|
||||
libxcb-randr0-dev \
|
||||
libxcb-render-util0-dev \
|
||||
libxcb-render0-dev \
|
||||
libxcb-shape0-dev \
|
||||
libxcb-shm0-dev \
|
||||
libxcb-util0-dev \
|
||||
libxcb-xf86dri0-dev \
|
||||
libxcb-xkb-dev \
|
||||
libxcb-xv0-dev \
|
||||
libxcb1-dev \
|
||||
libxdmcp-dev \
|
||||
libxext-dev \
|
||||
libxfixes-dev \
|
||||
libxfont-dev \
|
||||
libxi-dev \
|
||||
libxinerama-dev \
|
||||
libxkbcommon0 \
|
||||
libxkbfile-dev \
|
||||
libxmu-dev \
|
||||
libxmuu-dev \
|
||||
libxpm-dev \
|
||||
libxrender-dev \
|
||||
libxres-dev \
|
||||
libxshmfence-dev \
|
||||
libxt-dev \
|
||||
libxtst-dev \
|
||||
libxv-dev \
|
||||
mesa-common-dev \
|
||||
meson \
|
||||
nettle-dev \
|
||||
pkg-config \
|
||||
python3-mako \
|
||||
python3-numpy \
|
||||
python3-six \
|
||||
xfonts-utils \
|
||||
xkb-data \
|
||||
xtrans-dev \
|
||||
xutils-dev
|
||||
|
||||
cd /root
|
||||
|
||||
# xserver requires libxcvt
|
||||
git clone https://gitlab.freedesktop.org/xorg/lib/libxcvt.git --depth 1 --branch=libxcvt-0.1.0
|
||||
cd libxcvt
|
||||
meson _build
|
||||
ninja -C _build -j${FDO_CI_CONCURRENT:-4} install
|
||||
cd ..
|
||||
rm -rf libxcvt
|
||||
|
||||
# xserver requires xorgproto >= 2021.4.99.2 for XI 2.3.99.1
|
||||
git clone https://gitlab.freedesktop.org/xorg/proto/xorgproto.git --depth 1 --branch=xorgproto-2021.4.99.2
|
||||
pushd xorgproto
|
||||
./autogen.sh
|
||||
make -j${FDO_CI_CONCURRENT:-4} install
|
||||
popd
|
||||
rm -rf xorgproto
|
||||
|
||||
# weston 9.0 requires libwayland >= 1.18
|
||||
git clone https://gitlab.freedesktop.org/wayland/wayland.git --depth 1 --branch=1.18.0
|
||||
cd wayland
|
||||
meson _build -D{documentation,dtd_validation}=false
|
||||
ninja -C _build -j${FDO_CI_CONCURRENT:-4} install
|
||||
cd ..
|
||||
rm -rf wayland
|
||||
|
||||
# Xwayland requires wayland-protocols >= 1.22, but Debian buster has 1.17 only
|
||||
git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git --depth 1 --branch=1.22
|
||||
cd wayland-protocols
|
||||
./autogen.sh
|
||||
make -j${FDO_CI_CONCURRENT:-4} install
|
||||
cd ..
|
||||
rm -rf wayland-protocols
|
||||
|
||||
# Xwayland requires weston > 5.0, but Debian buster has 5.0 only
|
||||
git clone https://gitlab.freedesktop.org/wayland/weston.git --depth 1 --branch=9.0
|
||||
cd weston
|
||||
meson _build -Dbackend-{drm,drm-screencast-vaapi,fbdev,rdp,wayland,x11}=false \
|
||||
-Dbackend-default=headless -Dcolor-management-{colord,lcms}=false \
|
||||
-Ddemo-clients=false -Dimage-{jpeg,webp}=false \
|
||||
-D{pipewire,remoting,screenshare,test-junit-xml,wcap-decode,weston-launch,xwayland}=false \
|
||||
-Dshell-{fullscreen,ivi,kiosk}=false -Dsimple-clients=
|
||||
ninja -C _build -j${FDO_CI_CONCURRENT:-4} install
|
||||
cd ..
|
||||
rm -rf weston
|
||||
|
||||
git clone https://gitlab.freedesktop.org/mesa/piglit.git --depth 1
|
||||
|
||||
git clone https://gitlab.freedesktop.org/xorg/test/xts --depth 1
|
||||
cd xts
|
||||
./autogen.sh
|
||||
xvfb-run make -j${FDO_CI_CONCURRENT:-4}
|
||||
cd ..
|
||||
|
||||
git clone https://gitlab.freedesktop.org/xorg/test/rendercheck --depth 1
|
||||
cd rendercheck
|
||||
meson build
|
||||
ninja -j${FDO_CI_CONCURRENT:-4} -C build install
|
||||
cd ..
|
||||
|
||||
rm -rf piglit/.git xts/.git piglit/tests/spec/ rendercheck/
|
||||
|
||||
echo '[xts]' > piglit/piglit.conf
|
||||
echo 'path=/root/xts' >> piglit/piglit.conf
|
||||
|
||||
find -name \*.a -o -name \*.o -o -name \*.c -o -name \*.h -o -name \*.la\* | xargs rm
|
||||
strip xts/xts5/*/.libs/*
|
||||
|
||||
# Running meson dist requires xkbcomp 1.4.1 or newer, but Debian buster has 1.4.0 only
|
||||
git clone https://gitlab.freedesktop.org/xorg/app/xkbcomp.git --depth 1 --branch=xkbcomp-1.4.1
|
||||
cd xkbcomp
|
||||
./autogen.sh --datarootdir=/usr/share
|
||||
make -j${FDO_CI_CONCURRENT:-4} install
|
||||
cd ..
|
||||
rm -rf xkbcomp
|
||||
|
||||
apt-get purge -y \
|
||||
$EPHEMERAL
|
||||
|
||||
apt-get autoremove -y --purge
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
|
||||
find build/ -regex ".*\.[1-9]$" -exec grep -E \
|
||||
@vendorversion@\|\
|
||||
@xorgversion@\|\
|
||||
@xservername@\|\
|
||||
@xconfigfile@\|\
|
||||
@projectroot@\|\
|
||||
@apploaddir@\|\
|
||||
@appmansuffix@\|\
|
||||
@drivermansuffix@\|\
|
||||
@adminmansuffix@\|\
|
||||
@libmansuffix@\|\
|
||||
@miscmansuffix@\|\
|
||||
@filemansuffix@\|\
|
||||
@logdir@\|\
|
||||
@datadir@\|\
|
||||
@mandir@\|\
|
||||
@sysconfdir@\|\
|
||||
@xconfigdir@\|\
|
||||
@xkbdir@\|\
|
||||
@XKB_DFLT_RULES@\|\
|
||||
@XKB_DFLT_MODEL@\|\
|
||||
@XKB_DFLT_LAYOUT@\|\
|
||||
@XKB_DFLT_VARIANT@\|\
|
||||
@XKB_DFLT_OPTIONS@\|\
|
||||
@bundle_id_prefix@\|\
|
||||
@modulepath@\|\
|
||||
@suid_wrapper_dir@\|\
|
||||
@default_font_path@\
|
||||
'{}' + && { echo "Missing manpage substitutions detected!" >&2 ; exit 1; }
|
||||
|
||||
exit 0
|
|
@ -138,9 +138,15 @@ ProcGEDispatch(ClientPtr client)
|
|||
static int _X_COLD
|
||||
SProcGEDispatch(ClientPtr client)
|
||||
{
|
||||
GEClientInfoPtr pGEClient = GEGetClient(client);
|
||||
|
||||
REQUEST(xGEReq);
|
||||
if (stuff->ReqType >= GENumberRequests)
|
||||
|
||||
if (pGEClient->major_version >= ARRAY_SIZE(version_requests))
|
||||
return BadRequest;
|
||||
if (stuff->ReqType > version_requests[pGEClient->major_version])
|
||||
return BadRequest;
|
||||
|
||||
return (*SProcGEVector[stuff->ReqType]) (client);
|
||||
}
|
||||
|
||||
|
|
|
@ -1051,7 +1051,7 @@ ScreenSaverSetAttributes(ClientPtr client)
|
|||
pVlist++;
|
||||
}
|
||||
if (pPriv->attr)
|
||||
FreeScreenAttr(pPriv->attr);
|
||||
FreeResource(pPriv->attr->resource, AttrType);
|
||||
pPriv->attr = pAttr;
|
||||
pAttr->resource = FakeClientID(client->index);
|
||||
if (!AddResource(pAttr->resource, AttrType, (void *) pAttr))
|
||||
|
@ -1351,8 +1351,8 @@ SProcScreenSaverSuspend(ClientPtr client)
|
|||
REQUEST(xScreenSaverSuspendReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->suspend);
|
||||
REQUEST_SIZE_MATCH(xScreenSaverSuspendReq);
|
||||
swapl(&stuff->suspend);
|
||||
return ProcScreenSaverSuspend(client);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid)
|
||||
|
||||
typedef struct {
|
||||
security_context_t octx;
|
||||
security_context_t dctx;
|
||||
char *octx;
|
||||
char *dctx;
|
||||
CARD32 octx_len;
|
||||
CARD32 dctx_len;
|
||||
CARD32 id;
|
||||
|
@ -48,10 +48,10 @@ typedef struct {
|
|||
* Extension Dispatch
|
||||
*/
|
||||
|
||||
static security_context_t
|
||||
static char *
|
||||
SELinuxCopyContext(char *ptr, unsigned len)
|
||||
{
|
||||
security_context_t copy = malloc(len + 1);
|
||||
char *copy = malloc(len + 1);
|
||||
|
||||
if (!copy)
|
||||
return NULL;
|
||||
|
@ -84,7 +84,7 @@ static int
|
|||
SELinuxSendContextReply(ClientPtr client, security_id_t sid)
|
||||
{
|
||||
SELinuxGetContextReply rep;
|
||||
security_context_t ctx = NULL;
|
||||
char *ctx = NULL;
|
||||
int len = 0;
|
||||
|
||||
if (sid) {
|
||||
|
@ -117,7 +117,7 @@ ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset)
|
|||
{
|
||||
PrivateRec **privPtr = &client->devPrivates;
|
||||
security_id_t *pSid;
|
||||
security_context_t ctx = NULL;
|
||||
char *ctx = NULL;
|
||||
char *ptr;
|
||||
int rc;
|
||||
|
||||
|
@ -165,7 +165,7 @@ ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset)
|
|||
static int
|
||||
ProcSELinuxSetDeviceContext(ClientPtr client)
|
||||
{
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
security_id_t sid;
|
||||
DeviceIntPtr dev;
|
||||
SELinuxSubjectRec *subj;
|
||||
|
|
|
@ -114,7 +114,7 @@ SELinuxLabelClient(ClientPtr client)
|
|||
int fd = XaceGetConnectionNumber(client);
|
||||
SELinuxSubjectRec *subj;
|
||||
SELinuxObjectRec *obj;
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
|
||||
subj = dixLookupPrivate(&client->devPrivates, subjectKey);
|
||||
obj = dixLookupPrivate(&client->devPrivates, objectKey);
|
||||
|
@ -169,7 +169,7 @@ SELinuxLabelInitial(void)
|
|||
XaceScreenAccessRec srec;
|
||||
SELinuxSubjectRec *subj;
|
||||
SELinuxObjectRec *obj;
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
void *unused;
|
||||
|
||||
/* Do the serverClient */
|
||||
|
@ -773,7 +773,7 @@ SELinuxResourceState(CallbackListPtr *pcbl, void *unused, void *calldata)
|
|||
subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey);
|
||||
|
||||
if (subj->sid) {
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
int rc = avc_sid_to_context_raw(subj->sid, &ctx);
|
||||
|
||||
if (rc < 0)
|
||||
|
@ -791,7 +791,7 @@ SELinuxResourceState(CallbackListPtr *pcbl, void *unused, void *calldata)
|
|||
obj = dixLookupPrivate(&pWin->devPrivates, objectKey);
|
||||
|
||||
if (obj->sid) {
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
int rc = avc_sid_to_context_raw(obj->sid, &ctx);
|
||||
|
||||
if (rc < 0)
|
||||
|
@ -847,7 +847,7 @@ void
|
|||
SELinuxFlaskInit(void)
|
||||
{
|
||||
struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *) 0 };
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
int ret = TRUE;
|
||||
|
||||
switch (selinuxEnforcingState) {
|
||||
|
|
|
@ -97,7 +97,7 @@ static int
|
|||
SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec * obj, int map, int polymap)
|
||||
{
|
||||
const char *name = NameForAtom(atom);
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
int rc = Success;
|
||||
|
||||
obj->poly = 1;
|
||||
|
@ -255,7 +255,7 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
|
|||
{
|
||||
const char *name = LookupEventName(type);
|
||||
security_id_t sid;
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
|
||||
type &= 127;
|
||||
|
||||
|
@ -291,7 +291,7 @@ SELinuxEventToSID(unsigned type, security_id_t sid_of_window,
|
|||
int
|
||||
SELinuxExtensionToSID(const char *name, security_id_t * sid_rtn)
|
||||
{
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
|
||||
/* Look in the mappings of extension names to contexts */
|
||||
if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) {
|
||||
|
@ -347,10 +347,10 @@ SELinuxTypeToClass(RESTYPE type)
|
|||
return (security_class_t) (unsigned long) tmp;
|
||||
}
|
||||
|
||||
security_context_t
|
||||
char *
|
||||
SELinuxDefaultClientLabel(void)
|
||||
{
|
||||
security_context_t ctx;
|
||||
char *ctx;
|
||||
|
||||
if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0)
|
||||
FatalError("SELinux: failed to look up remote-client context\n");
|
||||
|
|
|
@ -99,7 +99,7 @@ int
|
|||
|
||||
security_class_t SELinuxTypeToClass(RESTYPE type);
|
||||
|
||||
security_context_t SELinuxDefaultClientLabel(void);
|
||||
char *SELinuxDefaultClientLabel(void);
|
||||
|
||||
void
|
||||
SELinuxLabelInit(void);
|
||||
|
|
|
@ -502,10 +502,11 @@ XTestSwapFakeInput(ClientPtr client, xReq * req)
|
|||
|
||||
nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
|
||||
for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) {
|
||||
int evtype = ev->u.u.type & 0177;
|
||||
/* Swap event */
|
||||
proc = EventSwapVector[ev->u.u.type & 0177];
|
||||
proc = EventSwapVector[evtype];
|
||||
/* no swapping proc; invalid event type? */
|
||||
if (!proc || proc == NotImplemented) {
|
||||
if (!proc || proc == NotImplemented || evtype == GenericEvent) {
|
||||
client->errorValue = ev->u.u.type;
|
||||
return BadValue;
|
||||
}
|
||||
|
|
|
@ -811,8 +811,10 @@ XvdiSelectVideoNotify(ClientPtr client, DrawablePtr pDraw, BOOL onoff)
|
|||
tpn = pn;
|
||||
while (tpn) {
|
||||
if (tpn->client == client) {
|
||||
if (!onoff)
|
||||
if (!onoff) {
|
||||
tpn->client = NULL;
|
||||
FreeResource(tpn->id, XvRTVideoNotify);
|
||||
}
|
||||
return Success;
|
||||
}
|
||||
if (!tpn->client)
|
||||
|
|
|
@ -464,8 +464,11 @@ ProcXChangeFeedbackControl(ClientPtr client)
|
|||
break;
|
||||
case StringFeedbackClass:
|
||||
{
|
||||
xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]);
|
||||
xStringFeedbackCtl *f;
|
||||
|
||||
REQUEST_AT_LEAST_EXTRA_SIZE(xChangeFeedbackControlReq,
|
||||
sizeof(xStringFeedbackCtl));
|
||||
f = ((xStringFeedbackCtl *) &stuff[1]);
|
||||
if (client->swapped) {
|
||||
if (len < bytes_to_int32(sizeof(xStringFeedbackCtl)))
|
||||
return BadLength;
|
||||
|
|
278
Xi/exevents.c
278
Xi/exevents.c
|
@ -95,6 +95,7 @@ SOFTWARE.
|
|||
#include "exevents.h"
|
||||
#include "extnsionst.h"
|
||||
#include "exglobals.h"
|
||||
#include "eventstr.h"
|
||||
#include "dixevents.h" /* DeliverFocusedEvent */
|
||||
#include "dixgrabs.h" /* CreateGrab() */
|
||||
#include "scrnintstr.h"
|
||||
|
@ -168,6 +169,49 @@ IsTouchEvent(InternalEvent *event)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
Bool
|
||||
IsGestureEvent(InternalEvent *event)
|
||||
{
|
||||
switch (event->any.type) {
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool
|
||||
IsGestureBeginEvent(InternalEvent *event)
|
||||
{
|
||||
switch (event->any.type) {
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GestureSwipeBegin:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Bool
|
||||
IsGestureEndEvent(InternalEvent *event)
|
||||
{
|
||||
switch (event->any.type) {
|
||||
case ET_GesturePinchEnd:
|
||||
case ET_GestureSwipeEnd:
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the device matching the deviceid of the device set in the event, or
|
||||
* NULL if the event is not an XInput event.
|
||||
|
@ -575,8 +619,10 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
|
|||
memcpy(to->button->xkb_acts, from->button->xkb_acts,
|
||||
sizeof(XkbAction));
|
||||
}
|
||||
else
|
||||
else {
|
||||
free(to->button->xkb_acts);
|
||||
to->button->xkb_acts = NULL;
|
||||
}
|
||||
|
||||
memcpy(to->button->labels, from->button->labels,
|
||||
from->button->numButtons * sizeof(Atom));
|
||||
|
@ -647,6 +693,25 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
|
|||
/* Don't remove touch class if from->touch is non-existent. The to device
|
||||
* may have an active touch grab, so we need to keep the touch class record
|
||||
* around. */
|
||||
|
||||
if (from->gesture) {
|
||||
if (!to->gesture) {
|
||||
classes = to->unused_classes;
|
||||
to->gesture = classes->gesture;
|
||||
if (!to->gesture) {
|
||||
if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches))
|
||||
FatalError("[Xi] no memory for class shift.\n");
|
||||
}
|
||||
else
|
||||
classes->gesture = NULL;
|
||||
}
|
||||
|
||||
to->gesture->sourceid = from->gesture->sourceid;
|
||||
/* to->gesture->gesture is separate on the master, don't copy */
|
||||
}
|
||||
/* Don't remove gesture class if from->gesture is non-existent. The to device
|
||||
* may have an active gesture grab, so we need to keep the gesture class record
|
||||
* around. */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1292,21 +1357,13 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
|||
int rc;
|
||||
InputClients *iclients = NULL;
|
||||
*mask = NULL;
|
||||
*grab = NULL;
|
||||
|
||||
if (listener->type == TOUCH_LISTENER_GRAB ||
|
||||
listener->type == TOUCH_LISTENER_POINTER_GRAB) {
|
||||
*grab = listener->grab;
|
||||
|
||||
BUG_RETURN_VAL(!*grab, FALSE);
|
||||
}
|
||||
else if (ti->emulate_pointer && dev->deviceGrab.grab &&
|
||||
!dev->deviceGrab.fromPassiveGrab) {
|
||||
/* There may be an active pointer grab on the device */
|
||||
*grab = dev->deviceGrab.grab;
|
||||
}
|
||||
|
||||
if (*grab) {
|
||||
*client = rClient(*grab);
|
||||
*win = (*grab)->window;
|
||||
*mask = (*grab)->xi2mask;
|
||||
|
@ -1363,6 +1420,8 @@ RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
|||
/* if owner selected, oclients is NULL */
|
||||
*client = oclients ? rClient(oclients) : wClient(*win);
|
||||
}
|
||||
|
||||
*grab = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -1379,6 +1438,16 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
|||
int nevents;
|
||||
DeviceIntPtr kbd;
|
||||
|
||||
/* There may be a pointer grab on the device */
|
||||
if (!grab) {
|
||||
grab = dev->deviceGrab.grab;
|
||||
if (grab) {
|
||||
win = grab->window;
|
||||
xi2mask = grab->xi2mask;
|
||||
client = rClient(grab);
|
||||
}
|
||||
}
|
||||
|
||||
/* We don't deliver pointer events to non-owners */
|
||||
if (!TouchResourceIsOwner(ti, listener->listener))
|
||||
return !Success;
|
||||
|
@ -1457,7 +1526,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
|||
g = AllocGrab(devgrab);
|
||||
BUG_WARN(!g);
|
||||
|
||||
*dev->deviceGrab.sync.event = *ev;
|
||||
CopyPartialInternalEvent(dev->deviceGrab.sync.event, ev);
|
||||
|
||||
/* The listener array has a sequence of grabs and then one event
|
||||
* selection. Implicit grab activation occurs through delivering an
|
||||
|
@ -1676,6 +1745,72 @@ ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
|
|||
free(ev);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
IsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev)
|
||||
{
|
||||
GestureClassPtr g = dev->gesture;
|
||||
if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}.
|
||||
*
|
||||
* Due to having rather different delivery semantics (see the Xi 2.4 protocol
|
||||
* spec for more information), this implements its own grab and event-selection
|
||||
* delivery logic.
|
||||
*/
|
||||
void
|
||||
ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
|
||||
{
|
||||
GestureInfoPtr gi;
|
||||
DeviceIntPtr kbd;
|
||||
Bool deactivateGestureGrab = FALSE;
|
||||
Bool delivered = FALSE;
|
||||
|
||||
if (!dev->gesture)
|
||||
return;
|
||||
|
||||
if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev))
|
||||
return;
|
||||
|
||||
if (IsGestureBeginEvent(ev))
|
||||
gi = GestureBeginGesture(dev, ev);
|
||||
else
|
||||
gi = GestureFindActiveByEventType(dev, ev->any.type);
|
||||
|
||||
if (!gi) {
|
||||
/* This may happen if gesture is no longer active or was never started. */
|
||||
return;
|
||||
}
|
||||
|
||||
kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
|
||||
event_set_state_gesture(kbd, &ev->gesture_event);
|
||||
|
||||
if (IsGestureBeginEvent(ev))
|
||||
GestureSetupListener(dev, gi, ev);
|
||||
|
||||
if (IsGestureEndEvent(ev) &&
|
||||
dev->deviceGrab.grab &&
|
||||
dev->deviceGrab.fromPassiveGrab &&
|
||||
GrabIsGestureGrab(dev->deviceGrab.grab))
|
||||
deactivateGestureGrab = TRUE;
|
||||
|
||||
delivered = DeliverGestureEventToOwner(dev, gi, ev);
|
||||
|
||||
if (delivered && !deactivateGestureGrab &&
|
||||
(IsGestureBeginEvent(ev) || IsGestureEndEvent(ev)))
|
||||
FreezeThisEventIfNeededForSyncGrab(dev, ev);
|
||||
|
||||
if (IsGestureEndEvent(ev))
|
||||
GestureEndGesture(gi);
|
||||
|
||||
if (deactivateGestureGrab)
|
||||
(*dev->deviceGrab.DeactivateGrab) (dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process DeviceEvents and DeviceChangedEvents.
|
||||
*/
|
||||
|
@ -1768,7 +1903,7 @@ ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
|
|||
* nested) to clients. */
|
||||
if (event->source_type == EVENT_SOURCE_FOCUS)
|
||||
return;
|
||||
if (!grab && CheckDeviceGrabs(device, event, 0))
|
||||
if (!grab && CheckDeviceGrabs(device, ev, 0))
|
||||
return;
|
||||
break;
|
||||
case ET_KeyRelease:
|
||||
|
@ -1781,7 +1916,7 @@ ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
|
|||
if (b->map[key] == 0) /* there's no button 0 */
|
||||
return;
|
||||
event->detail.button = b->map[key];
|
||||
if (!grab && CheckDeviceGrabs(device, event, 0)) {
|
||||
if (!grab && CheckDeviceGrabs(device, ev, 0)) {
|
||||
/* if a passive grab was activated, the event has been sent
|
||||
* already */
|
||||
return;
|
||||
|
@ -1870,6 +2005,14 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
|
|||
case ET_BarrierLeave:
|
||||
ProcessBarrierEvent(ev, device);
|
||||
break;
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
ProcessGestureEvent(ev, device);
|
||||
break;
|
||||
default:
|
||||
ProcessDeviceEvent(ev, device);
|
||||
break;
|
||||
|
@ -2074,6 +2217,111 @@ DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to deliver a gesture event to the given client.
|
||||
*/
|
||||
static Bool
|
||||
DeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi,
|
||||
GrabPtr grab, WindowPtr win, InternalEvent *ev)
|
||||
{
|
||||
int err;
|
||||
xEvent *xi2;
|
||||
Mask filter;
|
||||
Window child = DeepestSpriteWin(&gi->sprite)->drawable.id;
|
||||
|
||||
/* If we fail here, we're going to leave a client hanging. */
|
||||
err = EventToXI2(ev, &xi2);
|
||||
if (err != Success)
|
||||
FatalError("[Xi] %s: XI2 conversion failed in %s"
|
||||
" (%d)\n", dev->name, __func__, err);
|
||||
|
||||
FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE);
|
||||
filter = GetEventFilter(dev, xi2);
|
||||
if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
|
||||
return FALSE;
|
||||
err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
|
||||
free(xi2);
|
||||
|
||||
/* Returning the value from TryClientEvents isn't useful, since all our
|
||||
* resource-gone cleanups will update the delivery list anyway. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a gesture event and a potential listener, retrieve info needed for processing the event.
|
||||
*
|
||||
* @param dev The device generating the gesture event.
|
||||
* @param ev The gesture event to process.
|
||||
* @param listener The gesture event listener that may receive the gesture event.
|
||||
* @param[out] client The client that should receive the gesture event.
|
||||
* @param[out] win The window to deliver the event on.
|
||||
* @param[out] grab The grab to deliver the event through, if any.
|
||||
* @return TRUE if an event should be delivered to the listener, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
static Bool
|
||||
RetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener,
|
||||
ClientPtr *client, WindowPtr *win, GrabPtr *grab)
|
||||
{
|
||||
int rc;
|
||||
int evtype;
|
||||
InputClients *iclients = NULL;
|
||||
*grab = NULL;
|
||||
|
||||
if (listener->type == GESTURE_LISTENER_GRAB ||
|
||||
listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) {
|
||||
*grab = listener->grab;
|
||||
|
||||
BUG_RETURN_VAL(!*grab, FALSE);
|
||||
|
||||
*client = rClient(*grab);
|
||||
*win = (*grab)->window;
|
||||
}
|
||||
else {
|
||||
rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type,
|
||||
serverClient, DixSendAccess);
|
||||
if (rc != Success)
|
||||
return FALSE;
|
||||
|
||||
/* note that we only will have XI2 listeners as
|
||||
listener->type == GESTURE_LISTENER_REGULAR */
|
||||
evtype = GetXI2Type(ev->any.type);
|
||||
|
||||
nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
|
||||
if (xi2mask_isset(iclients->xi2mask, dev, evtype))
|
||||
break;
|
||||
|
||||
BUG_RETURN_VAL(!iclients, FALSE);
|
||||
|
||||
*client = rClient(iclients);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delivers a gesture to the owner, if possible and needed. Returns whether
|
||||
* an event was delivered.
|
||||
*/
|
||||
Bool
|
||||
DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
|
||||
{
|
||||
GrabPtr grab = NULL;
|
||||
ClientPtr client;
|
||||
WindowPtr win;
|
||||
|
||||
if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab))
|
||||
return 0;
|
||||
|
||||
ev->gesture_event.deviceid = dev->id;
|
||||
|
||||
return DeliverOneGestureEvent(client, dev, gi, grab, win, ev);
|
||||
}
|
||||
|
||||
int
|
||||
InitProximityClassDeviceStruct(DeviceIntPtr dev)
|
||||
{
|
||||
|
@ -2379,8 +2627,8 @@ GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
|
|||
|
||||
/* Touch grab */
|
||||
int
|
||||
GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
|
||||
GrabParameters *param, GrabMask *mask)
|
||||
GrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
|
||||
int type, GrabParameters *param, GrabMask *mask)
|
||||
{
|
||||
WindowPtr pWin;
|
||||
GrabPtr grab;
|
||||
|
@ -2398,7 +2646,7 @@ GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
|
|||
return rc;
|
||||
|
||||
grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
|
||||
mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
|
||||
mask, param, type, 0, NullWindow, NullCursor);
|
||||
if (!grab)
|
||||
return BadAlloc;
|
||||
|
||||
|
|
80
Xi/extinit.c
80
Xi/extinit.c
|
@ -850,6 +850,74 @@ SBarrierEvent(xXIBarrierEvent * from,
|
|||
swapl(&to->eventid);
|
||||
}
|
||||
|
||||
static void
|
||||
SGesturePinchEvent(xXIGesturePinchEvent* from,
|
||||
xXIGesturePinchEvent* to)
|
||||
{
|
||||
*to = *from;
|
||||
|
||||
swaps(&to->sequenceNumber);
|
||||
swapl(&to->length);
|
||||
swaps(&to->evtype);
|
||||
swaps(&to->deviceid);
|
||||
swapl(&to->time);
|
||||
swapl(&to->detail);
|
||||
swapl(&to->root);
|
||||
swapl(&to->event);
|
||||
swapl(&to->child);
|
||||
swapl(&to->root_x);
|
||||
swapl(&to->root_y);
|
||||
swapl(&to->event_x);
|
||||
swapl(&to->event_y);
|
||||
|
||||
swapl(&to->delta_x);
|
||||
swapl(&to->delta_y);
|
||||
swapl(&to->delta_unaccel_x);
|
||||
swapl(&to->delta_unaccel_y);
|
||||
swapl(&to->scale);
|
||||
swapl(&to->delta_angle);
|
||||
swaps(&to->sourceid);
|
||||
|
||||
swapl(&to->mods.base_mods);
|
||||
swapl(&to->mods.latched_mods);
|
||||
swapl(&to->mods.locked_mods);
|
||||
swapl(&to->mods.effective_mods);
|
||||
swapl(&to->flags);
|
||||
}
|
||||
|
||||
static void
|
||||
SGestureSwipeEvent(xXIGestureSwipeEvent* from,
|
||||
xXIGestureSwipeEvent* to)
|
||||
{
|
||||
*to = *from;
|
||||
|
||||
swaps(&to->sequenceNumber);
|
||||
swapl(&to->length);
|
||||
swaps(&to->evtype);
|
||||
swaps(&to->deviceid);
|
||||
swapl(&to->time);
|
||||
swapl(&to->detail);
|
||||
swapl(&to->root);
|
||||
swapl(&to->event);
|
||||
swapl(&to->child);
|
||||
swapl(&to->root_x);
|
||||
swapl(&to->root_y);
|
||||
swapl(&to->event_x);
|
||||
swapl(&to->event_y);
|
||||
|
||||
swapl(&to->delta_x);
|
||||
swapl(&to->delta_y);
|
||||
swapl(&to->delta_unaccel_x);
|
||||
swapl(&to->delta_unaccel_y);
|
||||
swaps(&to->sourceid);
|
||||
|
||||
swapl(&to->mods.base_mods);
|
||||
swapl(&to->mods.latched_mods);
|
||||
swapl(&to->mods.locked_mods);
|
||||
swapl(&to->mods.effective_mods);
|
||||
swapl(&to->flags);
|
||||
}
|
||||
|
||||
/** Event swapping function for XI2 events. */
|
||||
void _X_COLD
|
||||
XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
|
||||
|
@ -901,6 +969,18 @@ XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
|
|||
SBarrierEvent((xXIBarrierEvent *) from,
|
||||
(xXIBarrierEvent *) to);
|
||||
break;
|
||||
case XI_GesturePinchBegin:
|
||||
case XI_GesturePinchUpdate:
|
||||
case XI_GesturePinchEnd:
|
||||
SGesturePinchEvent((xXIGesturePinchEvent*) from,
|
||||
(xXIGesturePinchEvent*) to);
|
||||
break;
|
||||
case XI_GestureSwipeBegin:
|
||||
case XI_GestureSwipeUpdate:
|
||||
case XI_GestureSwipeEnd:
|
||||
SGestureSwipeEvent((xXIGestureSwipeEvent*) from,
|
||||
(xXIGestureSwipeEvent*) to);
|
||||
break;
|
||||
default:
|
||||
ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
|
||||
break;
|
||||
|
|
|
@ -39,6 +39,6 @@
|
|||
int SProcXIChangeHierarchy(ClientPtr /* client */ );
|
||||
int ProcXIChangeHierarchy(ClientPtr /* client */ );
|
||||
|
||||
void XISendDeviceHierarchyEvent(int flags[]);
|
||||
void XISendDeviceHierarchyEvent(int flags[MAXDEVICES]);
|
||||
|
||||
#endif /* CHDEVHIER_H */
|
||||
|
|
|
@ -114,14 +114,18 @@ ProcXIPassiveGrabDevice(ClientPtr client)
|
|||
stuff->grab_type != XIGrabtypeKeycode &&
|
||||
stuff->grab_type != XIGrabtypeEnter &&
|
||||
stuff->grab_type != XIGrabtypeFocusIn &&
|
||||
stuff->grab_type != XIGrabtypeTouchBegin) {
|
||||
stuff->grab_type != XIGrabtypeTouchBegin &&
|
||||
stuff->grab_type != XIGrabtypeGesturePinchBegin &&
|
||||
stuff->grab_type != XIGrabtypeGestureSwipeBegin) {
|
||||
client->errorValue = stuff->grab_type;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
if ((stuff->grab_type == XIGrabtypeEnter ||
|
||||
stuff->grab_type == XIGrabtypeFocusIn ||
|
||||
stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) {
|
||||
stuff->grab_type == XIGrabtypeTouchBegin ||
|
||||
stuff->grab_type == XIGrabtypeGesturePinchBegin ||
|
||||
stuff->grab_type == XIGrabtypeGestureSwipeBegin) && stuff->detail != 0) {
|
||||
client->errorValue = stuff->detail;
|
||||
return BadValue;
|
||||
}
|
||||
|
@ -133,6 +137,12 @@ ProcXIPassiveGrabDevice(ClientPtr client)
|
|||
return BadValue;
|
||||
}
|
||||
|
||||
/* XI2 allows 32-bit keycodes but thanks to XKB we can never
|
||||
* implement this. Just return an error for all keycodes that
|
||||
* cannot work anyway, same for buttons > 255. */
|
||||
if (stuff->detail > 255)
|
||||
return XIAlreadyGrabbed;
|
||||
|
||||
if (XICheckInvalidMaskBits(client, (unsigned char *) &stuff[1],
|
||||
stuff->mask_len * 4) != Success)
|
||||
return BadValue;
|
||||
|
@ -203,21 +213,24 @@ ProcXIPassiveGrabDevice(ClientPtr client)
|
|||
¶m, XI2, &mask);
|
||||
break;
|
||||
case XIGrabtypeKeycode:
|
||||
/* XI2 allows 32-bit keycodes but thanks to XKB we can never
|
||||
* implement this. Just return an error for all keycodes that
|
||||
* cannot work anyway */
|
||||
if (stuff->detail > 255)
|
||||
status = XIAlreadyGrabbed;
|
||||
else
|
||||
status = GrabKey(client, dev, mod_dev, stuff->detail,
|
||||
¶m, XI2, &mask);
|
||||
status = GrabKey(client, dev, mod_dev, stuff->detail,
|
||||
¶m, XI2, &mask);
|
||||
break;
|
||||
case XIGrabtypeEnter:
|
||||
case XIGrabtypeFocusIn:
|
||||
status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask);
|
||||
break;
|
||||
case XIGrabtypeTouchBegin:
|
||||
status = GrabTouch(client, dev, mod_dev, ¶m, &mask);
|
||||
status = GrabTouchOrGesture(client, dev, mod_dev, XI_TouchBegin,
|
||||
¶m, &mask);
|
||||
break;
|
||||
case XIGrabtypeGesturePinchBegin:
|
||||
status = GrabTouchOrGesture(client, dev, mod_dev,
|
||||
XI_GesturePinchBegin, ¶m, &mask);
|
||||
break;
|
||||
case XIGrabtypeGestureSwipeBegin:
|
||||
status = GrabTouchOrGesture(client, dev, mod_dev,
|
||||
XI_GestureSwipeBegin, ¶m, &mask);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -307,7 +320,9 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
|
|||
stuff->grab_type != XIGrabtypeKeycode &&
|
||||
stuff->grab_type != XIGrabtypeEnter &&
|
||||
stuff->grab_type != XIGrabtypeFocusIn &&
|
||||
stuff->grab_type != XIGrabtypeTouchBegin) {
|
||||
stuff->grab_type != XIGrabtypeTouchBegin &&
|
||||
stuff->grab_type != XIGrabtypeGesturePinchBegin &&
|
||||
stuff->grab_type != XIGrabtypeGestureSwipeBegin) {
|
||||
client->errorValue = stuff->grab_type;
|
||||
return BadValue;
|
||||
}
|
||||
|
@ -319,6 +334,12 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
|
|||
return BadValue;
|
||||
}
|
||||
|
||||
/* We don't allow passive grabs for details > 255 anyway */
|
||||
if (stuff->detail > 255) {
|
||||
client->errorValue = stuff->detail;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
rc = dixLookupWindow(&win, stuff->grab_window, client, DixSetAttrAccess);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
@ -348,6 +369,12 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
|
|||
case XIGrabtypeTouchBegin:
|
||||
tempGrab->type = XI_TouchBegin;
|
||||
break;
|
||||
case XIGrabtypeGesturePinchBegin:
|
||||
tempGrab->type = XI_GesturePinchBegin;
|
||||
break;
|
||||
case XIGrabtypeGestureSwipeBegin:
|
||||
tempGrab->type = XI_GestureSwipeBegin;
|
||||
break;
|
||||
}
|
||||
tempGrab->grabtype = XI2;
|
||||
tempGrab->modifierDevice = mod_dev;
|
||||
|
|
|
@ -890,7 +890,7 @@ ProcXChangeDeviceProperty(ClientPtr client)
|
|||
REQUEST(xChangeDevicePropertyReq);
|
||||
DeviceIntPtr dev;
|
||||
unsigned long len;
|
||||
int totalSize;
|
||||
uint64_t totalSize;
|
||||
int rc;
|
||||
|
||||
REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
|
||||
|
@ -902,6 +902,8 @@ ProcXChangeDeviceProperty(ClientPtr client)
|
|||
|
||||
rc = check_change_property(client, stuff->property, stuff->type,
|
||||
stuff->format, stuff->mode, stuff->nUnits);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
len = stuff->nUnits;
|
||||
if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
|
||||
|
@ -1128,7 +1130,7 @@ ProcXIChangeProperty(ClientPtr client)
|
|||
{
|
||||
int rc;
|
||||
DeviceIntPtr dev;
|
||||
int totalSize;
|
||||
uint64_t totalSize;
|
||||
unsigned long len;
|
||||
|
||||
REQUEST(xXIChangePropertyReq);
|
||||
|
@ -1141,6 +1143,9 @@ ProcXIChangeProperty(ClientPtr client)
|
|||
|
||||
rc = check_change_property(client, stuff->property, stuff->type,
|
||||
stuff->format, stuff->mode, stuff->num_items);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
|
||||
len = stuff->num_items;
|
||||
if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
|
||||
return BadLength;
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#include "xace.h"
|
||||
#include "inpututils.h"
|
||||
|
||||
#include "exglobals.h"
|
||||
#include "privates.h"
|
||||
|
||||
#include "xiquerydevice.h"
|
||||
|
||||
static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
|
||||
|
@ -234,6 +237,9 @@ SizeDeviceClasses(DeviceIntPtr dev)
|
|||
if (dev->touch)
|
||||
len += sizeof(xXITouchInfo);
|
||||
|
||||
if (dev->gesture)
|
||||
len += sizeof(xXIGestureInfo);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
@ -464,6 +470,46 @@ SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
|
|||
swaps(&touch->sourceid);
|
||||
}
|
||||
|
||||
static Bool ShouldListGestureInfo(ClientPtr client)
|
||||
{
|
||||
/* libxcb 14.1 and older are not forwards-compatible with new device classes as it does not
|
||||
* properly ignore unknown device classes. Since breaking libxcb would break quite a lot of
|
||||
* applications, we instead report Gesture device class only if the client advertised support
|
||||
* for XI 2.4. Clients may still not work in cases when a client advertises XI 2.4 support
|
||||
* and then a completely separate module within the client uses broken libxcb to call
|
||||
* XIQueryDevice.
|
||||
*/
|
||||
XIClientPtr pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
|
||||
if (pXIClient->major_version) {
|
||||
return version_compare(pXIClient->major_version, pXIClient->minor_version, 2, 4) >= 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* List gesture information
|
||||
*
|
||||
* @return The number of bytes written into info.
|
||||
*/
|
||||
static int
|
||||
ListGestureInfo(DeviceIntPtr dev, xXIGestureInfo * gesture)
|
||||
{
|
||||
gesture->type = XIGestureClass;
|
||||
gesture->length = sizeof(xXIGestureInfo) >> 2;
|
||||
gesture->sourceid = dev->gesture->sourceid;
|
||||
gesture->num_touches = dev->gesture->max_touches;
|
||||
|
||||
return gesture->length << 2;
|
||||
}
|
||||
|
||||
static void
|
||||
SwapGestureInfo(DeviceIntPtr dev, xXIGestureInfo * gesture)
|
||||
{
|
||||
swaps(&gesture->type);
|
||||
swaps(&gesture->length);
|
||||
swaps(&gesture->sourceid);
|
||||
}
|
||||
|
||||
int
|
||||
GetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
|
||||
{
|
||||
|
@ -567,6 +613,13 @@ ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
|
|||
total_len += len;
|
||||
}
|
||||
|
||||
if (dev->gesture && ShouldListGestureInfo(client)) {
|
||||
(*nclasses)++;
|
||||
len = ListGestureInfo(dev, (xXIGestureInfo *) any);
|
||||
any += len;
|
||||
total_len += len;
|
||||
}
|
||||
|
||||
return total_len;
|
||||
}
|
||||
|
||||
|
@ -598,7 +651,9 @@ SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
|
|||
case XITouchClass:
|
||||
SwapTouchInfo(dev, (xXITouchInfo *) any);
|
||||
break;
|
||||
|
||||
case XIGestureClass:
|
||||
SwapGestureInfo(dev, (xXIGestureInfo *) any);
|
||||
break;
|
||||
}
|
||||
|
||||
any += len * 4;
|
||||
|
|
|
@ -226,8 +226,41 @@ ProcXISelectEvents(ClientPtr client)
|
|||
return BadValue;
|
||||
}
|
||||
|
||||
/* Only one client per window may select for touch events on the
|
||||
* same devices, including master devices.
|
||||
/* All three pinch gesture events must be selected at once */
|
||||
if ((BitIsOn(bits, XI_GesturePinchBegin) ||
|
||||
BitIsOn(bits, XI_GesturePinchUpdate) ||
|
||||
BitIsOn(bits, XI_GesturePinchEnd)) &&
|
||||
(!BitIsOn(bits, XI_GesturePinchBegin) ||
|
||||
!BitIsOn(bits, XI_GesturePinchUpdate) ||
|
||||
!BitIsOn(bits, XI_GesturePinchEnd))) {
|
||||
client->errorValue = XI_GesturePinchBegin;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
/* All three swipe gesture events must be selected at once. Note
|
||||
that the XI_GestureSwipeEnd is at index 32 which is on the next
|
||||
4-byte mask element */
|
||||
if (evmask->mask_len == 1 &&
|
||||
(BitIsOn(bits, XI_GestureSwipeBegin) ||
|
||||
BitIsOn(bits, XI_GestureSwipeUpdate)))
|
||||
{
|
||||
client->errorValue = XI_GestureSwipeBegin;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
if (evmask->mask_len >= 2 &&
|
||||
(BitIsOn(bits, XI_GestureSwipeBegin) ||
|
||||
BitIsOn(bits, XI_GestureSwipeUpdate) ||
|
||||
BitIsOn(bits, XI_GestureSwipeEnd)) &&
|
||||
(!BitIsOn(bits, XI_GestureSwipeBegin) ||
|
||||
!BitIsOn(bits, XI_GestureSwipeUpdate) ||
|
||||
!BitIsOn(bits, XI_GestureSwipeEnd))) {
|
||||
client->errorValue = XI_GestureSwipeBegin;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
/* Only one client per window may select for touch or gesture events
|
||||
* on the same devices, including master devices.
|
||||
* XXX: This breaks if a device goes from floating to attached. */
|
||||
if (BitIsOn(bits, XI_TouchBegin)) {
|
||||
rc = check_for_touch_selection_conflicts(client,
|
||||
|
@ -237,6 +270,22 @@ ProcXISelectEvents(ClientPtr client)
|
|||
if (rc != Success)
|
||||
return rc;
|
||||
}
|
||||
if (BitIsOn(bits, XI_GesturePinchBegin)) {
|
||||
rc = check_for_touch_selection_conflicts(client,
|
||||
win,
|
||||
evmask->deviceid,
|
||||
XI_GesturePinchBegin);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
}
|
||||
if (BitIsOn(bits, XI_GestureSwipeBegin)) {
|
||||
rc = check_for_touch_selection_conflicts(client,
|
||||
win,
|
||||
evmask->deviceid,
|
||||
XI_GestureSwipeBegin);
|
||||
if (rc != Success)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
if (XICheckInvalidMaskBits(client, (unsigned char *) &evmask[1],
|
||||
|
|
|
@ -561,7 +561,11 @@ static int _X_COLD
|
|||
SProcDamageDispatch(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDamageReq);
|
||||
if (stuff->damageReqType >= XDamageNumberRequests)
|
||||
DamageClientPtr pDamageClient = GetDamageClient(client);
|
||||
|
||||
if (pDamageClient->major_version >= ARRAY_SIZE(version_requests))
|
||||
return BadRequest;
|
||||
if (stuff->damageReqType > version_requests[pDamageClient->major_version])
|
||||
return BadRequest;
|
||||
return (*SProcDamageVector[stuff->damageReqType]) (client);
|
||||
}
|
||||
|
|
57
devbook.am
57
devbook.am
|
@ -1,57 +0,0 @@
|
|||
#
|
||||
# Generate output formats for a single DocBook/XML with/without chapters
|
||||
#
|
||||
# Variables set by the calling Makefile:
|
||||
# noinst_DATA: developers docs are not installed
|
||||
# docbook: the main DocBook/XML file, no chapters, appendix or image files
|
||||
# chapters: all files pulled in by an XInclude statement and images.
|
||||
#
|
||||
|
||||
#
|
||||
# This makefile is intended for Developers Documentation and is not installed.
|
||||
# Do not use for Users docs or Specs which need to be installed and require olink support
|
||||
# Refer to http://www.x.org/releases/X11R7.6/doc/xorg-docs/ReleaseNotes.html#id2584393
|
||||
# for an explanation on documents classification.
|
||||
#
|
||||
|
||||
# Developers documnetation is not installed
|
||||
noinst_DATA =
|
||||
|
||||
# DocBook/XML file with chapters, appendix and images it includes
|
||||
dist_noinst_DATA = $(docbook) $(chapters)
|
||||
|
||||
FILTER_XMLTO=$(SHELL) $(top_srcdir)/doc/filter-xmlto.sh $(XMLTO)
|
||||
|
||||
if HAVE_STYLESHEETS
|
||||
|
||||
XMLTO_HTML_FLAGS = \
|
||||
--searchpath "$(XORG_SGML_PATH)/X11" \
|
||||
--searchpath "$(abs_top_builddir)" \
|
||||
-x $(STYLESHEET_SRCDIR)/xorg-xhtml.xsl
|
||||
|
||||
noinst_DATA += $(docbook:.xml=.html)
|
||||
%.html: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(FILTER_XMLTO) $(XMLTO_HTML_FLAGS) xhtml-nochunks $<
|
||||
|
||||
if HAVE_XMLTO_TEXT
|
||||
noinst_DATA += $(docbook:.xml=.txt)
|
||||
%.txt: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(FILTER_XMLTO) $(XMLTO_HTML_FLAGS) txt $<
|
||||
endif HAVE_XMLTO_TEXT
|
||||
|
||||
if HAVE_FOP
|
||||
XMLTO_FO_FLAGS = \
|
||||
--searchpath "$(XORG_SGML_PATH)/X11" \
|
||||
--searchpath "$(abs_top_builddir)" \
|
||||
--stringparam img.src.path=$(abs_builddir)/ \
|
||||
-x $(STYLESHEET_SRCDIR)/xorg-fo.xsl
|
||||
|
||||
noinst_DATA += $(docbook:.xml=.pdf) $(docbook:.xml=.ps)
|
||||
%.pdf: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(FILTER_XMLTO) $(XMLTO_FO_FLAGS) --with-fop pdf $<
|
||||
%.ps: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(FILTER_XMLTO) $(XMLTO_FO_FLAGS) --with-fop ps $<
|
||||
endif HAVE_FOP
|
||||
endif HAVE_STYLESHEETS
|
||||
|
||||
CLEANFILES = $(noinst_DATA)
|
|
@ -458,6 +458,7 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
|
|||
return FALSE;
|
||||
|
||||
TouchEndPhysicallyActiveTouches(dev);
|
||||
GestureEndActiveGestures(dev);
|
||||
ReleaseButtonsAndKeys(dev);
|
||||
SyncRemoveDeviceIdleTime(dev->idle_counter);
|
||||
dev->idle_counter = NULL;
|
||||
|
@ -1670,6 +1671,32 @@ InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up gesture capabilities on @device.
|
||||
*
|
||||
* @max_touches The maximum number of simultaneous touches, or 0 for unlimited.
|
||||
*/
|
||||
Bool
|
||||
InitGestureClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches)
|
||||
{
|
||||
GestureClassPtr g;
|
||||
|
||||
BUG_RETURN_VAL(device == NULL, FALSE);
|
||||
BUG_RETURN_VAL(device->gesture != NULL, FALSE);
|
||||
|
||||
g = calloc(1, sizeof(*g));
|
||||
if (!g)
|
||||
return FALSE;
|
||||
|
||||
g->sourceid = device->id;
|
||||
g->max_touches = max_touches;
|
||||
GestureInitGestureInfo(&g->gesture);
|
||||
|
||||
device->gesture = g;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the given buffer contains elements between low (inclusive) and
|
||||
* high (inclusive) only.
|
||||
|
|
|
@ -128,6 +128,7 @@ int ProcInitialConnection();
|
|||
#include "inputstr.h"
|
||||
#include "xkbsrv.h"
|
||||
#include "client.h"
|
||||
#include "xfixesint.h"
|
||||
|
||||
#ifdef XSERVER_DTRACE
|
||||
#include "registry.h"
|
||||
|
@ -164,6 +165,7 @@ static int nextFreeClientID; /* always MIN free client ID */
|
|||
static int nClients; /* number of authorized clients */
|
||||
|
||||
CallbackListPtr ClientStateCallback;
|
||||
OsTimerPtr dispatchExceptionTimer;
|
||||
|
||||
/* dispatchException & isItTimeToYield must be declared volatile since they
|
||||
* are modified by signal handlers - otherwise optimizer may assume it doesn't
|
||||
|
@ -399,6 +401,58 @@ SmartScheduleClient(void)
|
|||
return best;
|
||||
}
|
||||
|
||||
static CARD32
|
||||
DispatchExceptionCallback(OsTimerPtr timer, CARD32 time, void *arg)
|
||||
{
|
||||
dispatchException |= dispatchExceptionAtReset;
|
||||
|
||||
/* Don't re-arm the timer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
CancelDispatchExceptionTimer(void)
|
||||
{
|
||||
TimerFree(dispatchExceptionTimer);
|
||||
dispatchExceptionTimer = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
SetDispatchExceptionTimer(void)
|
||||
{
|
||||
/* The timer delay is only for terminate, not reset */
|
||||
if (!(dispatchExceptionAtReset & DE_TERMINATE)) {
|
||||
dispatchException |= dispatchExceptionAtReset;
|
||||
return;
|
||||
}
|
||||
|
||||
CancelDispatchExceptionTimer();
|
||||
|
||||
if (terminateDelay == 0)
|
||||
dispatchException |= dispatchExceptionAtReset;
|
||||
else
|
||||
dispatchExceptionTimer = TimerSet(dispatchExceptionTimer,
|
||||
0, terminateDelay * 1000 /* msec */,
|
||||
&DispatchExceptionCallback,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static Bool
|
||||
ShouldDisconnectRemainingClients(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < currentMaxClients; i++) {
|
||||
if (clients[i]) {
|
||||
if (!XFixesShouldDisconnectClient(clients[i]))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* All remaining clients can be safely ignored */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
EnableLimitedSchedulingLatency(void)
|
||||
{
|
||||
|
@ -3419,6 +3473,7 @@ ProcNoOperation(ClientPtr client)
|
|||
*********************/
|
||||
|
||||
char dispatchExceptionAtReset = DE_RESET;
|
||||
int terminateDelay = 0;
|
||||
|
||||
void
|
||||
CloseDownClient(ClientPtr client)
|
||||
|
@ -3475,7 +3530,7 @@ CloseDownClient(ClientPtr client)
|
|||
|
||||
if (really_close_down) {
|
||||
if (client->clientState == ClientStateRunning && nClients == 0)
|
||||
dispatchException |= dispatchExceptionAtReset;
|
||||
SetDispatchExceptionTimer();
|
||||
|
||||
client->clientState = ClientStateGone;
|
||||
if (ClientStateCallback) {
|
||||
|
@ -3487,6 +3542,7 @@ CloseDownClient(ClientPtr client)
|
|||
CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
|
||||
}
|
||||
TouchListenerGone(client->clientAsMask);
|
||||
GestureListenerGone(client->clientAsMask);
|
||||
FreeClientResources(client);
|
||||
/* Disable client ID tracking. This must be done after
|
||||
* ClientStateCallback. */
|
||||
|
@ -3503,6 +3559,9 @@ CloseDownClient(ClientPtr client)
|
|||
while (!clients[currentMaxClients - 1])
|
||||
currentMaxClients--;
|
||||
}
|
||||
|
||||
if (ShouldDisconnectRemainingClients())
|
||||
SetDispatchExceptionTimer();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3704,6 +3763,7 @@ SendConnSetup(ClientPtr client, const char *reason)
|
|||
clientinfo.setup = (xConnSetup *) lConnectionInfo;
|
||||
CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
|
||||
}
|
||||
CancelDispatchExceptionTimer();
|
||||
return Success;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
*
|
||||
* For a full description of the focus in/out model from a window's
|
||||
* perspective, see
|
||||
* http://lists.freedesktop.org/archives/xorg/2008-December/041740.html
|
||||
* https://lists.freedesktop.org/archives/xorg/2008-December/041684.html
|
||||
*
|
||||
* Additional notes:
|
||||
* - The core protocol spec says that "In a LeaveNotify event, if a child of the
|
||||
|
|
|
@ -59,6 +59,8 @@ static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
|
|||
static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
|
||||
static int eventToBarrierEvent(BarrierEvent *ev, xEvent **xi);
|
||||
static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
|
||||
static int eventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi);
|
||||
static int eventToGesturePinchEvent(GestureEvent *ev, xEvent **xi);
|
||||
|
||||
/* Do not use, read comments below */
|
||||
BOOL EventIsKeyRepeat(xEvent *event);
|
||||
|
@ -163,6 +165,12 @@ EventToCore(InternalEvent *event, xEvent **core_out, int *count_out)
|
|||
case ET_TouchOwnership:
|
||||
case ET_BarrierHit:
|
||||
case ET_BarrierLeave:
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
ret = BadMatch;
|
||||
break;
|
||||
default:
|
||||
|
@ -221,6 +229,12 @@ EventToXI(InternalEvent *ev, xEvent **xi, int *count)
|
|||
case ET_TouchOwnership:
|
||||
case ET_BarrierHit:
|
||||
case ET_BarrierLeave:
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
*count = 0;
|
||||
*xi = NULL;
|
||||
return BadMatch;
|
||||
|
@ -285,6 +299,14 @@ EventToXI2(InternalEvent *ev, xEvent **xi)
|
|||
case ET_BarrierHit:
|
||||
case ET_BarrierLeave:
|
||||
return eventToBarrierEvent(&ev->barrier_event, xi);
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
return eventToGesturePinchEvent(&ev->gesture_event, xi);
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
return eventToGestureSwipeEvent(&ev->gesture_event, xi);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -816,6 +838,88 @@ eventToBarrierEvent(BarrierEvent *ev, xEvent **xi)
|
|||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
eventToGesturePinchEvent(GestureEvent *ev, xEvent **xi)
|
||||
{
|
||||
int len = sizeof(xXIGesturePinchEvent);
|
||||
xXIGesturePinchEvent *xpe;
|
||||
|
||||
*xi = calloc(1, len);
|
||||
xpe = (xXIGesturePinchEvent *) * xi;
|
||||
xpe->type = GenericEvent;
|
||||
xpe->extension = IReqCode;
|
||||
xpe->evtype = GetXI2Type(ev->type);
|
||||
xpe->time = ev->time;
|
||||
xpe->length = bytes_to_int32(len - sizeof(xEvent));
|
||||
xpe->detail = ev->num_touches;
|
||||
|
||||
xpe->root = ev->root;
|
||||
xpe->deviceid = ev->deviceid;
|
||||
xpe->sourceid = ev->sourceid;
|
||||
xpe->root_x = double_to_fp1616(ev->root_x);
|
||||
xpe->root_y = double_to_fp1616(ev->root_y);
|
||||
xpe->flags |= (ev->flags & GESTURE_CANCELLED) ? XIGesturePinchEventCancelled : 0;
|
||||
|
||||
xpe->delta_x = double_to_fp1616(ev->delta_x);
|
||||
xpe->delta_y = double_to_fp1616(ev->delta_y);
|
||||
xpe->delta_unaccel_x = double_to_fp1616(ev->delta_unaccel_x);
|
||||
xpe->delta_unaccel_y = double_to_fp1616(ev->delta_unaccel_y);
|
||||
xpe->scale = double_to_fp1616(ev->scale);
|
||||
xpe->delta_angle = double_to_fp1616(ev->delta_angle);
|
||||
|
||||
xpe->mods.base_mods = ev->mods.base;
|
||||
xpe->mods.latched_mods = ev->mods.latched;
|
||||
xpe->mods.locked_mods = ev->mods.locked;
|
||||
xpe->mods.effective_mods = ev->mods.effective;
|
||||
|
||||
xpe->group.base_group = ev->group.base;
|
||||
xpe->group.latched_group = ev->group.latched;
|
||||
xpe->group.locked_group = ev->group.locked;
|
||||
xpe->group.effective_group = ev->group.effective;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
int
|
||||
eventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi)
|
||||
{
|
||||
int len = sizeof(xXIGestureSwipeEvent);
|
||||
xXIGestureSwipeEvent *xde;
|
||||
|
||||
*xi = calloc(1, len);
|
||||
xde = (xXIGestureSwipeEvent *) * xi;
|
||||
xde->type = GenericEvent;
|
||||
xde->extension = IReqCode;
|
||||
xde->evtype = GetXI2Type(ev->type);
|
||||
xde->time = ev->time;
|
||||
xde->length = bytes_to_int32(len - sizeof(xEvent));
|
||||
xde->detail = ev->num_touches;
|
||||
|
||||
xde->root = ev->root;
|
||||
xde->deviceid = ev->deviceid;
|
||||
xde->sourceid = ev->sourceid;
|
||||
xde->root_x = double_to_fp1616(ev->root_x);
|
||||
xde->root_y = double_to_fp1616(ev->root_y);
|
||||
xde->flags |= (ev->flags & GESTURE_CANCELLED) ? XIGestureSwipeEventCancelled : 0;
|
||||
|
||||
xde->delta_x = double_to_fp1616(ev->delta_x);
|
||||
xde->delta_y = double_to_fp1616(ev->delta_y);
|
||||
xde->delta_unaccel_x = double_to_fp1616(ev->delta_unaccel_x);
|
||||
xde->delta_unaccel_y = double_to_fp1616(ev->delta_unaccel_y);
|
||||
|
||||
xde->mods.base_mods = ev->mods.base;
|
||||
xde->mods.latched_mods = ev->mods.latched;
|
||||
xde->mods.locked_mods = ev->mods.locked;
|
||||
xde->mods.effective_mods = ev->mods.effective;
|
||||
|
||||
xde->group.base_group = ev->group.base;
|
||||
xde->group.latched_group = ev->group.latched;
|
||||
xde->group.locked_group = ev->group.locked;
|
||||
xde->group.effective_group = ev->group.effective;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the corresponding core type for the given event or 0 if no core
|
||||
* equivalent exists.
|
||||
|
@ -969,8 +1073,68 @@ GetXI2Type(enum EventType type)
|
|||
case ET_BarrierLeave:
|
||||
xi2type = XI_BarrierLeave;
|
||||
break;
|
||||
case ET_GesturePinchBegin:
|
||||
xi2type = XI_GesturePinchBegin;
|
||||
break;
|
||||
case ET_GesturePinchUpdate:
|
||||
xi2type = XI_GesturePinchUpdate;
|
||||
break;
|
||||
case ET_GesturePinchEnd:
|
||||
xi2type = XI_GesturePinchEnd;
|
||||
break;
|
||||
case ET_GestureSwipeBegin:
|
||||
xi2type = XI_GestureSwipeBegin;
|
||||
break;
|
||||
case ET_GestureSwipeUpdate:
|
||||
xi2type = XI_GestureSwipeUpdate;
|
||||
break;
|
||||
case ET_GestureSwipeEnd:
|
||||
xi2type = XI_GestureSwipeEnd;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return xi2type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a gesture type to corresponding Gesture{Pinch,Swipe}Begin.
|
||||
* Returns 0 if the input type is not a gesture.
|
||||
*/
|
||||
enum EventType
|
||||
GestureTypeToBegin(enum EventType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
return ET_GesturePinchBegin;
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
return ET_GestureSwipeBegin;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a gesture type to corresponding Gesture{Pinch,Swipe}End.
|
||||
* Returns 0 if the input type is not a gesture.
|
||||
*/
|
||||
enum EventType
|
||||
GestureTypeToEnd(enum EventType type)
|
||||
{
|
||||
switch (type) {
|
||||
case ET_GesturePinchBegin:
|
||||
case ET_GesturePinchUpdate:
|
||||
case ET_GesturePinchEnd:
|
||||
return ET_GesturePinchEnd;
|
||||
case ET_GestureSwipeBegin:
|
||||
case ET_GestureSwipeUpdate:
|
||||
case ET_GestureSwipeEnd:
|
||||
return ET_GestureSwipeEnd;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
207
dix/events.c
207
dix/events.c
|
@ -467,6 +467,20 @@ WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
|
|||
return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* When processing events we operate on InternalEvent pointers. They may actually refer to a
|
||||
* an instance of DeviceEvent, GestureEvent or any other event that comprises the InternalEvent
|
||||
* union. This works well in practice because we always look into event type before doing anything,
|
||||
* except in the case of copying the event. Any copying of InternalEvent should use this function
|
||||
* instead of doing *dst_event = *src_event whenever it's not clear whether source event actually
|
||||
* points to full InternalEvent instance.
|
||||
*/
|
||||
void
|
||||
CopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event)
|
||||
{
|
||||
memcpy(dst_event, src_event, src_event->any.length);
|
||||
}
|
||||
|
||||
Mask
|
||||
GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
|
||||
{
|
||||
|
@ -1191,7 +1205,7 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
|
|||
}
|
||||
}
|
||||
|
||||
eventlen = event->length;
|
||||
eventlen = sizeof(InternalEvent);
|
||||
|
||||
qe = malloc(sizeof(QdEventRec) + eventlen);
|
||||
if (!qe)
|
||||
|
@ -1201,7 +1215,7 @@ EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
|
|||
qe->pScreen = pSprite->hotPhys.pScreen;
|
||||
qe->months = currentTime.months;
|
||||
qe->event = (InternalEvent *) (qe + 1);
|
||||
memcpy(qe->event, event, eventlen);
|
||||
CopyPartialInternalEvent(qe->event, (InternalEvent *)event);
|
||||
xorg_list_append(&qe->next, &syncEvents.pending);
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1333,7 @@ ComputeFreezes(void)
|
|||
|
||||
syncEvents.replayDev = (DeviceIntPtr) NULL;
|
||||
|
||||
if (!CheckDeviceGrabs(replayDev, &event->device_event,
|
||||
if (!CheckDeviceGrabs(replayDev, event,
|
||||
syncEvents.replayWin)) {
|
||||
if (IsTouchEvent(event)) {
|
||||
TouchPointInfoPtr ti =
|
||||
|
@ -1328,6 +1342,15 @@ ComputeFreezes(void)
|
|||
|
||||
TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
|
||||
}
|
||||
else if (IsGestureEvent(event)) {
|
||||
GestureInfoPtr gi =
|
||||
GestureFindActiveByEventType(replayDev, event->any.type);
|
||||
if (gi) {
|
||||
GestureEmitGestureEndToOwner(replayDev, gi);
|
||||
GestureEndGesture(gi);
|
||||
}
|
||||
ProcessGestureEvent(event, replayDev);
|
||||
}
|
||||
else {
|
||||
WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite,
|
||||
event->device_event.root_x,
|
||||
|
@ -1480,16 +1503,28 @@ UpdateTouchesForGrab(DeviceIntPtr mouse)
|
|||
|
||||
if (ti->active &&
|
||||
CLIENT_BITS(listener->listener) == grab->resource) {
|
||||
if (grab->grabtype == CORE || grab->grabtype == XI ||
|
||||
!xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) {
|
||||
|
||||
if (listener->type == TOUCH_LISTENER_REGULAR &&
|
||||
listener->state != TOUCH_LISTENER_AWAITING_BEGIN &&
|
||||
listener->state != TOUCH_LISTENER_HAS_END) {
|
||||
/* if the listener already got any events relating to the touch, we must send
|
||||
a touch end because the grab overrides the previous listener and won't
|
||||
itself send any touch events.
|
||||
*/
|
||||
TouchEmitTouchEnd(mouse, ti, 0, listener->listener);
|
||||
}
|
||||
listener->type = TOUCH_LISTENER_POINTER_GRAB;
|
||||
} else {
|
||||
listener->type = TOUCH_LISTENER_GRAB;
|
||||
}
|
||||
|
||||
listener->listener = grab->resource;
|
||||
listener->level = grab->grabtype;
|
||||
listener->state = TOUCH_LISTENER_IS_OWNER;
|
||||
listener->window = grab->window;
|
||||
listener->state = TOUCH_LISTENER_IS_OWNER;
|
||||
|
||||
if (grab->grabtype == CORE || grab->grabtype == XI ||
|
||||
!xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
|
||||
listener->type = TOUCH_LISTENER_POINTER_GRAB;
|
||||
else
|
||||
listener->type = TOUCH_LISTENER_GRAB;
|
||||
if (listener->grab)
|
||||
FreeGrab(listener->grab);
|
||||
listener->grab = AllocGrab(grab);
|
||||
|
@ -1497,6 +1532,46 @@ UpdateTouchesForGrab(DeviceIntPtr mouse)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update gesture records when an explicit grab is activated. Any gestures owned
|
||||
* by the grabbing client are updated so the listener state reflects the new
|
||||
* grab.
|
||||
*/
|
||||
static void
|
||||
UpdateGesturesForGrab(DeviceIntPtr mouse)
|
||||
{
|
||||
if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab)
|
||||
return;
|
||||
|
||||
GestureInfoPtr gi = &mouse->gesture->gesture;
|
||||
GestureListener *listener = &gi->listener;
|
||||
GrabPtr grab = mouse->deviceGrab.grab;
|
||||
|
||||
if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) {
|
||||
if (grab->grabtype == CORE || grab->grabtype == XI ||
|
||||
!xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) {
|
||||
|
||||
if (listener->type == GESTURE_LISTENER_REGULAR) {
|
||||
/* if the listener already got any events relating to the gesture, we must send
|
||||
a gesture end because the grab overrides the previous listener and won't
|
||||
itself send any gesture events.
|
||||
*/
|
||||
GestureEmitGestureEndToOwner(mouse, gi);
|
||||
}
|
||||
listener->type = GESTURE_LISTENER_NONGESTURE_GRAB;
|
||||
} else {
|
||||
listener->type = GESTURE_LISTENER_GRAB;
|
||||
}
|
||||
|
||||
listener->listener = grab->resource;
|
||||
listener->window = grab->window;
|
||||
|
||||
if (listener->grab)
|
||||
FreeGrab(listener->grab);
|
||||
listener->grab = AllocGrab(grab);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate a pointer grab on the given device. A pointer grab will cause all
|
||||
* core pointer events of this device to be delivered to the grabbing client only.
|
||||
|
@ -1547,6 +1622,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
|
|||
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
|
||||
PostNewCursor(mouse);
|
||||
UpdateTouchesForGrab(mouse);
|
||||
UpdateGesturesForGrab(mouse);
|
||||
CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
|
||||
(Bool) grab->keyboardMode);
|
||||
if (oldgrab)
|
||||
|
@ -1602,6 +1678,16 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
|
|||
if (dev->deviceGrab.sync.other == grab)
|
||||
dev->deviceGrab.sync.other = NullGrab;
|
||||
}
|
||||
|
||||
/* in case of explicit gesture grab, send end event to the grab client */
|
||||
if (!wasPassive && mouse->gesture) {
|
||||
GestureInfoPtr gi = &mouse->gesture->gesture;
|
||||
if (gi->active && GestureResourceIsOwner(gi, grab_resource)) {
|
||||
GestureEmitGestureEndToOwner(mouse, gi);
|
||||
GestureEndGesture(gi);
|
||||
}
|
||||
}
|
||||
|
||||
DoEnterLeaveEvents(mouse, mouse->id, grab->window,
|
||||
mouse->spriteInfo->sprite->win, NotifyUngrab);
|
||||
if (grab->confineTo)
|
||||
|
@ -2533,6 +2619,44 @@ FixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype,
|
|||
(pSprite->hot.pScreen == pWin->drawable.pScreen);
|
||||
}
|
||||
|
||||
static void
|
||||
FixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event,
|
||||
WindowPtr pWin, Window child)
|
||||
{
|
||||
event->root = RootWindow(pSprite)->drawable.id;
|
||||
event->event = pWin->drawable.id;
|
||||
|
||||
if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
|
||||
event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
|
||||
event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
|
||||
event->child = child;
|
||||
}
|
||||
else {
|
||||
event->event_x = 0;
|
||||
event->event_y = 0;
|
||||
event->child = None;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
FixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event,
|
||||
WindowPtr pWin, Window child)
|
||||
{
|
||||
event->root = RootWindow(pSprite)->drawable.id;
|
||||
event->event = pWin->drawable.id;
|
||||
|
||||
if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
|
||||
event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
|
||||
event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
|
||||
event->child = child;
|
||||
}
|
||||
else {
|
||||
event->event_x = 0;
|
||||
event->event_y = 0;
|
||||
event->child = None;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust event fields to comply with the window properties.
|
||||
*
|
||||
|
@ -2566,6 +2690,18 @@ FixUpEventFromWindow(SpritePtr pSprite,
|
|||
case XI_BarrierHit:
|
||||
case XI_BarrierLeave:
|
||||
return;
|
||||
case XI_GesturePinchBegin:
|
||||
case XI_GesturePinchUpdate:
|
||||
case XI_GesturePinchEnd:
|
||||
FixUpXI2PinchEventFromWindow(pSprite,
|
||||
(xXIGesturePinchEvent*) xE, pWin, child);
|
||||
break;
|
||||
case XI_GestureSwipeBegin:
|
||||
case XI_GestureSwipeUpdate:
|
||||
case XI_GestureSwipeEnd:
|
||||
FixUpXI2SwipeEventFromWindow(pSprite,
|
||||
(xXIGestureSwipeEvent*) xE, pWin, child);
|
||||
break;
|
||||
default:
|
||||
FixUpXI2DeviceEventFromWindow(pSprite, evtype,
|
||||
(xXIDeviceEvent*) xE, pWin, child);
|
||||
|
@ -2905,7 +3041,7 @@ BOOL
|
|||
ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
DeviceEvent event;
|
||||
InternalEvent event;
|
||||
|
||||
if (dev->deviceGrab.grab) {
|
||||
if (!dev->deviceGrab.fromPassiveGrab ||
|
||||
|
@ -2920,16 +3056,16 @@ ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
|
|||
if (win == NoneWin || win == PointerRootWin)
|
||||
return FALSE;
|
||||
|
||||
event = (DeviceEvent) {
|
||||
.header = ET_Internal,
|
||||
.type = ET_FocusIn,
|
||||
.length = sizeof(DeviceEvent),
|
||||
.time = GetTimeInMillis(),
|
||||
.deviceid = dev->id,
|
||||
.sourceid = dev->id,
|
||||
.detail.button = 0
|
||||
event = (InternalEvent) {
|
||||
.device_event.header = ET_Internal,
|
||||
.device_event.type = ET_FocusIn,
|
||||
.device_event.length = sizeof(DeviceEvent),
|
||||
.device_event.time = GetTimeInMillis(),
|
||||
.device_event.deviceid = dev->id,
|
||||
.device_event.sourceid = dev->id,
|
||||
.device_event.detail.button = 0
|
||||
};
|
||||
rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
|
||||
rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
|
||||
TRUE) != NULL);
|
||||
if (rc)
|
||||
DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
|
||||
|
@ -2946,7 +3082,7 @@ static BOOL
|
|||
ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
DeviceEvent event;
|
||||
InternalEvent event;
|
||||
|
||||
if (dev->deviceGrab.grab) {
|
||||
if (!dev->deviceGrab.fromPassiveGrab ||
|
||||
|
@ -2958,16 +3094,16 @@ ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
|
|||
(*dev->deviceGrab.DeactivateGrab) (dev);
|
||||
}
|
||||
|
||||
event = (DeviceEvent) {
|
||||
.header = ET_Internal,
|
||||
.type = ET_Enter,
|
||||
.length = sizeof(DeviceEvent),
|
||||
.time = GetTimeInMillis(),
|
||||
.deviceid = dev->id,
|
||||
.sourceid = dev->id,
|
||||
.detail.button = 0
|
||||
event = (InternalEvent) {
|
||||
.device_event.header = ET_Internal,
|
||||
.device_event.type = ET_Enter,
|
||||
.device_event.length = sizeof(DeviceEvent),
|
||||
.device_event.time = GetTimeInMillis(),
|
||||
.device_event.deviceid = dev->id,
|
||||
.device_event.sourceid = dev->id,
|
||||
.device_event.detail.button = 0
|
||||
};
|
||||
rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
|
||||
rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE,
|
||||
TRUE) != NULL);
|
||||
if (rc)
|
||||
DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
|
||||
|
@ -3751,7 +3887,7 @@ void ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab,
|
|||
|
||||
if (grabinfo->sync.state == FROZEN_NO_EVENT)
|
||||
grabinfo->sync.state = FROZEN_WITH_EVENT;
|
||||
*grabinfo->sync.event = *real_event;
|
||||
CopyPartialInternalEvent(grabinfo->sync.event, real_event);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
|
@ -4019,14 +4155,15 @@ CheckPassiveGrabsOnWindow(WindowPtr pWin,
|
|||
*/
|
||||
|
||||
Bool
|
||||
CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
|
||||
CheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor)
|
||||
{
|
||||
int i;
|
||||
WindowPtr pWin = NULL;
|
||||
FocusClassPtr focus =
|
||||
IsPointerEvent((InternalEvent *) event) ? NULL : device->focus;
|
||||
IsPointerEvent(ievent) ? NULL : device->focus;
|
||||
BOOL sendCore = (IsMaster(device) && device->coreEvents);
|
||||
Bool ret = FALSE;
|
||||
DeviceEvent *event = &ievent->device_event;
|
||||
|
||||
if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
|
||||
return FALSE;
|
||||
|
@ -4049,7 +4186,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
|
|||
if (focus) {
|
||||
for (; i < focus->traceGood; i++) {
|
||||
pWin = focus->trace[i];
|
||||
if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
|
||||
if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
|
||||
sendCore, TRUE)) {
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
|
@ -4064,7 +4201,7 @@ CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
|
|||
|
||||
for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
|
||||
pWin = device->spriteInfo->sprite->spriteTrace[i];
|
||||
if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
|
||||
if (CheckPassiveGrabsOnWindow(pWin, device, ievent,
|
||||
sendCore, TRUE)) {
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
|
@ -4332,7 +4469,7 @@ FreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event)
|
|||
case FREEZE_NEXT_EVENT:
|
||||
grabinfo->sync.state = FROZEN_WITH_EVENT;
|
||||
FreezeThaw(thisDev, TRUE);
|
||||
*grabinfo->sync.event = *event;
|
||||
CopyPartialInternalEvent(grabinfo->sync.event, event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
* Copyright © 2011 Collabra Ltd.
|
||||
* Copyright © 2011 Red Hat, Inc.
|
||||
* Copyright © 2020 Povilas Kanapickas <povilas@radix.lt>
|
||||
*
|
||||
* 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 "inputstr.h"
|
||||
#include "scrnintstr.h"
|
||||
#include "dixgrabs.h"
|
||||
|
||||
#include "eventstr.h"
|
||||
#include "exevents.h"
|
||||
#include "exglobals.h"
|
||||
#include "inpututils.h"
|
||||
#include "eventconvert.h"
|
||||
#include "windowstr.h"
|
||||
#include "mi.h"
|
||||
|
||||
#define GESTURE_HISTORY_SIZE 100
|
||||
|
||||
Bool
|
||||
GestureInitGestureInfo(GestureInfoPtr gi)
|
||||
{
|
||||
memset(gi, 0, sizeof(*gi));
|
||||
|
||||
gi->sprite.spriteTrace = calloc(32, sizeof(*gi->sprite.spriteTrace));
|
||||
if (!gi->sprite.spriteTrace) {
|
||||
return FALSE;
|
||||
}
|
||||
gi->sprite.spriteTraceSize = 32;
|
||||
gi->sprite.spriteTrace[0] = screenInfo.screens[0]->root;
|
||||
gi->sprite.hot.pScreen = screenInfo.screens[0];
|
||||
gi->sprite.hotPhys.pScreen = screenInfo.screens[0];
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an event type returns the associated gesture event info.
|
||||
*/
|
||||
GestureInfoPtr
|
||||
GestureFindActiveByEventType(DeviceIntPtr dev, int type)
|
||||
{
|
||||
GestureClassPtr g = dev->gesture;
|
||||
enum EventType type_to_expect = GestureTypeToBegin(type);
|
||||
|
||||
if (!g || type_to_expect == 0 || !g->gesture.active ||
|
||||
g->gesture.type != type_to_expect) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &g->gesture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up gesture info for a new gesture. Returns NULL on failure.
|
||||
*/
|
||||
GestureInfoPtr
|
||||
GestureBeginGesture(DeviceIntPtr dev, InternalEvent *ev)
|
||||
{
|
||||
GestureClassPtr g = dev->gesture;
|
||||
enum EventType gesture_type = GestureTypeToBegin(ev->any.type);
|
||||
|
||||
/* Note that we ignore begin events when an existing gesture is active */
|
||||
if (!g || gesture_type == 0 || g->gesture.active)
|
||||
return NULL;
|
||||
|
||||
g->gesture.type = gesture_type;
|
||||
|
||||
if (!GestureBuildSprite(dev, &g->gesture))
|
||||
return NULL;
|
||||
|
||||
g->gesture.active = TRUE;
|
||||
g->gesture.num_touches = ev->gesture_event.num_touches;
|
||||
g->gesture.sourceid = ev->gesture_event.sourceid;
|
||||
g->gesture.has_listener = FALSE;
|
||||
return &g->gesture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases a gesture: this must only be called after all events
|
||||
* related to that gesture have been sent and finalised.
|
||||
*/
|
||||
void
|
||||
GestureEndGesture(GestureInfoPtr gi)
|
||||
{
|
||||
if (gi->has_listener) {
|
||||
if (gi->listener.grab) {
|
||||
FreeGrab(gi->listener.grab);
|
||||
gi->listener.grab = NULL;
|
||||
}
|
||||
gi->listener.listener = 0;
|
||||
gi->has_listener = FALSE;
|
||||
}
|
||||
|
||||
gi->active = FALSE;
|
||||
gi->num_touches = 0;
|
||||
gi->sprite.spriteTraceGood = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure a window trace is present in gi->sprite, constructing one for
|
||||
* Gesture{Pinch,Swipe}Begin events.
|
||||
*/
|
||||
Bool
|
||||
GestureBuildSprite(DeviceIntPtr sourcedev, GestureInfoPtr gi)
|
||||
{
|
||||
SpritePtr sprite = &gi->sprite;
|
||||
|
||||
if (!sourcedev->spriteInfo->sprite)
|
||||
return FALSE;
|
||||
|
||||
if (!CopySprite(sourcedev->spriteInfo->sprite, sprite))
|
||||
return FALSE;
|
||||
|
||||
if (sprite->spriteTraceGood <= 0)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns TRUE if the specified grab or selection is the current owner of
|
||||
* the gesture sequence.
|
||||
*/
|
||||
Bool
|
||||
GestureResourceIsOwner(GestureInfoPtr gi, XID resource)
|
||||
{
|
||||
return (gi->listener.listener == resource);
|
||||
}
|
||||
|
||||
void
|
||||
GestureAddListener(GestureInfoPtr gi, XID resource, int resource_type,
|
||||
enum GestureListenerType type, WindowPtr window, const GrabPtr grab)
|
||||
{
|
||||
GrabPtr g = NULL;
|
||||
|
||||
BUG_RETURN(gi->has_listener);
|
||||
|
||||
/* We need a copy of the grab, not the grab itself since that may be deleted by
|
||||
* a UngrabButton request and leaves us with a dangling pointer */
|
||||
if (grab)
|
||||
g = AllocGrab(grab);
|
||||
|
||||
gi->listener.listener = resource;
|
||||
gi->listener.resource_type = resource_type;
|
||||
gi->listener.type = type;
|
||||
gi->listener.window = window;
|
||||
gi->listener.grab = g;
|
||||
gi->has_listener = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
GestureAddGrabListener(DeviceIntPtr dev, GestureInfoPtr gi, GrabPtr grab)
|
||||
{
|
||||
enum GestureListenerType type;
|
||||
|
||||
/* FIXME: owner_events */
|
||||
|
||||
if (grab->grabtype == XI2) {
|
||||
if (xi2mask_isset(grab->xi2mask, dev, XI_GesturePinchBegin) ||
|
||||
xi2mask_isset(grab->xi2mask, dev, XI_GestureSwipeBegin)) {
|
||||
type = GESTURE_LISTENER_GRAB;
|
||||
} else
|
||||
type = GESTURE_LISTENER_NONGESTURE_GRAB;
|
||||
}
|
||||
else if (grab->grabtype == XI || grab->grabtype == CORE) {
|
||||
type = GESTURE_LISTENER_NONGESTURE_GRAB;
|
||||
}
|
||||
else {
|
||||
BUG_RETURN_MSG(1, "Unsupported grab type\n");
|
||||
}
|
||||
|
||||
/* grab listeners are always RT_NONE since we keep the grab pointer */
|
||||
GestureAddListener(gi, grab->resource, RT_NONE, type, grab->window, grab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add one listener if there is a grab on the given window.
|
||||
*/
|
||||
static void
|
||||
GestureAddPassiveGrabListener(DeviceIntPtr dev, GestureInfoPtr gi, WindowPtr win, InternalEvent *ev)
|
||||
{
|
||||
Bool activate = FALSE;
|
||||
Bool check_core = FALSE;
|
||||
|
||||
GrabPtr grab = CheckPassiveGrabsOnWindow(win, dev, ev, check_core,
|
||||
activate);
|
||||
if (!grab)
|
||||
return;
|
||||
|
||||
/* We'll deliver later in gesture-specific code */
|
||||
ActivateGrabNoDelivery(dev, grab, ev, ev);
|
||||
GestureAddGrabListener(dev, gi, grab);
|
||||
}
|
||||
|
||||
static void
|
||||
GestureAddRegularListener(DeviceIntPtr dev, GestureInfoPtr gi, WindowPtr win, InternalEvent *ev)
|
||||
{
|
||||
InputClients *iclients = NULL;
|
||||
OtherInputMasks *inputMasks = NULL;
|
||||
uint16_t evtype = GetXI2Type(ev->any.type);
|
||||
int mask;
|
||||
|
||||
mask = EventIsDeliverable(dev, ev->any.type, win);
|
||||
if (!mask)
|
||||
return;
|
||||
|
||||
inputMasks = wOtherInputMasks(win);
|
||||
|
||||
if (mask & EVENT_XI2_MASK) {
|
||||
nt_list_for_each_entry(iclients, inputMasks->inputClients, next) {
|
||||
if (!xi2mask_isset(iclients->xi2mask, dev, evtype))
|
||||
continue;
|
||||
|
||||
GestureAddListener(gi, iclients->resource, RT_INPUTCLIENT,
|
||||
GESTURE_LISTENER_REGULAR, win, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GestureSetupListener(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
|
||||
{
|
||||
int i;
|
||||
SpritePtr sprite = &gi->sprite;
|
||||
WindowPtr win;
|
||||
|
||||
/* Any current grab will consume all gesture events */
|
||||
if (dev->deviceGrab.grab) {
|
||||
GestureAddGrabListener(dev, gi, dev->deviceGrab.grab);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find passive grab that would be activated by this event, if any. If we're handling
|
||||
* ReplayDevice then the search starts from the descendant of the grab window, otherwise
|
||||
* the search starts at the root window. The search ends at deepest child window. */
|
||||
i = 0;
|
||||
if (syncEvents.playingEvents) {
|
||||
while (i < dev->spriteInfo->sprite->spriteTraceGood) {
|
||||
if (dev->spriteInfo->sprite->spriteTrace[i++] == syncEvents.replayWin)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < sprite->spriteTraceGood; i++) {
|
||||
win = sprite->spriteTrace[i];
|
||||
GestureAddPassiveGrabListener(dev, gi, win, ev);
|
||||
if (gi->has_listener)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the first client with an applicable event selection,
|
||||
* going from deepest child window back up to the root window. */
|
||||
for (i = sprite->spriteTraceGood - 1; i >= 0; i--) {
|
||||
win = sprite->spriteTrace[i];
|
||||
GestureAddRegularListener(dev, gi, win, ev);
|
||||
if (gi->has_listener)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* As gesture grabs don't turn into active grabs with their own resources, we
|
||||
* need to walk all the gestures and remove this grab from listener */
|
||||
void
|
||||
GestureListenerGone(XID resource)
|
||||
{
|
||||
GestureInfoPtr gi;
|
||||
DeviceIntPtr dev;
|
||||
InternalEvent *events = InitEventList(GetMaximumEventsNum());
|
||||
|
||||
if (!events)
|
||||
FatalError("GestureListenerGone: couldn't allocate events\n");
|
||||
|
||||
for (dev = inputInfo.devices; dev; dev = dev->next) {
|
||||
if (!dev->gesture)
|
||||
continue;
|
||||
|
||||
gi = &dev->gesture->gesture;
|
||||
if (!gi->active)
|
||||
continue;
|
||||
|
||||
if (CLIENT_BITS(gi->listener.listener) == resource)
|
||||
GestureEndGesture(gi);
|
||||
}
|
||||
|
||||
FreeEventList(events, GetMaximumEventsNum());
|
||||
}
|
||||
|
||||
/**
|
||||
* End physically active gestures for a device.
|
||||
*/
|
||||
void
|
||||
GestureEndActiveGestures(DeviceIntPtr dev)
|
||||
{
|
||||
GestureClassPtr g = dev->gesture;
|
||||
InternalEvent *eventlist;
|
||||
|
||||
if (!g)
|
||||
return;
|
||||
|
||||
eventlist = InitEventList(GetMaximumEventsNum());
|
||||
|
||||
input_lock();
|
||||
mieqProcessInputEvents();
|
||||
if (g->gesture.active) {
|
||||
int j;
|
||||
int type = GetXI2Type(GestureTypeToEnd(g->gesture.type));
|
||||
int nevents = GetGestureEvents(eventlist, dev, type, g->gesture.num_touches,
|
||||
0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
for (j = 0; j < nevents; j++)
|
||||
mieqProcessDeviceEvent(dev, eventlist + j, NULL);
|
||||
}
|
||||
input_unlock();
|
||||
|
||||
FreeEventList(eventlist, GetMaximumEventsNum());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and deliver a Gesture{Pinch,Swipe}End event to the owner.
|
||||
*
|
||||
* @param dev The device to deliver the event for.
|
||||
* @param gi The gesture record to deliver the event for.
|
||||
*/
|
||||
void
|
||||
GestureEmitGestureEndToOwner(DeviceIntPtr dev, GestureInfoPtr gi)
|
||||
{
|
||||
InternalEvent event;
|
||||
/* We're not processing a gesture end for a frozen device */
|
||||
if (dev->deviceGrab.sync.frozen)
|
||||
return;
|
||||
|
||||
DeliverDeviceClassesChangedEvent(gi->sourceid, GetTimeInMillis());
|
||||
InitGestureEvent(&event, dev, GetTimeInMillis(), GestureTypeToEnd(gi->type),
|
||||
0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
DeliverGestureEventToOwner(dev, gi, &event);
|
||||
}
|
140
dix/getevents.c
140
dix/getevents.c
|
@ -1874,7 +1874,7 @@ int
|
|||
GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
|
||||
uint16_t type, uint32_t flags, const ValuatorMask *mask_in)
|
||||
{
|
||||
ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
|
||||
ScreenPtr scr;
|
||||
TouchClassPtr t = dev->touch;
|
||||
ValuatorClassPtr v = dev->valuator;
|
||||
DeviceEvent *event;
|
||||
|
@ -1989,6 +1989,8 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
|
|||
if (need_rawevent)
|
||||
set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
|
||||
|
||||
scr = dev->spriteInfo->sprite->hotPhys.pScreen;
|
||||
|
||||
/* Indirect device touch coordinates are not used for cursor positioning.
|
||||
* They are merely informational, and are provided in device coordinates.
|
||||
* The device sprite is used for positioning instead, and it is already
|
||||
|
@ -2099,3 +2101,139 @@ PostSyntheticMotion(DeviceIntPtr pDev,
|
|||
/* FIXME: MD/SD considerations? */
|
||||
(*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev);
|
||||
}
|
||||
|
||||
void
|
||||
InitGestureEvent(InternalEvent *ievent, DeviceIntPtr dev, CARD32 ms,
|
||||
int type, uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x, double delta_unaccel_y,
|
||||
double scale, double delta_angle)
|
||||
{
|
||||
ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
|
||||
GestureEvent *event = &ievent->gesture_event;
|
||||
double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
|
||||
|
||||
init_gesture_event(event, dev, ms);
|
||||
|
||||
screenx = dev->spriteInfo->sprite->hotPhys.x;
|
||||
screeny = dev->spriteInfo->sprite->hotPhys.y;
|
||||
|
||||
event->type = type;
|
||||
event->root = scr->root->drawable.id;
|
||||
event->root_x = screenx - scr->x;
|
||||
event->root_y = screeny - scr->y;
|
||||
event->num_touches = num_touches;
|
||||
event->flags = flags;
|
||||
|
||||
event->delta_x = delta_x;
|
||||
event->delta_y = delta_y;
|
||||
event->delta_unaccel_x = delta_unaccel_x;
|
||||
event->delta_unaccel_y = delta_unaccel_y;
|
||||
event->scale = scale;
|
||||
event->delta_angle = delta_angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get events for a pinch or swipe gesture.
|
||||
*
|
||||
* events is not NULL-terminated; the return value is the number of events.
|
||||
* The DDX is responsible for allocating the event structure in the first
|
||||
* place via GetMaximumEventsNum(), and for freeing it.
|
||||
*
|
||||
* @param[out] events The list of events generated
|
||||
* @param dev The device to generate the events for
|
||||
* @param type XI_Gesture{Pinch,Swipe}{Begin,Update,End}
|
||||
* @prama num_touches The number of touches in the gesture
|
||||
* @param flags Event flags
|
||||
* @param delta_x,delta_y accelerated relative motion delta
|
||||
* @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta
|
||||
* @param scale (valid only to pinch events) absolute scale of a pinch gesture
|
||||
* @param delta_angle (valid only to pinch events) the ange delta in degrees between the last and
|
||||
* the current pinch event.
|
||||
*/
|
||||
int
|
||||
GetGestureEvents(InternalEvent *events, DeviceIntPtr dev,
|
||||
uint16_t type, uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x, double delta_unaccel_y,
|
||||
double scale, double delta_angle)
|
||||
|
||||
{
|
||||
GestureClassPtr g = dev->gesture;
|
||||
CARD32 ms = GetTimeInMillis();
|
||||
enum EventType evtype;
|
||||
int num_events = 0;
|
||||
uint32_t evflags = 0;
|
||||
|
||||
if (!dev->enabled || !g)
|
||||
return 0;
|
||||
|
||||
if (!IsMaster(dev))
|
||||
events = UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT,
|
||||
&num_events);
|
||||
|
||||
switch (type) {
|
||||
case XI_GesturePinchBegin:
|
||||
evtype = ET_GesturePinchBegin;
|
||||
break;
|
||||
case XI_GesturePinchUpdate:
|
||||
evtype = ET_GesturePinchUpdate;
|
||||
break;
|
||||
case XI_GesturePinchEnd:
|
||||
evtype = ET_GesturePinchEnd;
|
||||
if (flags & XIGesturePinchEventCancelled)
|
||||
evflags |= GESTURE_CANCELLED;
|
||||
break;
|
||||
case XI_GestureSwipeBegin:
|
||||
evtype = ET_GestureSwipeBegin;
|
||||
break;
|
||||
case XI_GestureSwipeUpdate:
|
||||
evtype = ET_GestureSwipeUpdate;
|
||||
break;
|
||||
case XI_GestureSwipeEnd:
|
||||
evtype = ET_GestureSwipeEnd;
|
||||
if (flags & XIGestureSwipeEventCancelled)
|
||||
evflags |= GESTURE_CANCELLED;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
InitGestureEvent(events, dev, ms, evtype, num_touches, evflags,
|
||||
delta_x, delta_y, delta_unaccel_x, delta_unaccel_y,
|
||||
scale, delta_angle);
|
||||
num_events++;
|
||||
|
||||
return num_events;
|
||||
}
|
||||
|
||||
void
|
||||
QueueGesturePinchEvents(DeviceIntPtr dev, uint16_t type,
|
||||
uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x,
|
||||
double delta_unaccel_y,
|
||||
double scale, double delta_angle)
|
||||
{
|
||||
int nevents;
|
||||
nevents = GetGestureEvents(InputEventList, dev, type, num_touches, flags,
|
||||
delta_x, delta_y,
|
||||
delta_unaccel_x, delta_unaccel_y,
|
||||
scale, delta_angle);
|
||||
queueEventList(dev, InputEventList, nevents);
|
||||
}
|
||||
|
||||
void
|
||||
QueueGestureSwipeEvents(DeviceIntPtr dev, uint16_t type,
|
||||
uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x,
|
||||
double delta_unaccel_y)
|
||||
{
|
||||
int nevents;
|
||||
nevents = GetGestureEvents(InputEventList, dev, type, num_touches, flags,
|
||||
delta_x, delta_y,
|
||||
delta_unaccel_x, delta_unaccel_y,
|
||||
0.0, 0.0);
|
||||
queueEventList(dev, InputEventList, nevents);
|
||||
}
|
||||
|
|
|
@ -716,3 +716,10 @@ GrabIsKeyboardGrab(GrabPtr grab)
|
|||
return (grab->type == KeyPress ||
|
||||
grab->type == DeviceKeyPress || grab->type == XI_KeyPress);
|
||||
}
|
||||
|
||||
Bool
|
||||
GrabIsGestureGrab(GrabPtr grab)
|
||||
{
|
||||
return (grab->type == XI_GesturePinchBegin ||
|
||||
grab->type == XI_GestureSwipeBegin);
|
||||
}
|
||||
|
|
|
@ -746,6 +746,21 @@ init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
|
|||
event->source_type = source_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the given gesture event to zero (or default values),
|
||||
* for the given device.
|
||||
*/
|
||||
void
|
||||
init_gesture_event(GestureEvent *event, DeviceIntPtr dev, Time ms)
|
||||
{
|
||||
memset(event, 0, sizeof(GestureEvent));
|
||||
event->header = ET_Internal;
|
||||
event->length = sizeof(GestureEvent);
|
||||
event->time = ms;
|
||||
event->deviceid = dev->id;
|
||||
event->sourceid = dev->id;
|
||||
}
|
||||
|
||||
int
|
||||
event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd)
|
||||
{
|
||||
|
@ -794,6 +809,24 @@ event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
event_set_state_gesture(DeviceIntPtr kbd, GestureEvent *event)
|
||||
{
|
||||
if (kbd && kbd->key) {
|
||||
XkbStatePtr state= &kbd->key->xkbInfo->state;
|
||||
|
||||
event->mods.base = state->base_mods;
|
||||
event->mods.latched = state->latched_mods;
|
||||
event->mods.locked = state->locked_mods;
|
||||
event->mods.effective = state->mods;
|
||||
|
||||
event->group.base = state->base_group;
|
||||
event->group.latched = state->latched_group;
|
||||
event->group.locked = state->locked_group;
|
||||
event->group.effective = state->group;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the event filter mask for the given device and the given core or
|
||||
* XI1 protocol type.
|
||||
|
|
|
@ -12,6 +12,7 @@ srcs_dix = [
|
|||
'eventconvert.c',
|
||||
'extension.c',
|
||||
'gc.c',
|
||||
'gestures.c',
|
||||
'getevents.c',
|
||||
'globals.c',
|
||||
'glyphcurs.c',
|
||||
|
|
|
@ -155,14 +155,13 @@ dixMovePrivates(PrivatePtr *privates, int new_offset, unsigned bytes)
|
|||
static Bool
|
||||
fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
|
||||
{
|
||||
intptr_t dist;
|
||||
char *old;
|
||||
uintptr_t old;
|
||||
char *new;
|
||||
DevPrivateKey *keyp, key;
|
||||
DevPrivateType type;
|
||||
int size;
|
||||
|
||||
old = (char *) pScreen->devPrivates;
|
||||
old = (uintptr_t) pScreen->devPrivates;
|
||||
size = global_keys[PRIVATE_SCREEN].offset;
|
||||
if (!fixup (&pScreen->devPrivates, size, bytes))
|
||||
return FALSE;
|
||||
|
@ -182,9 +181,7 @@ fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
|
|||
if (fixup == dixMovePrivates)
|
||||
new += bytes;
|
||||
|
||||
dist = new - old;
|
||||
|
||||
if (dist) {
|
||||
if ((uintptr_t) new != old) {
|
||||
for (type = PRIVATE_XSELINUX; type < PRIVATE_LAST; type++)
|
||||
|
||||
/* Walk the privates list, being careful as the
|
||||
|
@ -199,10 +196,11 @@ fixupOneScreen(ScreenPtr pScreen, FixupFunc fixup, unsigned bytes)
|
|||
* is contained within the allocation. Privates
|
||||
* stored elsewhere will be left alone
|
||||
*/
|
||||
if (old <= (char *) key && (char *) key < old + size)
|
||||
if (old <= (uintptr_t) key && (uintptr_t) key < old + size)
|
||||
{
|
||||
/* Compute new location of key */
|
||||
key = (DevPrivateKey) ((char *) key + dist);
|
||||
/* Compute new location of key (deriving from the new
|
||||
* allocation to avoid UB) */
|
||||
key = (DevPrivateKey) (new + ((uintptr_t) key - old));
|
||||
|
||||
/* Patch the list */
|
||||
*keyp = key;
|
||||
|
|
|
@ -205,7 +205,8 @@ ProcChangeProperty(ClientPtr client)
|
|||
WindowPtr pWin;
|
||||
char format, mode;
|
||||
unsigned long len;
|
||||
int sizeInBytes, totalSize, err;
|
||||
int sizeInBytes, err;
|
||||
uint64_t totalSize;
|
||||
|
||||
REQUEST(xChangePropertyReq);
|
||||
|
||||
|
@ -253,7 +254,7 @@ ProcChangeProperty(ClientPtr client)
|
|||
int
|
||||
dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
|
||||
Atom type, int format, int mode, unsigned long len,
|
||||
void *value, Bool sendevent)
|
||||
const void *value, Bool sendevent)
|
||||
{
|
||||
PropertyPtr pProp;
|
||||
PropertyRec savedProp;
|
||||
|
|
|
@ -620,12 +620,15 @@ ilog2(int val)
|
|||
unsigned int
|
||||
ResourceClientBits(void)
|
||||
{
|
||||
static unsigned int cached = 0;
|
||||
static unsigned int cache_ilog2 = 0;
|
||||
static unsigned int cache_limit = 0;
|
||||
|
||||
if (cached == 0)
|
||||
cached = ilog2(LimitClients);
|
||||
if (LimitClients != cache_limit) {
|
||||
cache_limit = LimitClients;
|
||||
cache_ilog2 = ilog2(LimitClients);
|
||||
}
|
||||
|
||||
return cached;
|
||||
return cache_ilog2;
|
||||
}
|
||||
|
||||
/*****************
|
||||
|
|
|
@ -42,6 +42,8 @@
|
|||
|
||||
#define TOUCH_HISTORY_SIZE 100
|
||||
|
||||
Bool touchEmulatePointer = TRUE;
|
||||
|
||||
/**
|
||||
* Some documentation about touch points:
|
||||
* The driver submits touch events with its own (unique) touch point ID.
|
||||
|
@ -142,7 +144,7 @@ TouchBeginDDXTouch(DeviceIntPtr dev, uint32_t ddx_id)
|
|||
if (!t)
|
||||
return NULL;
|
||||
|
||||
emulate_pointer = (t->mode == XIDirectTouch);
|
||||
emulate_pointer = touchEmulatePointer && (t->mode == XIDirectTouch);
|
||||
|
||||
/* Look for another active touchpoint with the same DDX ID. DDX
|
||||
* touchpoints must be unique. */
|
||||
|
|
|
@ -3642,7 +3642,7 @@ SetRootClip(ScreenPtr pScreen, int enable)
|
|||
if (!pWin)
|
||||
return;
|
||||
WasViewable = (Bool) (pWin->viewable);
|
||||
if (WasViewable) {
|
||||
if (WasViewable && mode != ROOT_CLIP_INPUT_ONLY) {
|
||||
for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
|
||||
(void) (*pScreen->MarkOverlappedWindows) (pChild,
|
||||
pChild, &pLayerWin);
|
||||
|
@ -3696,7 +3696,7 @@ SetRootClip(ScreenPtr pScreen, int enable)
|
|||
|
||||
ResizeChildrenWinSize(pWin, 0, 0, 0, 0);
|
||||
|
||||
if (WasViewable) {
|
||||
if (WasViewable && mode != ROOT_CLIP_INPUT_ONLY) {
|
||||
if (pWin->firstChild) {
|
||||
anyMarked |= (*pScreen->MarkOverlappedWindows) (pWin->firstChild,
|
||||
pWin->firstChild,
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
if build_docs
|
||||
basename = 'Xserver-DTrace'
|
||||
|
||||
input_xml = basename + '.xml'
|
||||
|
||||
custom_target(
|
||||
basename + '.html',
|
||||
output: basename + '.html',
|
||||
input: [input_xml],
|
||||
command: [xmlto] + docs_xmlto_search_flags + [
|
||||
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-xhtml.xsl'),
|
||||
'--stringparam', 'target.database.document=' + join_paths(doc_sgml_path, 'X11/dbs/masterdb.html.xml'),
|
||||
'--stringparam', 'current.docid=' + basename,
|
||||
'-o', meson.current_build_dir(),
|
||||
'xhtml-nochunks', '@INPUT0@'],
|
||||
build_by_default: true,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('datadir'), 'doc/xorg-server'),
|
||||
)
|
||||
|
||||
if build_docs_pdf
|
||||
foreach format : ['ps', 'pdf']
|
||||
output_fn = basename + '.' + format
|
||||
custom_target(
|
||||
output_fn,
|
||||
output: output_fn,
|
||||
input: [input_xml],
|
||||
command: [xmlto] + docs_xmlto_search_flags + [
|
||||
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-fo.xsl'),
|
||||
'--stringparam', 'img.src.path=' + meson.current_build_dir(),
|
||||
'--stringparam', 'target.database.document=' + join_paths(doc_sgml_path, 'X11/dbs/masterdb.pdf.xml'),
|
||||
'--stringparam', 'current.docid=' + basename,
|
||||
'-o', meson.current_build_dir(),
|
||||
'--with-fop', format, '@INPUT0@'],
|
||||
build_by_default: true,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('datadir'), 'doc/xorg-server'),
|
||||
)
|
||||
endforeach
|
||||
endif
|
||||
|
||||
foreach format_data : [['html', 'xorg-xhtml.xsl'], ['pdf', 'xorg-fo.xsl']]
|
||||
format = format_data[0]
|
||||
stylesheet = format_data[1]
|
||||
output_fn = basename + '.' + format + '.db'
|
||||
custom_target(
|
||||
output_fn,
|
||||
output: output_fn,
|
||||
input: [input_xml],
|
||||
command: [xsltproc] + docs_xslt_search_flags + [
|
||||
'--stringparam', 'targets.filename', output_fn,
|
||||
'--stringparam', 'collect.xref.targets', 'only',
|
||||
'--stringparam', 'olink.base.uri', basename + '.' + format,
|
||||
'--nonet',
|
||||
'--output', join_paths(meson.current_build_dir(), output_fn),
|
||||
'--xinclude', join_paths(doc_stylesheet_srcdir, stylesheet),
|
||||
'@INPUT0@'],
|
||||
build_by_default: true,
|
||||
install: true,
|
||||
install_dir: join_paths(get_option('datadir'), 'doc/xorg-server'),
|
||||
)
|
||||
endforeach
|
||||
endif
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
if build_docs_devel
|
||||
foreach basename : ['Xserver-spec', 'Xinput']
|
||||
|
||||
input_xml = basename + '.xml'
|
||||
|
||||
custom_target(
|
||||
basename + '.html',
|
||||
output: basename + '.html',
|
||||
input: [input_xml],
|
||||
command: [xmlto] + docs_xmlto_search_flags + [
|
||||
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-xhtml.xsl'),
|
||||
'-o', meson.current_build_dir(),
|
||||
'xhtml-nochunks', '@INPUT0@'],
|
||||
build_by_default: true,
|
||||
install: false,
|
||||
)
|
||||
|
||||
if build_docs_pdf
|
||||
foreach format : ['ps', 'pdf']
|
||||
output_fn = basename + '.' + format
|
||||
custom_target(
|
||||
output_fn,
|
||||
output: output_fn,
|
||||
input: [input_xml],
|
||||
command: [xmlto] + docs_xmlto_search_flags + [
|
||||
'-x', join_paths(doc_stylesheet_srcdir, 'xorg-fo.xsl'),
|
||||
'--stringparam', 'img.src.path=' + meson.current_build_dir(),
|
||||
'-o', meson.current_build_dir(),
|
||||
'--with-fop', format, '@INPUT0@'],
|
||||
build_by_default: true,
|
||||
install: false,
|
||||
)
|
||||
endforeach
|
||||
endif
|
||||
endforeach
|
||||
endif
|
||||
|
||||
subdir('dtrace')
|
105
docbook.am
105
docbook.am
|
@ -1,105 +0,0 @@
|
|||
#
|
||||
# Generate output formats for a single DocBook/XML with/without chapters
|
||||
#
|
||||
# Variables set by the calling Makefile:
|
||||
# shelfdir: the location where the docs/specs are installed. Typically $(docdir)
|
||||
# docbook: the main DocBook/XML file, no chapters, appendix or image files
|
||||
# chapters: all files pulled in by an XInclude statement and images.
|
||||
#
|
||||
|
||||
#
|
||||
# This makefile is intended for Users Documentation and Functional Specifications.
|
||||
# Do not use for Developer Documentation which is not installed and does not require olink.
|
||||
# Refer to http://www.x.org/releases/X11R7.6/doc/xorg-docs/ReleaseNotes.html#id2584393
|
||||
# for an explanation on documents classification.
|
||||
#
|
||||
|
||||
# DocBook/XML generated output formats to be installed
|
||||
shelf_DATA =
|
||||
|
||||
# DocBook/XML file with chapters, appendix and images it includes
|
||||
dist_shelf_DATA = $(docbook) $(chapters)
|
||||
|
||||
if HAVE_XMLTO
|
||||
if HAVE_STYLESHEETS
|
||||
|
||||
XMLTO_SEARCHPATH_FLAGS = \
|
||||
--searchpath "$(XORG_SGML_PATH)/X11" \
|
||||
--searchpath "$(abs_top_builddir)"
|
||||
XMLTO_HTML_OLINK_FLAGS = \
|
||||
--stringparam target.database.document=$(XORG_SGML_PATH)/X11/dbs/masterdb.html.xml \
|
||||
--stringparam current.docid="$(<:.xml=)"
|
||||
XMLTO_HTML_STYLESHEET_FLAGS = -x $(STYLESHEET_SRCDIR)/xorg-xhtml.xsl
|
||||
XMLTO_HTML_FLAGS = \
|
||||
$(XMLTO_SEARCHPATH_FLAGS) \
|
||||
$(XMLTO_HTML_STYLESHEET_FLAGS) \
|
||||
$(XMLTO_HTML_OLINK_FLAGS)
|
||||
|
||||
shelf_DATA += $(docbook:.xml=.html)
|
||||
%.html: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(XMLTO) $(XMLTO_HTML_FLAGS) xhtml-nochunks $<
|
||||
|
||||
if HAVE_XMLTO_TEXT
|
||||
|
||||
shelf_DATA += $(docbook:.xml=.txt)
|
||||
%.txt: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(XMLTO) $(XMLTO_HTML_FLAGS) txt $<
|
||||
endif HAVE_XMLTO_TEXT
|
||||
|
||||
if HAVE_FOP
|
||||
XMLTO_FO_IMAGEPATH_FLAGS = --stringparam img.src.path=$(abs_builddir)/
|
||||
XMLTO_PDF_OLINK_FLAGS = \
|
||||
--stringparam target.database.document=$(XORG_SGML_PATH)/X11/dbs/masterdb.pdf.xml \
|
||||
--stringparam current.docid="$(<:.xml=)"
|
||||
XMLTO_FO_STYLESHEET_FLAGS = -x $(STYLESHEET_SRCDIR)/xorg-fo.xsl
|
||||
|
||||
XMLTO_FO_FLAGS = \
|
||||
$(XMLTO_SEARCHPATH_FLAGS) \
|
||||
$(XMLTO_FO_STYLESHEET_FLAGS) \
|
||||
$(XMLTO_FO_IMAGEPATH_FLAGS) \
|
||||
$(XMLTO_PDF_OLINK_FLAGS)
|
||||
|
||||
shelf_DATA += $(docbook:.xml=.pdf)
|
||||
%.pdf: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(XMLTO) $(XMLTO_FO_FLAGS) --with-fop pdf $<
|
||||
|
||||
shelf_DATA += $(docbook:.xml=.ps)
|
||||
%.ps: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(XMLTO) $(XMLTO_FO_FLAGS) --with-fop ps $<
|
||||
endif HAVE_FOP
|
||||
|
||||
# Generate documents cross-reference target databases
|
||||
if HAVE_XSLTPROC
|
||||
|
||||
XSLT_SEARCHPATH_FLAGS = \
|
||||
--path "$(XORG_SGML_PATH)/X11" \
|
||||
--path "$(abs_top_builddir)"
|
||||
XSLT_OLINK_FLAGS = \
|
||||
--stringparam targets.filename "$@" \
|
||||
--stringparam collect.xref.targets "only" \
|
||||
--stringparam olink.base.uri "$(@:.db=)"
|
||||
|
||||
XSLT_HTML_FLAGS = \
|
||||
$(XSLT_SEARCHPATH_FLAGS) \
|
||||
$(XSLT_OLINK_FLAGS) \
|
||||
--nonet --xinclude \
|
||||
$(STYLESHEET_SRCDIR)/xorg-xhtml.xsl
|
||||
XSLT_PDF_FLAGS = \
|
||||
$(XSLT_SEARCHPATH_FLAGS) \
|
||||
$(XSLT_OLINK_FLAGS) \
|
||||
--nonet --xinclude \
|
||||
$(STYLESHEET_SRCDIR)/xorg-fo.xsl
|
||||
|
||||
shelf_DATA += $(docbook:.xml=.html.db)
|
||||
%.html.db: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(XSLTPROC) $(XSLT_HTML_FLAGS) $<
|
||||
|
||||
shelf_DATA += $(docbook:.xml=.pdf.db)
|
||||
%.pdf.db: %.xml $(chapters)
|
||||
$(AM_V_GEN)$(XSLTPROC) $(XSLT_PDF_FLAGS) $<
|
||||
|
||||
endif HAVE_XSLTPROC
|
||||
endif HAVE_STYLESHEETS
|
||||
endif HAVE_XMLTO
|
||||
|
||||
CLEANFILES = $(shelf_DATA)
|
|
@ -216,7 +216,7 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
|
|||
w <= glamor_priv->glyph_max_dim &&
|
||||
h <= glamor_priv->glyph_max_dim)
|
||||
|| (w == 0 && h == 0)
|
||||
|| !glamor_priv->formats[depth].format))
|
||||
|| !glamor_priv->formats[depth].rendering_supported))
|
||||
return fbCreatePixmap(screen, w, h, depth, usage);
|
||||
else
|
||||
pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
|
||||
|
@ -414,6 +414,7 @@ glamor_debug_output_callback(GLenum source,
|
|||
|
||||
LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n",
|
||||
screen->myNum, length, message);
|
||||
xorg_backtrace();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -460,7 +461,8 @@ glamor_format_for_pixmap(PixmapPtr pixmap)
|
|||
|
||||
static void
|
||||
glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format,
|
||||
GLenum internalformat, GLenum format, GLenum type)
|
||||
GLenum internalformat, GLenum format, GLenum type,
|
||||
Bool rendering_supported)
|
||||
{
|
||||
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
|
||||
struct glamor_format *f = &glamor_priv->formats[depth];
|
||||
|
@ -475,7 +477,7 @@ glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format,
|
|||
* Note that we can't just create a pixmap because we're in
|
||||
* screeninit.
|
||||
*/
|
||||
if (glamor_priv->is_gles) {
|
||||
if (rendering_supported && glamor_priv->is_gles) {
|
||||
unsigned fbo, tex;
|
||||
int read_format, read_type;
|
||||
GLenum status;
|
||||
|
@ -520,6 +522,7 @@ glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format,
|
|||
f->internalformat = internalformat;
|
||||
f->format = format;
|
||||
f->type = type;
|
||||
f->rendering_supported = rendering_supported;
|
||||
}
|
||||
|
||||
/* Set up the GL format/types that glamor will use for the various depths
|
||||
|
@ -550,11 +553,15 @@ glamor_setup_formats(ScreenPtr screen)
|
|||
* only falling back to a8 if we can't do them.
|
||||
*/
|
||||
if (glamor_priv->is_gles || epoxy_has_gl_extension("GL_ARB_texture_rg")) {
|
||||
glamor_add_format(screen, 1, PICT_a1,
|
||||
GL_R8, GL_RED, GL_UNSIGNED_BYTE, FALSE);
|
||||
glamor_add_format(screen, 8, PICT_a8,
|
||||
GL_R8, GL_RED, GL_UNSIGNED_BYTE);
|
||||
GL_R8, GL_RED, GL_UNSIGNED_BYTE, TRUE);
|
||||
} else {
|
||||
glamor_add_format(screen, 1, PICT_a1,
|
||||
GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, FALSE);
|
||||
glamor_add_format(screen, 8, PICT_a8,
|
||||
GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
|
||||
GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, TRUE);
|
||||
}
|
||||
|
||||
if (glamor_priv->is_gles) {
|
||||
|
@ -568,40 +575,41 @@ glamor_setup_formats(ScreenPtr screen)
|
|||
* disable render accel for now.
|
||||
*/
|
||||
glamor_add_format(screen, 15, PICT_x1r5g5b5,
|
||||
GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1);
|
||||
GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, TRUE);
|
||||
} else {
|
||||
glamor_add_format(screen, 15, PICT_x1r5g5b5,
|
||||
GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV);
|
||||
GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, TRUE);
|
||||
}
|
||||
|
||||
glamor_add_format(screen, 16, PICT_r5g6b5,
|
||||
GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5);
|
||||
GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, TRUE);
|
||||
|
||||
if (glamor_priv->is_gles) {
|
||||
assert(X_BYTE_ORDER == X_LITTLE_ENDIAN);
|
||||
glamor_add_format(screen, 24, PICT_x8b8g8r8,
|
||||
GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, TRUE);
|
||||
glamor_add_format(screen, 32, PICT_a8b8g8r8,
|
||||
GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, TRUE);
|
||||
} else {
|
||||
glamor_add_format(screen, 24, PICT_x8r8g8b8,
|
||||
GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
||||
GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE);
|
||||
glamor_add_format(screen, 32, PICT_a8r8g8b8,
|
||||
GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV);
|
||||
GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE);
|
||||
}
|
||||
|
||||
if (glamor_priv->is_gles) {
|
||||
glamor_add_format(screen, 30, PICT_x2b10g10r10,
|
||||
GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV);
|
||||
GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE);
|
||||
} else {
|
||||
glamor_add_format(screen, 30, PICT_x2r10g10b10,
|
||||
GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV);
|
||||
GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE);
|
||||
}
|
||||
|
||||
glamor_priv->cbcr_format.depth = 16;
|
||||
glamor_priv->cbcr_format.internalformat = GL_RG8;
|
||||
glamor_priv->cbcr_format.format = GL_RG;
|
||||
glamor_priv->cbcr_format.type = GL_UNSIGNED_BYTE;
|
||||
glamor_priv->cbcr_format.rendering_supported = TRUE;
|
||||
}
|
||||
|
||||
/** Set up glamor for an already-configured GL context. */
|
||||
|
@ -610,10 +618,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
{
|
||||
glamor_screen_private *glamor_priv;
|
||||
int gl_version;
|
||||
int glsl_major, glsl_minor;
|
||||
int max_viewport_size[2];
|
||||
const char *shading_version_string;
|
||||
int shading_version_offset;
|
||||
|
||||
PictureScreenPtr ps = GetPictureScreenIfSet(screen);
|
||||
|
||||
|
@ -662,9 +667,6 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
* register correct close screen function. */
|
||||
if (flags & GLAMOR_USE_EGL_SCREEN) {
|
||||
glamor_egl_screen_init(screen, &glamor_priv->ctx);
|
||||
} else {
|
||||
if (!glamor_glx_screen_init(&glamor_priv->ctx))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
glamor_make_current(glamor_priv);
|
||||
|
@ -678,29 +680,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
glamor_priv->is_core_profile =
|
||||
gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility");
|
||||
|
||||
shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
|
||||
if (!shading_version_string) {
|
||||
LogMessage(X_WARNING,
|
||||
"glamor%d: Failed to get GLSL version\n",
|
||||
screen->myNum);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
shading_version_offset = 0;
|
||||
if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0)
|
||||
shading_version_offset = 18;
|
||||
|
||||
if (sscanf(shading_version_string + shading_version_offset,
|
||||
"%i.%i",
|
||||
&glsl_major,
|
||||
&glsl_minor) != 2) {
|
||||
LogMessage(X_WARNING,
|
||||
"glamor%d: Failed to parse GLSL version string %s\n",
|
||||
screen->myNum, shading_version_string);
|
||||
goto fail;
|
||||
}
|
||||
glamor_priv->glsl_version = glsl_major * 100 + glsl_minor;
|
||||
glamor_priv->glsl_version = epoxy_glsl_version();
|
||||
|
||||
if (glamor_priv->is_gles) {
|
||||
/* Force us back to the base version of our programs on an ES
|
||||
|
@ -745,7 +725,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
* have instanced arrays, but this is not always the case.
|
||||
* etnaviv offers GLSL 140 with OpenGL 2.1.
|
||||
*/
|
||||
if (glamor_priv->glsl_version >= 130 &&
|
||||
if (glamor_glsl_has_ints(glamor_priv) &&
|
||||
!epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
|
||||
glamor_priv->glsl_version = 120;
|
||||
} else {
|
||||
|
@ -771,6 +751,10 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!glamor_priv->is_gles && glamor_priv->glsl_version == 120 &&
|
||||
epoxy_has_gl_extension("GL_ARB_instanced_arrays"))
|
||||
glamor_priv->use_gpu_shader4 = epoxy_has_gl_extension("GL_EXT_gpu_shader4");
|
||||
|
||||
glamor_priv->has_rw_pbo = FALSE;
|
||||
if (!glamor_priv->is_gles)
|
||||
glamor_priv->has_rw_pbo = TRUE;
|
||||
|
@ -798,7 +782,7 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
epoxy_gl_version() >= 30 ||
|
||||
epoxy_has_gl_extension("GL_NV_pack_subimage");
|
||||
glamor_priv->has_dual_blend =
|
||||
glamor_priv->glsl_version >= 130 &&
|
||||
glamor_glsl_has_ints(glamor_priv) &&
|
||||
epoxy_has_gl_extension("GL_ARB_blend_func_extended");
|
||||
glamor_priv->has_clear_texture =
|
||||
epoxy_gl_version() >= 44 ||
|
||||
|
@ -816,7 +800,8 @@ glamor_init(ScreenPtr screen, unsigned int flags)
|
|||
* cached IB.
|
||||
*/
|
||||
if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") &&
|
||||
strstr((char *)glGetString(GL_RENDERER), "VC4"))
|
||||
(strstr((char *)glGetString(GL_RENDERER), "VC4") ||
|
||||
strstr((char *)glGetString(GL_RENDERER), "V3D")))
|
||||
glamor_priv->use_quads = FALSE;
|
||||
|
||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size);
|
||||
|
|
|
@ -208,11 +208,6 @@ static const glamor_facet glamor_facet_composite_glyphs_120 = {
|
|||
.locations = glamor_program_location_atlas,
|
||||
};
|
||||
|
||||
static inline Bool
|
||||
glamor_glyph_use_130(glamor_screen_private *glamor_priv) {
|
||||
return glamor_priv->glsl_version >= 130;
|
||||
}
|
||||
|
||||
static Bool
|
||||
glamor_glyphs_init_facet(ScreenPtr screen)
|
||||
{
|
||||
|
@ -274,7 +269,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst,
|
|||
box->y2 - box->y1);
|
||||
box++;
|
||||
|
||||
if (glamor_glyph_use_130(glamor_priv))
|
||||
if (glamor_glsl_has_ints(glamor_priv))
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nglyph);
|
||||
else
|
||||
glamor_glDrawArrays_GL_QUADS(glamor_priv, nglyph);
|
||||
|
@ -287,7 +282,7 @@ glamor_glyphs_flush(CARD8 op, PicturePtr src, PicturePtr dst,
|
|||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
if (glamor_glyph_use_130(glamor_priv)) {
|
||||
if (glamor_glsl_has_ints(glamor_priv)) {
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
|
||||
}
|
||||
|
@ -305,7 +300,7 @@ glamor_glyph_start(ScreenPtr screen, int count)
|
|||
|
||||
/* Set up the vertex buffers for the font and destination */
|
||||
|
||||
if (glamor_glyph_use_130(glamor_priv)) {
|
||||
if (glamor_glsl_has_ints(glamor_priv)) {
|
||||
v = glamor_get_vbo_space(screen, count * (6 * sizeof (GLshort)), &vbo_offset);
|
||||
|
||||
glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
|
||||
|
@ -439,7 +434,7 @@ glamor_composite_glyphs(CARD8 op,
|
|||
/* First glyph in the current atlas?
|
||||
*/
|
||||
if (_X_UNLIKELY(glyphs_queued == 0)) {
|
||||
if (glamor_glyph_use_130(glamor_priv))
|
||||
if (glamor_glsl_has_ints(glamor_priv))
|
||||
prog = glamor_setup_program_render(op, src, glyph_pict, dst,
|
||||
glyphs_program,
|
||||
&glamor_facet_composite_glyphs_130,
|
||||
|
@ -458,7 +453,7 @@ glamor_composite_glyphs(CARD8 op,
|
|||
*/
|
||||
|
||||
glyphs_queued++;
|
||||
if (_X_LIKELY(glamor_glyph_use_130(glamor_priv))) {
|
||||
if (_X_LIKELY(glamor_glsl_has_ints(glamor_priv))) {
|
||||
v[0] = x - glyph->info.x;
|
||||
v[1] = y - glyph->info.y;
|
||||
v[2] = glyph_draw->width;
|
||||
|
|
|
@ -21,29 +21,26 @@
|
|||
* IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GLAMOR_CONTEXT_H
|
||||
#define GLAMOR_CONTEXT_H
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
/**
|
||||
* @file glamor_context.h
|
||||
*
|
||||
* This is the struct of state required for context switching in
|
||||
* glamor. It has to use types that don't require including either
|
||||
* server headers or Xlib headers, since it will be included by both
|
||||
* the server and the GLX (xlib) code.
|
||||
* glamor. Initially this was abstracted away from EGL, and
|
||||
* presumably it would need to be again if someone wanted to use
|
||||
* glamor with WGL/CGL.
|
||||
*/
|
||||
|
||||
struct glamor_context {
|
||||
/** Either an EGLDisplay or an Xlib Display */
|
||||
void *display;
|
||||
|
||||
/** Either a GLXContext or an EGLContext. */
|
||||
void *ctx;
|
||||
|
||||
/** The EGLSurface we should MakeCurrent to */
|
||||
void *drawable;
|
||||
|
||||
/** The GLXDrawable we should MakeCurrent to */
|
||||
uint32_t drawable_xid;
|
||||
EGLDisplay display;
|
||||
EGLContext ctx;
|
||||
EGLSurface surface;
|
||||
|
||||
void (*make_current)(struct glamor_context *glamor_ctx);
|
||||
};
|
||||
|
||||
Bool glamor_glx_screen_init(struct glamor_context *glamor_ctx);
|
||||
#endif
|
||||
|
|
|
@ -933,8 +933,6 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
{
|
||||
struct glamor_egl_screen_private *glamor_egl;
|
||||
const GLubyte *renderer;
|
||||
EGLConfig egl_config;
|
||||
int n;
|
||||
|
||||
glamor_egl = calloc(sizeof(*glamor_egl), 1);
|
||||
if (glamor_egl == NULL)
|
||||
|
@ -977,6 +975,7 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
}
|
||||
|
||||
GLAMOR_CHECK_EGL_EXTENSION(KHR_surfaceless_context);
|
||||
GLAMOR_CHECK_EGL_EXTENSION(KHR_no_config_context);
|
||||
|
||||
if (eglBindAPI(EGL_OPENGL_API)) {
|
||||
static const EGLint config_attribs_core[] = {
|
||||
|
@ -993,12 +992,13 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
};
|
||||
|
||||
glamor_egl->context = eglCreateContext(glamor_egl->display,
|
||||
NULL, EGL_NO_CONTEXT,
|
||||
EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
|
||||
config_attribs_core);
|
||||
|
||||
if (glamor_egl->context == EGL_NO_CONTEXT)
|
||||
glamor_egl->context = eglCreateContext(glamor_egl->display,
|
||||
NULL, EGL_NO_CONTEXT,
|
||||
EGL_NO_CONFIG_KHR,
|
||||
EGL_NO_CONTEXT,
|
||||
config_attribs);
|
||||
}
|
||||
|
||||
|
@ -1029,14 +1029,8 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!eglChooseConfig(glamor_egl->display, NULL, &egl_config, 1, &n)) {
|
||||
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
|
||||
"glamor: No acceptable EGL configs found\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
glamor_egl->context = eglCreateContext(glamor_egl->display,
|
||||
egl_config, EGL_NO_CONTEXT,
|
||||
EGL_NO_CONFIG_KHR, EGL_NO_CONTEXT,
|
||||
config_attribs);
|
||||
|
||||
if (glamor_egl->context == EGL_NO_CONTEXT) {
|
||||
|
@ -1060,9 +1054,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
goto error;
|
||||
}
|
||||
if (strstr((const char *)renderer, "llvmpipe")) {
|
||||
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
||||
"Refusing to try glamor on llvmpipe\n");
|
||||
goto error;
|
||||
if (scrn->confScreen->num_gpu_devices)
|
||||
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
||||
"Allowing glamor on llvmpipe for PRIME\n");
|
||||
else {
|
||||
xf86DrvMsg(scrn->scrnIndex, X_INFO,
|
||||
"Refusing to try glamor on llvmpipe\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1085,11 +1084,11 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd)
|
|||
"EGL_EXT_image_dma_buf_import") &&
|
||||
epoxy_has_egl_extension(glamor_egl->display,
|
||||
"EGL_EXT_image_dma_buf_import_modifiers")) {
|
||||
if (xf86Info.debug != NULL)
|
||||
glamor_egl->dmabuf_capable = !!strstr(xf86Info.debug,
|
||||
"dmabuf_capable");
|
||||
else
|
||||
glamor_egl->dmabuf_capable = TRUE;
|
||||
if (xf86Info.debug != NULL)
|
||||
glamor_egl->dmabuf_capable = !!strstr(xf86Info.debug,
|
||||
"dmabuf_capable");
|
||||
else
|
||||
glamor_egl->dmabuf_capable = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ glamor_font_get(ScreenPtr screen, FontPtr font)
|
|||
unsigned long count;
|
||||
char *bits;
|
||||
|
||||
if (glamor_priv->glsl_version < 130)
|
||||
if (!glamor_glsl_has_ints(glamor_priv))
|
||||
return NULL;
|
||||
|
||||
privates = FontGetPrivate(font, glamor_font_private_index);
|
||||
|
@ -210,7 +210,7 @@ glamor_font_init(ScreenPtr screen)
|
|||
{
|
||||
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
|
||||
|
||||
if (glamor_priv->glsl_version < 130)
|
||||
if (!glamor_glsl_has_ints(glamor_priv))
|
||||
return TRUE;
|
||||
|
||||
if (glamor_font_generation != serverGeneration) {
|
||||
|
|
|
@ -1,68 +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 <epoxy/glx.h>
|
||||
#include "glamor_context.h"
|
||||
|
||||
/**
|
||||
* @file glamor_glx.c
|
||||
*
|
||||
* GLX context management for glamor.
|
||||
*
|
||||
* This has to be kept separate from the server sources because of
|
||||
* Xlib's conflicting definition of CARD32 and similar typedefs.
|
||||
*/
|
||||
|
||||
static void
|
||||
glamor_glx_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
|
||||
* GLX's no-op context change fast path when switching back to
|
||||
* GLX.
|
||||
*/
|
||||
glXMakeCurrent(glamor_ctx->display, None, None);
|
||||
|
||||
glXMakeCurrent(glamor_ctx->display, glamor_ctx->drawable_xid,
|
||||
glamor_ctx->ctx);
|
||||
}
|
||||
|
||||
|
||||
Bool
|
||||
glamor_glx_screen_init(struct glamor_context *glamor_ctx)
|
||||
{
|
||||
glamor_ctx->ctx = glXGetCurrentContext();
|
||||
if (!glamor_ctx->ctx)
|
||||
return False;
|
||||
|
||||
glamor_ctx->display = glXGetCurrentDisplay();
|
||||
if (!glamor_ctx->display)
|
||||
return False;
|
||||
|
||||
glamor_ctx->drawable_xid = glXGetCurrentDrawable();
|
||||
|
||||
glamor_ctx->make_current = glamor_glx_make_current;
|
||||
|
||||
return True;
|
||||
}
|
|
@ -170,6 +170,11 @@ struct glamor_format {
|
|||
* transferred using format/type.
|
||||
*/
|
||||
CARD32 render_format;
|
||||
/**
|
||||
* Whether rendering is supported in GL at all (i.e. without pixel data conversion
|
||||
* just before upload)
|
||||
*/
|
||||
Bool rendering_supported;
|
||||
};
|
||||
|
||||
struct glamor_saved_procs {
|
||||
|
@ -213,8 +218,14 @@ typedef struct glamor_screen_private {
|
|||
Bool has_texture_swizzle;
|
||||
Bool is_core_profile;
|
||||
Bool can_copyplane;
|
||||
Bool use_gpu_shader4;
|
||||
int max_fbo_size;
|
||||
|
||||
/**
|
||||
* Stores information about supported formats. Note, that this list contains all
|
||||
* supported pixel formats, including these that are not supported on GL side
|
||||
* directly, but are converted to another format instead.
|
||||
*/
|
||||
struct glamor_format formats[33];
|
||||
struct glamor_format cbcr_format;
|
||||
|
||||
|
|
|
@ -187,6 +187,7 @@ fs_location_vars(glamor_program_location locations)
|
|||
|
||||
static const char vs_template[] =
|
||||
"%s" /* version */
|
||||
"%s" /* exts */
|
||||
"%s" /* defines */
|
||||
"%s" /* prim vs_vars */
|
||||
"%s" /* fill vs_vars */
|
||||
|
@ -199,6 +200,7 @@ static const char vs_template[] =
|
|||
|
||||
static const char fs_template[] =
|
||||
"%s" /* version */
|
||||
"%s" /* exts */
|
||||
GLAMOR_DEFAULT_PRECISION
|
||||
"%s" /* defines */
|
||||
"%s" /* prim fs_vars */
|
||||
|
@ -258,10 +260,11 @@ glamor_build_program(ScreenPtr screen,
|
|||
char *fs_vars = NULL;
|
||||
char *vs_vars = NULL;
|
||||
|
||||
char *vs_prog_string;
|
||||
char *fs_prog_string;
|
||||
char *vs_prog_string = NULL;
|
||||
char *fs_prog_string = NULL;
|
||||
|
||||
GLint fs_prog, vs_prog;
|
||||
Bool gpu_shader4 = FALSE;
|
||||
|
||||
if (!fill)
|
||||
fill = &facet_null_fill;
|
||||
|
@ -270,8 +273,14 @@ glamor_build_program(ScreenPtr screen,
|
|||
flags |= fill->flags;
|
||||
version = MAX(version, fill->version);
|
||||
|
||||
if (version > glamor_priv->glsl_version)
|
||||
goto fail;
|
||||
if (version > glamor_priv->glsl_version) {
|
||||
if (version == 130 && !glamor_priv->use_gpu_shader4)
|
||||
goto fail;
|
||||
else {
|
||||
version = 120;
|
||||
gpu_shader4 = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
vs_vars = vs_location_vars(locations);
|
||||
fs_vars = fs_location_vars(locations);
|
||||
|
@ -291,6 +300,7 @@ glamor_build_program(ScreenPtr screen,
|
|||
if (asprintf(&vs_prog_string,
|
||||
vs_template,
|
||||
str(version_string),
|
||||
gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n" : "",
|
||||
str(defines),
|
||||
str(prim->vs_vars),
|
||||
str(fill->vs_vars),
|
||||
|
@ -302,6 +312,7 @@ glamor_build_program(ScreenPtr screen,
|
|||
if (asprintf(&fs_prog_string,
|
||||
fs_template,
|
||||
str(version_string),
|
||||
gpu_shader4 ? "#extension GL_EXT_gpu_shader4 : require\n#define texelFetch texelFetch2D\n#define uint unsigned int\n" : "",
|
||||
str(defines),
|
||||
str(prim->fs_vars),
|
||||
str(fill->fs_vars),
|
||||
|
@ -372,6 +383,8 @@ fail:
|
|||
glDeleteProgram(prog->prog);
|
||||
prog->prog = 0;
|
||||
}
|
||||
free(vs_prog_string);
|
||||
free(fs_prog_string);
|
||||
free(version_string);
|
||||
free(fs_vars);
|
||||
free(vs_vars);
|
||||
|
|
|
@ -69,7 +69,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
|
|||
glamor_bounds_union_rect(&bounds, &prect[i]);
|
||||
}
|
||||
|
||||
if (glamor_priv->glsl_version >= 130) {
|
||||
if (glamor_glsl_has_ints(glamor_priv)) {
|
||||
prog = glamor_use_program_fill(pixmap, gc,
|
||||
&glamor_priv->poly_fill_rect_program,
|
||||
&glamor_facet_polyfillrect_130);
|
||||
|
@ -151,7 +151,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
|
|||
scissor.y1 + off_y,
|
||||
scissor.x2 - scissor.x1,
|
||||
scissor.y2 - scissor.y1);
|
||||
if (glamor_priv->glsl_version >= 130)
|
||||
if (glamor_glsl_has_ints(glamor_priv))
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, nrect);
|
||||
else {
|
||||
glamor_glDrawArrays_GL_QUADS(glamor_priv, nrect);
|
||||
|
@ -163,7 +163,7 @@ glamor_poly_fill_rect_gl(DrawablePtr drawable,
|
|||
|
||||
bail:
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
if (glamor_priv->glsl_version >= 130) {
|
||||
if (glamor_glsl_has_ints(glamor_priv)) {
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_SOURCE, 0);
|
||||
glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
|
||||
|
|
|
@ -773,14 +773,19 @@ glamor_render_format_is_supported(PicturePtr picture)
|
|||
{
|
||||
PictFormatShort storage_format;
|
||||
glamor_screen_private *glamor_priv;
|
||||
struct glamor_format *f;
|
||||
|
||||
/* Source-only pictures should always work */
|
||||
if (!picture->pDrawable)
|
||||
return TRUE;
|
||||
|
||||
glamor_priv = glamor_get_screen_private(picture->pDrawable->pScreen);
|
||||
storage_format =
|
||||
glamor_priv->formats[picture->pDrawable->depth].render_format;
|
||||
f = &glamor_priv->formats[picture->pDrawable->depth];
|
||||
|
||||
if (!f->rendering_supported)
|
||||
return FALSE;
|
||||
|
||||
storage_format = f->render_format;
|
||||
|
||||
switch (picture->format) {
|
||||
case PICT_a2r10g10b10:
|
||||
|
|
|
@ -64,7 +64,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
|
|||
|
||||
glamor_make_current(glamor_priv);
|
||||
|
||||
if (glamor_priv->glsl_version >= 130) {
|
||||
if (glamor_glsl_has_ints(glamor_priv)) {
|
||||
prog = glamor_use_program_fill(pixmap, gc, &glamor_priv->fill_spans_program,
|
||||
&glamor_facet_fillspans_130);
|
||||
|
||||
|
@ -134,7 +134,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
|
|||
box->x2 - box->x1,
|
||||
box->y2 - box->y1);
|
||||
box++;
|
||||
if (glamor_priv->glsl_version >= 130)
|
||||
if (glamor_glsl_has_ints(glamor_priv))
|
||||
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, n);
|
||||
else {
|
||||
glamor_glDrawArrays_GL_QUADS(glamor_priv, n);
|
||||
|
@ -146,7 +146,7 @@ glamor_fill_spans_gl(DrawablePtr drawable,
|
|||
|
||||
bail:
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
if (glamor_priv->glsl_version >= 130)
|
||||
if (glamor_glsl_has_ints(glamor_priv))
|
||||
glVertexAttribDivisor(GLAMOR_VERTEX_POS, 0);
|
||||
glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
|
||||
|
||||
|
|
|
@ -732,5 +732,9 @@ glamor_glDrawArrays_GL_QUADS(glamor_screen_private *glamor_priv, unsigned count)
|
|||
}
|
||||
}
|
||||
|
||||
static inline Bool
|
||||
glamor_glsl_has_ints(glamor_screen_private *glamor_priv) {
|
||||
return glamor_priv->glsl_version >= 130 || glamor_priv->use_gpu_shader4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,6 @@ srcs_glamor = [
|
|||
'glamor_core.c',
|
||||
'glamor_dash.c',
|
||||
'glamor_font.c',
|
||||
'glamor_glx.c',
|
||||
'glamor_composite_glyphs.c',
|
||||
'glamor_image.c',
|
||||
'glamor_lines.c',
|
||||
|
|
|
@ -487,8 +487,15 @@ __glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client,
|
|||
__GLXscreen *pGlxScreen;
|
||||
int rc;
|
||||
|
||||
if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
|
||||
DixWriteAccess, &pGlxDraw, &rc)) {
|
||||
rc = dixLookupResourceByType((void **)&pGlxDraw, drawId,
|
||||
__glXDrawableRes, client, DixWriteAccess);
|
||||
if (rc == Success &&
|
||||
/* If pGlxDraw->drawId == drawId, drawId is a valid GLX drawable.
|
||||
* Otherwise, if pGlxDraw->type == GLX_DRAWABLE_WINDOW, drawId is
|
||||
* an X window, but the client has already created a GLXWindow
|
||||
* associated with it, so we don't want to create another one. */
|
||||
(pGlxDraw->drawId == drawId ||
|
||||
pGlxDraw->type == GLX_DRAWABLE_WINDOW)) {
|
||||
if (glxc != NULL &&
|
||||
glxc->config != NULL &&
|
||||
glxc->config != pGlxDraw->config) {
|
||||
|
@ -655,11 +662,12 @@ xorgGlxMakeCurrent(ClientPtr client, GLXContextTag tag, XID drawId, XID readId,
|
|||
glxc->readPriv = NULL;
|
||||
return __glXError(GLXBadContext);
|
||||
}
|
||||
|
||||
glxc->currentClient = client;
|
||||
glxServer.setContextTagPrivate(client, newContextTag, glxc);
|
||||
}
|
||||
|
||||
glxServer.setContextTagPrivate(client, newContextTag, glxc);
|
||||
if (glxc)
|
||||
glxc->currentClient = client;
|
||||
|
||||
if (prevglxc) {
|
||||
prevglxc->currentClient = NULL;
|
||||
if (!prevglxc->idExists) {
|
||||
|
@ -985,7 +993,6 @@ __glXDisp_GetVisualConfigs(__GLXclientState * cl, GLbyte * pc)
|
|||
/* Pad with zeroes, so that attributes count is constant. */
|
||||
while (p < GLX_VIS_CONFIG_TOTAL) {
|
||||
buf[p++] = 0;
|
||||
buf[p++] = 0;
|
||||
}
|
||||
|
||||
assert(p == GLX_VIS_CONFIG_TOTAL);
|
||||
|
@ -1874,7 +1881,7 @@ DoGetDrawableAttributes(__GLXclientState * cl, XID drawId)
|
|||
int err = dixLookupWindow((WindowPtr *)&pDraw, drawId, client,
|
||||
DixGetAttrAccess);
|
||||
if (err != Success)
|
||||
return error;
|
||||
return __glXError(GLXBadDrawable);
|
||||
}
|
||||
if (pGlxDraw)
|
||||
pDraw = pGlxDraw->pDraw;
|
||||
|
|
|
@ -115,6 +115,16 @@ render_type_is_pbuffer_only(unsigned renderType)
|
|||
| __DRI_ATTRIB_FLOAT_BIT));
|
||||
}
|
||||
|
||||
static int
|
||||
server_has_depth(int depth)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < screenInfo.numPixmapFormats; i++)
|
||||
if (screenInfo.formats[i].depth == depth)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __GLXconfig *
|
||||
createModeFromConfig(const __DRIcoreExtension * core,
|
||||
const __DRIconfig * driConfig,
|
||||
|
@ -178,6 +188,16 @@ createModeFromConfig(const __DRIcoreExtension * core,
|
|||
if (!render_type_is_pbuffer_only(renderType))
|
||||
drawableType |= GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
|
||||
|
||||
/* Make sure we don't advertise things the server isn't configured for */
|
||||
if ((drawableType & (GLX_PBUFFER_BIT | GLX_PIXMAP_BIT)) &&
|
||||
!server_has_depth(config->config.rgbBits)) {
|
||||
drawableType &= ~(GLX_PBUFFER_BIT | GLX_PIXMAP_BIT);
|
||||
if (!drawableType) {
|
||||
free(config);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
config->config.next = NULL;
|
||||
config->config.visualType = visualType;
|
||||
config->config.renderType = renderType;
|
||||
|
|
|
@ -92,6 +92,9 @@ static void SetReplyHeader(ClientPtr client, void *replyPtr)
|
|||
xGenericReply *rep = (xGenericReply *) replyPtr;
|
||||
rep->type = X_Reply;
|
||||
rep->sequenceNumber = client->sequence;
|
||||
if (client->swapped) {
|
||||
swaps(&rep->sequenceNumber);
|
||||
}
|
||||
rep->length = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,11 @@ deprecated, use \fI\-listenfd\fP instead.
|
|||
Add given fd as a listen socket. This option is used by the \fIWayland\fP
|
||||
server to pass \fIXwayland\fP the socket where X clients connect.
|
||||
.TP 8
|
||||
.B \-noTouchPointerEmulation
|
||||
Disable touch pointer emulation. This allows the Wayland compositor to
|
||||
implement its own pointer emulation mechanism for X11 clients that don't
|
||||
support touch input.
|
||||
.TP 8
|
||||
.B \-rootless
|
||||
Run \fIXwayland\fP rootless, so that X clients integrate seamlessly with
|
||||
Wayland clients in a Wayland desktop. That requires the Wayland server
|
||||
|
|
|
@ -4,6 +4,8 @@ srcs = [
|
|||
'xwayland-input.h',
|
||||
'xwayland-cursor.c',
|
||||
'xwayland-cursor.h',
|
||||
'xwayland-drm-lease.h',
|
||||
'xwayland-drm-lease.c',
|
||||
'xwayland-glamor.h',
|
||||
'xwayland-glx.h',
|
||||
'xwayland-pixmap.c',
|
||||
|
@ -36,12 +38,14 @@ protodir = protocols_dep.get_pkgconfig_variable('pkgdatadir')
|
|||
|
||||
pointer_xml = join_paths(protodir, 'unstable', 'pointer-constraints', 'pointer-constraints-unstable-v1.xml')
|
||||
relative_xml = join_paths(protodir, 'unstable', 'relative-pointer', 'relative-pointer-unstable-v1.xml')
|
||||
gestures_xml = join_paths(protodir, 'unstable', 'pointer-gestures', 'pointer-gestures-unstable-v1.xml')
|
||||
tablet_xml = join_paths(protodir, 'unstable', 'tablet', 'tablet-unstable-v2.xml')
|
||||
kbgrab_xml = join_paths(protodir, 'unstable', 'xwayland-keyboard-grab', 'xwayland-keyboard-grab-unstable-v1.xml')
|
||||
xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output', 'xdg-output-unstable-v1.xml')
|
||||
dmabuf_xml = join_paths(protodir, 'unstable', 'linux-dmabuf', 'linux-dmabuf-unstable-v1.xml')
|
||||
viewporter_xml = join_paths(protodir, 'stable', 'viewporter', 'viewporter.xml')
|
||||
xdg_shell_xml = join_paths(protodir, 'stable', 'xdg-shell', 'xdg-shell.xml')
|
||||
drm_lease_xml = join_paths(protodir, 'staging', 'drm-lease', 'drm-lease-v1.xml')
|
||||
|
||||
client_header = generator(scanner,
|
||||
output : '@BASENAME@-client-protocol.h',
|
||||
|
@ -60,20 +64,24 @@ code = generator(scanner,
|
|||
)
|
||||
srcs += client_header.process(relative_xml)
|
||||
srcs += client_header.process(pointer_xml)
|
||||
srcs += client_header.process(gestures_xml)
|
||||
srcs += client_header.process(tablet_xml)
|
||||
srcs += client_header.process(kbgrab_xml)
|
||||
srcs += client_header.process(xdg_output_xml)
|
||||
srcs += client_header.process(dmabuf_xml)
|
||||
srcs += client_header.process(viewporter_xml)
|
||||
srcs += client_header.process(xdg_shell_xml)
|
||||
srcs += client_header.process(drm_lease_xml)
|
||||
srcs += code.process(relative_xml)
|
||||
srcs += code.process(pointer_xml)
|
||||
srcs += code.process(gestures_xml)
|
||||
srcs += code.process(tablet_xml)
|
||||
srcs += code.process(kbgrab_xml)
|
||||
srcs += code.process(xdg_output_xml)
|
||||
srcs += code.process(dmabuf_xml)
|
||||
srcs += code.process(viewporter_xml)
|
||||
srcs += code.process(xdg_shell_xml)
|
||||
srcs += code.process(drm_lease_xml)
|
||||
|
||||
xwayland_glamor = []
|
||||
eglstream_srcs = []
|
||||
|
@ -113,6 +121,10 @@ if build_glx
|
|||
wayland_inc += glx_inc
|
||||
endif
|
||||
|
||||
if libdrm_dep.found()
|
||||
xwayland_dep += libdrm_dep
|
||||
endif
|
||||
|
||||
xwayland_server = executable(
|
||||
'Xwayland',
|
||||
srcs,
|
||||
|
@ -137,6 +149,8 @@ xwayland_server = executable(
|
|||
)
|
||||
|
||||
xwayland_data = configuration_data()
|
||||
xwayland_data.set('prefix', get_option('prefix'))
|
||||
xwayland_data.set('exec_prefix', '${prefix}')
|
||||
xwayland_data.set('PACKAGE_VERSION', meson.project_version())
|
||||
xwayland_data.set('xwayland_path', xwayland_path)
|
||||
xwayland_data.set('have_glamor', build_glamor ? 'true' : 'false')
|
||||
|
|
|
@ -54,9 +54,11 @@ expand_source_and_mask(CursorPtr cursor, CARD32 *data)
|
|||
|
||||
p = data;
|
||||
fg = ((cursor->foreRed & 0xff00) << 8) |
|
||||
(cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8);
|
||||
(cursor->foreGreen & 0xff00) |
|
||||
(cursor->foreBlue >> 8);
|
||||
bg = ((cursor->backRed & 0xff00) << 8) |
|
||||
(cursor->backGreen & 0xff00) | (cursor->backGreen >> 8);
|
||||
(cursor->backGreen & 0xff00) |
|
||||
(cursor->backBlue >> 8);
|
||||
stride = BitmapBytePad(bits->width);
|
||||
for (y = 0; y < bits->height; y++)
|
||||
for (x = 0; x < bits->width; x++) {
|
||||
|
@ -111,15 +113,6 @@ xwl_unrealize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
|
|||
return xwl_shm_destroy_pixmap(pixmap);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_cursor_frame_callback(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
if (xwl_cursor->frame_cb) {
|
||||
wl_callback_destroy (xwl_cursor->frame_cb);
|
||||
xwl_cursor->frame_cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
frame_callback(void *data,
|
||||
struct wl_callback *callback,
|
||||
|
@ -127,7 +120,7 @@ frame_callback(void *data,
|
|||
{
|
||||
struct xwl_cursor *xwl_cursor = data;
|
||||
|
||||
clear_cursor_frame_callback(xwl_cursor);
|
||||
xwl_cursor_clear_frame_cb(xwl_cursor);
|
||||
if (xwl_cursor->needs_update) {
|
||||
xwl_cursor->needs_update = FALSE;
|
||||
xwl_cursor->update_proc(xwl_cursor);
|
||||
|
@ -162,8 +155,15 @@ static void
|
|||
xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
|
||||
struct xwl_cursor *xwl_cursor, PixmapPtr pixmap)
|
||||
{
|
||||
wl_surface_attach(xwl_cursor->surface,
|
||||
xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
|
||||
struct wl_buffer *buffer;
|
||||
|
||||
buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
|
||||
if (!buffer) {
|
||||
ErrorF("cursor: Error getting buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_surface_attach(xwl_cursor->surface, buffer, 0, 0);
|
||||
xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
|
||||
xwl_seat->x_cursor->bits->width,
|
||||
xwl_seat->x_cursor->bits->height);
|
||||
|
@ -180,6 +180,18 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
|
|||
wl_surface_commit(xwl_cursor->surface);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_cursor_clear_frame_cb(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
if (xwl_cursor->frame_cb) {
|
||||
wl_callback_destroy(xwl_cursor->frame_cb);
|
||||
xwl_cursor->frame_cb = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
|
@ -193,7 +205,7 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
|
|||
if (!xwl_seat->x_cursor) {
|
||||
wl_pointer_set_cursor(xwl_seat->wl_pointer,
|
||||
xwl_seat->pointer_enter_serial, NULL, 0, 0);
|
||||
clear_cursor_frame_callback(xwl_cursor);
|
||||
xwl_cursor_clear_frame_cb(xwl_cursor);
|
||||
xwl_cursor->needs_update = FALSE;
|
||||
return;
|
||||
}
|
||||
|
@ -231,7 +243,7 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
|||
zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
|
||||
xwl_tablet_tool->proximity_in_serial,
|
||||
NULL, 0, 0);
|
||||
clear_cursor_frame_callback(xwl_cursor);
|
||||
xwl_cursor_clear_frame_cb(xwl_cursor);
|
||||
xwl_cursor->needs_update = FALSE;
|
||||
return;
|
||||
}
|
||||
|
@ -257,8 +269,15 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
|
|||
xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_cursor_release(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
wl_surface_destroy(xwl_cursor->surface);
|
||||
xwl_cursor_clear_frame_cb(xwl_cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_seat_update_cursor(struct xwl_seat *xwl_seat)
|
||||
xwl_seat_update_all_cursors(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
struct xwl_tablet_tool *xwl_tablet_tool;
|
||||
|
||||
|
@ -278,7 +297,7 @@ xwl_seat_update_cursor_visibility(struct xwl_seat *xwl_seat)
|
|||
{
|
||||
xwl_seat->x_cursor = xwl_seat->pending_x_cursor;
|
||||
xwl_seat_cursor_visibility_changed(xwl_seat);
|
||||
xwl_seat_update_cursor(xwl_seat);
|
||||
xwl_seat_update_all_cursors(xwl_seat);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -332,7 +351,7 @@ xwl_set_cursor(DeviceIntPtr device,
|
|||
/* Cursor remains shown or hidden, apply the change immediately */
|
||||
xwl_set_cursor_free_timer(xwl_seat);
|
||||
xwl_seat->x_cursor = cursor;
|
||||
xwl_seat_update_cursor(xwl_seat);
|
||||
xwl_seat_update_all_cursors(xwl_seat);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <xwayland-types.h>
|
||||
#include <xwayland-input.h>
|
||||
|
||||
Bool xwl_cursor_clear_frame_cb(struct xwl_cursor *xwl_cursor);
|
||||
void xwl_cursor_release(struct xwl_cursor *xwl_cursor);
|
||||
void xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *tool);
|
||||
void xwl_seat_set_cursor(struct xwl_seat *xwl_seat);
|
||||
Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/* Copied from hw/xfree86/modes/xf86cvt.c into xwayland DDX and
|
||||
* changed to generate an RRMode */
|
||||
|
||||
/*
|
||||
* Copyright 2005-2006 Luc Verhaegen.
|
||||
* Copyright © 2021 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"),
|
||||
|
@ -23,284 +21,38 @@
|
|||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The reason for having this function in a file of its own is
|
||||
* so that ../utils/cvt/cvt can link to it, and that xf86CVTMode
|
||||
* code is shared directly.
|
||||
*/
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <randrstr.h>
|
||||
#include <libxcvt/libxcvt.h>
|
||||
|
||||
#include "xwayland-cvt.h"
|
||||
|
||||
/*
|
||||
* Generate a CVT standard mode from HDisplay, VDisplay and VRefresh.
|
||||
*
|
||||
* These calculations are stolen from the CVT calculation spreadsheet written
|
||||
* by Graham Loveridge. He seems to be claiming no copyright and there seems to
|
||||
* be no license attached to this. He apparently just wants to see his name
|
||||
* mentioned.
|
||||
*
|
||||
* This file can be found at http://www.vesa.org/Public/CVT/CVTd6r1.xls
|
||||
*
|
||||
* Comments and structure corresponds to the comments and structure of the xls.
|
||||
* This should ease importing of future changes to the standard (not very
|
||||
* likely though).
|
||||
*
|
||||
* About margins; i'm sure that they are to be the bit between HDisplay and
|
||||
* HBlankStart, HBlankEnd and HTotal, VDisplay and VBlankStart, VBlankEnd and
|
||||
* VTotal, where the overscan colour is shown. FB seems to call _all_ blanking
|
||||
* outside sync "margin" for some reason. Since we prefer seeing proper
|
||||
* blanking instead of the overscan colour, and since the Crtc* values will
|
||||
* probably get altered after us, we will disable margins altogether. With
|
||||
* these calculations, Margins will plainly expand H/VDisplay, and we don't
|
||||
* want that. -- libv
|
||||
*
|
||||
*/
|
||||
RRModePtr
|
||||
xwayland_cvt(int HDisplay, int VDisplay, float VRefresh, Bool Reduced,
|
||||
Bool Interlaced)
|
||||
xwayland_cvt(int hdisplay, int vdisplay, float vrefresh, Bool reduced,
|
||||
Bool interlaced)
|
||||
{
|
||||
/* 1) top/bottom margin size (% of height) - default: 1.8 */
|
||||
#define CVT_MARGIN_PERCENTAGE 1.8
|
||||
|
||||
/* 2) character cell horizontal granularity (pixels) - default 8 */
|
||||
#define CVT_H_GRANULARITY 8
|
||||
|
||||
/* 4) Minimum vertical porch (lines) - default 3 */
|
||||
#define CVT_MIN_V_PORCH 3
|
||||
|
||||
/* 4) Minimum number of vertical back porch lines - default 6 */
|
||||
#define CVT_MIN_V_BPORCH 6
|
||||
|
||||
/* Pixel Clock step (kHz) */
|
||||
#define CVT_CLOCK_STEP 250
|
||||
|
||||
Bool Margins = FALSE;
|
||||
float VFieldRate, HPeriod;
|
||||
int HDisplayRnd, HMargin;
|
||||
int VDisplayRnd, VMargin, VSync;
|
||||
float Interlace; /* Please rename this */
|
||||
struct libxcvt_mode_info *libxcvt_mode_info;
|
||||
char name[128];
|
||||
xRRModeInfo modeinfo;
|
||||
|
||||
libxcvt_mode_info =
|
||||
libxcvt_gen_mode_info(hdisplay, vdisplay, vrefresh, reduced, interlaced);
|
||||
|
||||
memset(&modeinfo, 0, sizeof modeinfo);
|
||||
modeinfo.width = libxcvt_mode_info->hdisplay;
|
||||
modeinfo.height = libxcvt_mode_info->vdisplay;
|
||||
modeinfo.dotClock = libxcvt_mode_info->dot_clock * 1000.0;
|
||||
modeinfo.hSyncStart = libxcvt_mode_info->hsync_start;
|
||||
modeinfo.hSyncEnd = libxcvt_mode_info->hsync_end;
|
||||
modeinfo.hTotal = libxcvt_mode_info->htotal;
|
||||
modeinfo.vSyncStart = libxcvt_mode_info->vsync_start;
|
||||
modeinfo.vSyncEnd = libxcvt_mode_info->vsync_end;
|
||||
modeinfo.vTotal = libxcvt_mode_info->vtotal;
|
||||
modeinfo.modeFlags = libxcvt_mode_info->mode_flags;
|
||||
|
||||
/* CVT default is 60.0Hz */
|
||||
if (!VRefresh)
|
||||
VRefresh = 60.0;
|
||||
|
||||
/* 1. Required field rate */
|
||||
if (Interlaced)
|
||||
VFieldRate = VRefresh * 2;
|
||||
else
|
||||
VFieldRate = VRefresh;
|
||||
|
||||
/* 2. Horizontal pixels */
|
||||
HDisplayRnd = HDisplay - (HDisplay % CVT_H_GRANULARITY);
|
||||
|
||||
/* 3. Determine left and right borders */
|
||||
if (Margins) {
|
||||
/* right margin is actually exactly the same as left */
|
||||
HMargin = (((float) HDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
|
||||
HMargin -= HMargin % CVT_H_GRANULARITY;
|
||||
}
|
||||
else
|
||||
HMargin = 0;
|
||||
|
||||
/* 4. Find total active pixels */
|
||||
modeinfo.width = HDisplayRnd + 2 * HMargin;
|
||||
|
||||
/* 5. Find number of lines per field */
|
||||
if (Interlaced)
|
||||
VDisplayRnd = VDisplay / 2;
|
||||
else
|
||||
VDisplayRnd = VDisplay;
|
||||
|
||||
/* 6. Find top and bottom margins */
|
||||
/* nope. */
|
||||
if (Margins)
|
||||
/* top and bottom margins are equal again. */
|
||||
VMargin = (((float) VDisplayRnd) * CVT_MARGIN_PERCENTAGE / 100.0);
|
||||
else
|
||||
VMargin = 0;
|
||||
|
||||
modeinfo.height = VDisplay + 2 * VMargin;
|
||||
|
||||
/* 7. Interlace */
|
||||
if (Interlaced)
|
||||
Interlace = 0.5;
|
||||
else
|
||||
Interlace = 0.0;
|
||||
|
||||
/* Determine VSync Width from aspect ratio */
|
||||
if (!(VDisplay % 3) && ((VDisplay * 4 / 3) == HDisplay))
|
||||
VSync = 4;
|
||||
else if (!(VDisplay % 9) && ((VDisplay * 16 / 9) == HDisplay))
|
||||
VSync = 5;
|
||||
else if (!(VDisplay % 10) && ((VDisplay * 16 / 10) == HDisplay))
|
||||
VSync = 6;
|
||||
else if (!(VDisplay % 4) && ((VDisplay * 5 / 4) == HDisplay))
|
||||
VSync = 7;
|
||||
else if (!(VDisplay % 9) && ((VDisplay * 15 / 9) == HDisplay))
|
||||
VSync = 7;
|
||||
else /* Custom */
|
||||
VSync = 10;
|
||||
|
||||
if (!Reduced) { /* simplified GTF calculation */
|
||||
|
||||
/* 4) Minimum time of vertical sync + back porch interval (µs)
|
||||
* default 550.0 */
|
||||
#define CVT_MIN_VSYNC_BP 550.0
|
||||
|
||||
/* 3) Nominal HSync width (% of line period) - default 8 */
|
||||
#define CVT_HSYNC_PERCENTAGE 8
|
||||
|
||||
float HBlankPercentage;
|
||||
int VSyncAndBackPorch, VBackPorch;
|
||||
int HBlank;
|
||||
|
||||
/* 8. Estimated Horizontal period */
|
||||
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_MIN_VSYNC_BP)) /
|
||||
(VDisplayRnd + 2 * VMargin + CVT_MIN_V_PORCH + Interlace);
|
||||
|
||||
/* 9. Find number of lines in sync + backporch */
|
||||
if (((int) (CVT_MIN_VSYNC_BP / HPeriod) + 1) <
|
||||
(VSync + CVT_MIN_V_PORCH))
|
||||
VSyncAndBackPorch = VSync + CVT_MIN_V_PORCH;
|
||||
else
|
||||
VSyncAndBackPorch = (int) (CVT_MIN_VSYNC_BP / HPeriod) + 1;
|
||||
|
||||
/* 10. Find number of lines in back porch */
|
||||
VBackPorch = VSyncAndBackPorch - VSync;
|
||||
(void) VBackPorch;
|
||||
|
||||
/* 11. Find total number of lines in vertical field */
|
||||
modeinfo.vTotal =
|
||||
VDisplayRnd + 2 * VMargin + VSyncAndBackPorch + Interlace +
|
||||
CVT_MIN_V_PORCH;
|
||||
|
||||
/* 5) Definition of Horizontal blanking time limitation */
|
||||
/* Gradient (%/kHz) - default 600 */
|
||||
#define CVT_M_FACTOR 600
|
||||
|
||||
/* Offset (%) - default 40 */
|
||||
#define CVT_C_FACTOR 40
|
||||
|
||||
/* Blanking time scaling factor - default 128 */
|
||||
#define CVT_K_FACTOR 128
|
||||
|
||||
/* Scaling factor weighting - default 20 */
|
||||
#define CVT_J_FACTOR 20
|
||||
|
||||
#define CVT_M_PRIME CVT_M_FACTOR * CVT_K_FACTOR / 256
|
||||
#define CVT_C_PRIME (CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \
|
||||
CVT_J_FACTOR
|
||||
|
||||
/* 12. Find ideal blanking duty cycle from formula */
|
||||
HBlankPercentage = CVT_C_PRIME - CVT_M_PRIME * HPeriod / 1000.0;
|
||||
|
||||
/* 13. Blanking time */
|
||||
if (HBlankPercentage < 20)
|
||||
HBlankPercentage = 20;
|
||||
|
||||
HBlank = modeinfo.width * HBlankPercentage / (100.0 - HBlankPercentage);
|
||||
HBlank -= HBlank % (2 * CVT_H_GRANULARITY);
|
||||
|
||||
/* 14. Find total number of pixels in a line. */
|
||||
modeinfo.hTotal = modeinfo.width + HBlank;
|
||||
|
||||
/* Fill in HSync values */
|
||||
modeinfo.hSyncEnd = modeinfo.width + HBlank / 2;
|
||||
|
||||
modeinfo.hSyncStart = modeinfo.hSyncEnd -
|
||||
(modeinfo.hTotal * CVT_HSYNC_PERCENTAGE) / 100;
|
||||
modeinfo.hSyncStart += CVT_H_GRANULARITY -
|
||||
modeinfo.hSyncStart % CVT_H_GRANULARITY;
|
||||
|
||||
/* Fill in VSync values */
|
||||
modeinfo.vSyncStart = modeinfo.height + CVT_MIN_V_PORCH;
|
||||
modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
|
||||
|
||||
}
|
||||
else { /* Reduced blanking */
|
||||
/* Minimum vertical blanking interval time (µs) - default 460 */
|
||||
#define CVT_RB_MIN_VBLANK 460.0
|
||||
|
||||
/* Fixed number of clocks for horizontal sync */
|
||||
#define CVT_RB_H_SYNC 32.0
|
||||
|
||||
/* Fixed number of clocks for horizontal blanking */
|
||||
#define CVT_RB_H_BLANK 160.0
|
||||
|
||||
/* Fixed number of lines for vertical front porch - default 3 */
|
||||
#define CVT_RB_VFPORCH 3
|
||||
|
||||
int VBILines;
|
||||
|
||||
/* 8. Estimate Horizontal period. */
|
||||
HPeriod = ((float) (1000000.0 / VFieldRate - CVT_RB_MIN_VBLANK)) /
|
||||
(VDisplayRnd + 2 * VMargin);
|
||||
|
||||
/* 9. Find number of lines in vertical blanking */
|
||||
VBILines = ((float) CVT_RB_MIN_VBLANK) / HPeriod + 1;
|
||||
|
||||
/* 10. Check if vertical blanking is sufficient */
|
||||
if (VBILines < (CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH))
|
||||
VBILines = CVT_RB_VFPORCH + VSync + CVT_MIN_V_BPORCH;
|
||||
|
||||
/* 11. Find total number of lines in vertical field */
|
||||
modeinfo.vTotal = VDisplayRnd + 2 * VMargin + Interlace + VBILines;
|
||||
|
||||
/* 12. Find total number of pixels in a line */
|
||||
modeinfo.hTotal = modeinfo.width + CVT_RB_H_BLANK;
|
||||
|
||||
/* Fill in HSync values */
|
||||
modeinfo.hSyncEnd = modeinfo.width + CVT_RB_H_BLANK / 2;
|
||||
modeinfo.hSyncStart = modeinfo.hSyncEnd - CVT_RB_H_SYNC;
|
||||
|
||||
/* Fill in VSync values */
|
||||
modeinfo.vSyncStart = modeinfo.height + CVT_RB_VFPORCH;
|
||||
modeinfo.vSyncEnd = modeinfo.vSyncStart + VSync;
|
||||
}
|
||||
|
||||
/* 15/13. Find pixel clock frequency (kHz for xf86) */
|
||||
modeinfo.dotClock = modeinfo.hTotal * 1000.0 / HPeriod;
|
||||
modeinfo.dotClock -= modeinfo.dotClock % CVT_CLOCK_STEP;
|
||||
modeinfo.dotClock *= 1000.0;
|
||||
#if 0
|
||||
/* 16/14. Find actual Horizontal Frequency (kHz) */
|
||||
modeinfo.hSync = ((float) modeinfo.dotClock) / ((float) modeinfo.hTotal);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* 17/15. Find actual Field rate */
|
||||
modeinfo.vRefresh = (1000.0 * ((float) modeinfo.dotClock)) /
|
||||
((float) (modeinfo.hTotal * modeinfo.vTotal));
|
||||
#endif
|
||||
|
||||
/* 18/16. Find actual vertical frame frequency */
|
||||
/* ignore - just set the mode flag for interlaced */
|
||||
if (Interlaced)
|
||||
modeinfo.vTotal *= 2;
|
||||
|
||||
if (Reduced)
|
||||
modeinfo.modeFlags |= RR_HSyncPositive | RR_VSyncNegative;
|
||||
else
|
||||
modeinfo.modeFlags |= RR_HSyncNegative | RR_VSyncPositive;
|
||||
|
||||
if (Interlaced)
|
||||
modeinfo.modeFlags |= RR_Interlace;
|
||||
|
||||
/* FWXGA hack adapted from hw/xfree86/modes/xf86EdidModes.c, because you can't say 1366 */
|
||||
if (HDisplay == 1366 && VDisplay == 768) {
|
||||
modeinfo.width = 1366;
|
||||
modeinfo.hSyncStart--;
|
||||
modeinfo.hSyncEnd--;
|
||||
}
|
||||
free(libxcvt_mode_info);
|
||||
|
||||
snprintf(name, sizeof name, "%dx%d",
|
||||
modeinfo.width, modeinfo.height);
|
||||
|
|
|
@ -0,0 +1,440 @@
|
|||
/*
|
||||
* Copyright © 2020 Drew Devault
|
||||
* Copyright © 2021 Xaver Hugl
|
||||
*
|
||||
* 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 the
|
||||
* copyright holders not be used in advertising or publicity
|
||||
* pertaining to distribution of the software without specific,
|
||||
* written prior permission. The 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.
|
||||
*/
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#ifdef WITH_LIBDRM
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#endif
|
||||
|
||||
#include "xwayland-drm-lease.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-output.h"
|
||||
|
||||
static void
|
||||
drm_lease_handle_lease_fd(void *data,
|
||||
struct wp_drm_lease_v1 *wp_drm_lease_v1,
|
||||
int32_t lease_fd)
|
||||
{
|
||||
struct xwl_drm_lease *lease = (struct xwl_drm_lease *)data;
|
||||
|
||||
lease->fd = lease_fd;
|
||||
AttendClient(lease->client);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_lease_handle_finished(void *data,
|
||||
struct wp_drm_lease_v1 *wp_drm_lease_v1)
|
||||
{
|
||||
struct xwl_drm_lease *lease = (struct xwl_drm_lease *)data;
|
||||
struct xwl_output *output;
|
||||
int i;
|
||||
|
||||
if (lease->fd >= 0) {
|
||||
RRTerminateLease(lease->rrLease);
|
||||
} else {
|
||||
AttendClient(lease->client);
|
||||
for (i = 0; i < lease->rrLease->numOutputs; ++i) {
|
||||
output = lease->rrLease->outputs[i]->devPrivate;
|
||||
output->lease = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct wp_drm_lease_v1_listener drm_lease_listener = {
|
||||
.lease_fd = drm_lease_handle_lease_fd,
|
||||
.finished = drm_lease_handle_finished,
|
||||
};
|
||||
|
||||
void
|
||||
xwl_randr_get_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr *rrLease, int *fd)
|
||||
{
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_drm_lease *lease;
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
xorg_list_for_each_entry(lease, &xwl_screen->drm_leases, link) {
|
||||
if (lease->client == client) {
|
||||
*rrLease = lease->rrLease;
|
||||
*fd = lease->fd;
|
||||
if (lease->fd < 0)
|
||||
xorg_list_del(&lease->link);
|
||||
return;
|
||||
}
|
||||
}
|
||||
*rrLease = NULL;
|
||||
*fd = -1;
|
||||
}
|
||||
|
||||
int
|
||||
xwl_randr_request_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr rrLease)
|
||||
{
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct wp_drm_lease_request_v1 *req;
|
||||
struct xwl_drm_lease *lease_private;
|
||||
struct xwl_drm_lease_device *lease_device = NULL;
|
||||
struct xwl_drm_lease_device *device_data;
|
||||
struct xwl_output *output;
|
||||
int i;
|
||||
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
if (xorg_list_is_empty(&xwl_screen->drm_lease_devices)) {
|
||||
ErrorF("Attempted to create DRM lease without wp_drm_lease_device_v1\n");
|
||||
return BadMatch;
|
||||
}
|
||||
|
||||
xorg_list_for_each_entry(device_data, &xwl_screen->drm_lease_devices, link) {
|
||||
Bool connectors_of_device = FALSE;
|
||||
for (i = 0; i < rrLease->numOutputs; ++i) {
|
||||
output = rrLease->outputs[i]->devPrivate;
|
||||
if (output->lease_device == device_data) {
|
||||
connectors_of_device = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (connectors_of_device) {
|
||||
if (lease_device != NULL) {
|
||||
ErrorF("Attempted to create DRM lease from multiple devices\n");
|
||||
return BadValue;
|
||||
}
|
||||
lease_device = device_data;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < rrLease->numOutputs; ++i) {
|
||||
output = rrLease->outputs[i]->devPrivate;
|
||||
if (!output || !output->lease_connector || output->lease) {
|
||||
return BadValue;
|
||||
}
|
||||
}
|
||||
|
||||
req = wp_drm_lease_device_v1_create_lease_request(
|
||||
lease_device->drm_lease_device);
|
||||
lease_private = calloc(1, sizeof(struct xwl_drm_lease));
|
||||
for (i = 0; i < rrLease->numOutputs; ++i) {
|
||||
output = rrLease->outputs[i]->devPrivate;
|
||||
output->lease = lease_private;
|
||||
wp_drm_lease_request_v1_request_connector(req, output->lease_connector);
|
||||
}
|
||||
lease_private->fd = -1;
|
||||
lease_private->lease = wp_drm_lease_request_v1_submit(req);
|
||||
lease_private->rrLease = rrLease;
|
||||
lease_private->client = client;
|
||||
rrLease->devPrivate = lease_private;
|
||||
|
||||
wp_drm_lease_v1_add_listener(lease_private->lease,
|
||||
&drm_lease_listener, lease_private);
|
||||
xorg_list_add(&lease_private->link, &xwl_screen->drm_leases);
|
||||
|
||||
ResetCurrentRequest(client);
|
||||
client->sequence--;
|
||||
IgnoreClient(client);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_randr_terminate_lease(ScreenPtr screen, RRLeasePtr lease)
|
||||
{
|
||||
struct xwl_drm_lease *lease_private = lease->devPrivate;
|
||||
|
||||
if (lease_private) {
|
||||
xorg_list_del(&lease_private->link);
|
||||
if (lease_private->fd >= 0)
|
||||
close(lease_private->fd);
|
||||
wp_drm_lease_v1_destroy(lease_private->lease);
|
||||
free(lease_private);
|
||||
lease->devPrivate = NULL;
|
||||
}
|
||||
|
||||
RRLeaseTerminated(lease);
|
||||
}
|
||||
|
||||
static void
|
||||
lease_connector_handle_name(void *data,
|
||||
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
|
||||
const char *name)
|
||||
{
|
||||
/* This space is deliberately left blank */
|
||||
}
|
||||
|
||||
static void
|
||||
lease_connector_handle_description(void *data,
|
||||
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
|
||||
const char *description)
|
||||
{
|
||||
/* This space is deliberately left blank */
|
||||
}
|
||||
|
||||
static RRModePtr *
|
||||
xwl_get_rrmodes_from_connector_id(int drm, int32_t connector_id, int *nmode, int *npref)
|
||||
{
|
||||
#ifdef WITH_LIBDRM
|
||||
drmModeConnectorPtr conn;
|
||||
drmModeModeInfoPtr kmode;
|
||||
RRModePtr *rrmodes;
|
||||
int pref, i;
|
||||
|
||||
*nmode = *npref = 0;
|
||||
|
||||
conn = drmModeGetConnectorCurrent(drm, connector_id);
|
||||
if (!conn) {
|
||||
ErrorF("drmModeGetConnector for connector %d failed\n", connector_id);
|
||||
return NULL;
|
||||
}
|
||||
rrmodes = xallocarray(conn->count_modes, sizeof(RRModePtr));
|
||||
if (!rrmodes) {
|
||||
ErrorF("Failed to allocate connector modes\n");
|
||||
drmModeFreeConnector(conn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This spaghetti brought to you courtesey of xf86RandrR12.c
|
||||
* It adds preferred modes first, then non-preferred modes */
|
||||
for (pref = 1; pref >= 0; pref--) {
|
||||
for (i = 0; i < conn->count_modes; ++i) {
|
||||
kmode = &conn->modes[i];
|
||||
if ((pref != 0) == ((kmode->type & DRM_MODE_TYPE_PREFERRED) != 0)) {
|
||||
xRRModeInfo modeInfo;
|
||||
RRModePtr rrmode;
|
||||
|
||||
modeInfo.nameLength = strlen(kmode->name);
|
||||
|
||||
modeInfo.width = kmode->hdisplay;
|
||||
modeInfo.dotClock = kmode->clock * 1000;
|
||||
modeInfo.hSyncStart = kmode->hsync_start;
|
||||
modeInfo.hSyncEnd = kmode->hsync_end;
|
||||
modeInfo.hTotal = kmode->htotal;
|
||||
modeInfo.hSkew = kmode->hskew;
|
||||
|
||||
modeInfo.height = kmode->vdisplay;
|
||||
modeInfo.vSyncStart = kmode->vsync_start;
|
||||
modeInfo.vSyncEnd = kmode->vsync_end;
|
||||
modeInfo.vTotal = kmode->vtotal;
|
||||
modeInfo.modeFlags = kmode->flags;
|
||||
|
||||
rrmode = RRModeGet(&modeInfo, kmode->name);
|
||||
if (rrmode) {
|
||||
rrmodes[*nmode] = rrmode;
|
||||
*nmode = *nmode + 1;
|
||||
*npref = *npref + pref;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* workaround: there could be no preferred mode that got added */
|
||||
if (*nmode > 0 && *npref == 0)
|
||||
*npref = 1;
|
||||
|
||||
drmModeFreeConnector(conn);
|
||||
return rrmodes;
|
||||
#else
|
||||
*nmode = *npref = 0;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
lease_connector_handle_connector_id(void *data,
|
||||
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1,
|
||||
uint32_t connector_id)
|
||||
{
|
||||
struct xwl_output *output;
|
||||
Atom name;
|
||||
INT32 value;
|
||||
int err;
|
||||
int nmode, npref;
|
||||
RRModePtr *rrmodes;
|
||||
|
||||
value = connector_id;
|
||||
output = (struct xwl_output *)data;
|
||||
name = MakeAtom("CONNECTOR_ID", 12, TRUE);
|
||||
|
||||
if (name != BAD_RESOURCE) {
|
||||
err = RRConfigureOutputProperty(output->randr_output, name,
|
||||
FALSE, FALSE, TRUE,
|
||||
1, &value);
|
||||
if (err != 0) {
|
||||
ErrorF("RRConfigureOutputProperty error, %d\n", err);
|
||||
return;
|
||||
}
|
||||
err = RRChangeOutputProperty(output->randr_output, name,
|
||||
XA_INTEGER, 32, PropModeReplace, 1,
|
||||
&value, FALSE, FALSE);
|
||||
if (err != 0) {
|
||||
ErrorF("RRChangeOutputProperty error, %d\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
rrmodes = xwl_get_rrmodes_from_connector_id(output->lease_device->drm_read_only_fd,
|
||||
connector_id, &nmode, &npref);
|
||||
|
||||
if (rrmodes != NULL)
|
||||
RROutputSetModes(output->randr_output, rrmodes, nmode, npref);
|
||||
|
||||
free(rrmodes);
|
||||
}
|
||||
|
||||
static void
|
||||
lease_connector_handle_done(void *data,
|
||||
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
|
||||
{
|
||||
/* This space is deliberately left blank */
|
||||
}
|
||||
|
||||
static void
|
||||
lease_connector_handle_withdrawn(void *data,
|
||||
struct wp_drm_lease_connector_v1 *wp_drm_lease_connector_v1)
|
||||
{
|
||||
xwl_output_remove(data);
|
||||
}
|
||||
|
||||
static const struct wp_drm_lease_connector_v1_listener lease_connector_listener = {
|
||||
.name = lease_connector_handle_name,
|
||||
.description = lease_connector_handle_description,
|
||||
.connector_id = lease_connector_handle_connector_id,
|
||||
.withdrawn = lease_connector_handle_withdrawn,
|
||||
.done = lease_connector_handle_done,
|
||||
};
|
||||
|
||||
static void
|
||||
drm_lease_device_handle_drm_fd(void *data,
|
||||
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1,
|
||||
int fd)
|
||||
{
|
||||
((struct xwl_drm_lease_device *)data)->drm_read_only_fd = fd;
|
||||
}
|
||||
|
||||
static void
|
||||
drm_lease_device_handle_connector(void *data,
|
||||
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1,
|
||||
struct wp_drm_lease_connector_v1 *connector)
|
||||
{
|
||||
struct xwl_drm_lease_device *lease_device = data;
|
||||
struct xwl_output *xwl_output;
|
||||
char name[256];
|
||||
|
||||
xwl_output = calloc(1, sizeof *xwl_output);
|
||||
if (xwl_output == NULL) {
|
||||
ErrorF("%s ENOMEM\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(name, sizeof name, "XWAYLAND%d", xwl_get_next_output_serial());
|
||||
|
||||
xwl_output->lease_device = lease_device;
|
||||
xwl_output->xwl_screen = lease_device->xwl_screen;
|
||||
xwl_output->lease_connector = connector;
|
||||
xwl_output->randr_crtc = RRCrtcCreate(lease_device->xwl_screen->screen, xwl_output);
|
||||
if (!xwl_output->randr_crtc) {
|
||||
ErrorF("Failed creating RandR CRTC\n");
|
||||
goto err;
|
||||
}
|
||||
RRCrtcSetRotations(xwl_output->randr_crtc, ALL_ROTATIONS);
|
||||
xwl_output->randr_output = RROutputCreate(lease_device->xwl_screen->screen,
|
||||
name, strlen(name), xwl_output);
|
||||
if (!xwl_output->randr_output) {
|
||||
ErrorF("Failed creating RandR Output\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
|
||||
RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
|
||||
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
|
||||
RROutputSetNonDesktop(xwl_output->randr_output, TRUE);
|
||||
xwl_output->randr_output->devPrivate = xwl_output;
|
||||
|
||||
wp_drm_lease_connector_v1_add_listener(connector,
|
||||
&lease_connector_listener,
|
||||
xwl_output);
|
||||
|
||||
xorg_list_append(&xwl_output->link, &lease_device->xwl_screen->output_list);
|
||||
return;
|
||||
|
||||
err:
|
||||
if (xwl_output->randr_crtc)
|
||||
RRCrtcDestroy(xwl_output->randr_crtc);
|
||||
free(xwl_output);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_lease_device_handle_released(void *data,
|
||||
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
|
||||
{
|
||||
struct xwl_drm_lease_device *lease_device = data;
|
||||
xwl_screen_destroy_drm_lease_device(lease_device->xwl_screen, wp_drm_lease_device_v1);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_lease_device_handle_done(void *data,
|
||||
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
|
||||
{
|
||||
/* This space is deliberately left blank */
|
||||
}
|
||||
|
||||
static const struct wp_drm_lease_device_v1_listener drm_lease_device_listener = {
|
||||
.drm_fd = drm_lease_device_handle_drm_fd,
|
||||
.connector = drm_lease_device_handle_connector,
|
||||
.released = drm_lease_device_handle_released,
|
||||
.done = drm_lease_device_handle_done,
|
||||
};
|
||||
|
||||
void
|
||||
xwl_screen_add_drm_lease_device(struct xwl_screen *xwl_screen, uint32_t id)
|
||||
{
|
||||
struct wp_drm_lease_device_v1 *lease_device = wl_registry_bind(
|
||||
xwl_screen->registry, id, &wp_drm_lease_device_v1_interface, 1);
|
||||
struct xwl_drm_lease_device *device_data = malloc(sizeof(struct xwl_drm_lease_device));
|
||||
|
||||
device_data->drm_lease_device = lease_device;
|
||||
device_data->xwl_screen = xwl_screen;
|
||||
device_data->drm_read_only_fd = -1;
|
||||
device_data->id = id;
|
||||
xorg_list_add(&device_data->link, &xwl_screen->drm_lease_devices);
|
||||
wp_drm_lease_device_v1_add_listener(lease_device,
|
||||
&drm_lease_device_listener,
|
||||
device_data);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_screen_destroy_drm_lease_device(struct xwl_screen *xwl_screen,
|
||||
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1)
|
||||
{
|
||||
struct xwl_drm_lease_device *device_data;
|
||||
|
||||
xorg_list_for_each_entry(device_data, &xwl_screen->drm_lease_devices, link) {
|
||||
if (device_data->drm_lease_device == wp_drm_lease_device_v1) {
|
||||
wp_drm_lease_device_v1_destroy(wp_drm_lease_device_v1);
|
||||
xorg_list_del(&device_data->link);
|
||||
if (device_data->drm_read_only_fd >= 0)
|
||||
close(device_data->drm_read_only_fd);
|
||||
free(device_data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright © 2020 Drew Devault
|
||||
* Copyright © 2021 Xaver Hugl
|
||||
*
|
||||
* 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 the
|
||||
* copyright holders not be used in advertising or publicity
|
||||
* pertaining to distribution of the software without specific,
|
||||
* written prior permission. The 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.
|
||||
*/
|
||||
|
||||
#ifndef XWAYLAND_DRM_LEASE_H
|
||||
#define XWAYLAND_DRM_LEASE_H
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <randrstr.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "list.h"
|
||||
|
||||
#include "drm-lease-v1-client-protocol.h"
|
||||
|
||||
struct xwl_drm_lease_device {
|
||||
struct xorg_list link;
|
||||
struct wp_drm_lease_device_v1 *drm_lease_device;
|
||||
int drm_read_only_fd;
|
||||
struct xwl_screen *xwl_screen;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct xwl_queued_drm_lease_device {
|
||||
struct xorg_list link;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct xwl_drm_lease {
|
||||
struct xorg_list link;
|
||||
struct wp_drm_lease_v1 *lease;
|
||||
RRLeasePtr rrLease;
|
||||
ClientPtr client;
|
||||
int fd;
|
||||
};
|
||||
|
||||
int xwl_randr_request_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr rrLease);
|
||||
void xwl_randr_get_lease(ClientPtr client, ScreenPtr screen, RRLeasePtr *rrLease, int *fd);
|
||||
void xwl_randr_terminate_lease(ScreenPtr screen, RRLeasePtr lease);
|
||||
|
||||
void xwl_screen_add_drm_lease_device(struct xwl_screen *xwl_screen, uint32_t id);
|
||||
void xwl_screen_destroy_drm_lease_device(struct xwl_screen *xwl_screen,
|
||||
struct wp_drm_lease_device_v1 *wp_drm_lease_device_v1);
|
||||
|
||||
#endif /* XWAYLAND_DRM_LEASE_H */
|
|
@ -33,10 +33,13 @@
|
|||
#define EGL_NO_X11
|
||||
#include <glamor_egl.h>
|
||||
#include <glamor.h>
|
||||
#include <glamor_priv.h>
|
||||
#include <glamor_transform.h>
|
||||
#include <glamor_transfer.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <dri3.h>
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include <epoxy/egl.h>
|
||||
|
||||
|
@ -47,18 +50,7 @@
|
|||
|
||||
#include "wayland-eglstream-client-protocol.h"
|
||||
#include "wayland-eglstream-controller-client-protocol.h"
|
||||
|
||||
struct xwl_eglstream_pending_stream {
|
||||
PixmapPtr pixmap;
|
||||
WindowPtr window;
|
||||
|
||||
struct xwl_pixmap *xwl_pixmap;
|
||||
struct wl_callback *cb;
|
||||
|
||||
Bool is_valid;
|
||||
|
||||
struct xorg_list link;
|
||||
};
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
||||
struct xwl_eglstream_private {
|
||||
EGLDeviceEXT egl_device;
|
||||
|
@ -68,11 +60,8 @@ struct xwl_eglstream_private {
|
|||
|
||||
EGLConfig config;
|
||||
|
||||
SetWindowPixmapProcPtr SetWindowPixmap;
|
||||
|
||||
struct xorg_list pending_streams;
|
||||
|
||||
Bool have_egl_damage;
|
||||
Bool have_egl_stream_flush;
|
||||
|
||||
GLint blit_prog;
|
||||
GLuint blit_vao;
|
||||
|
@ -80,16 +69,28 @@ struct xwl_eglstream_private {
|
|||
GLuint blit_is_rgba_pos;
|
||||
};
|
||||
|
||||
struct xwl_pixmap {
|
||||
struct wl_buffer *buffer;
|
||||
struct xwl_screen *xwl_screen;
|
||||
enum xwl_pixmap_type {
|
||||
XWL_PIXMAP_EGLSTREAM, /* Pixmaps created by glamor. */
|
||||
XWL_PIXMAP_DMA_BUF, /* Pixmaps allocated through DRI3. */
|
||||
};
|
||||
|
||||
struct xwl_pixmap {
|
||||
enum xwl_pixmap_type type;
|
||||
/* add any new <= 4-byte member here to avoid holes on 64-bit */
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct wl_buffer *buffer;
|
||||
struct wl_callback *pending_cb;
|
||||
Bool wait_for_buffer_release;
|
||||
|
||||
/* XWL_PIXMAP_EGLSTREAM. */
|
||||
EGLStreamKHR stream;
|
||||
EGLSurface surface;
|
||||
|
||||
/* XWL_PIXMAP_DMA_BUF. */
|
||||
EGLImage image;
|
||||
};
|
||||
|
||||
static DevPrivateKeyRec xwl_eglstream_private_key;
|
||||
static DevPrivateKeyRec xwl_eglstream_window_private_key;
|
||||
|
||||
static inline struct xwl_eglstream_private *
|
||||
xwl_eglstream_get(struct xwl_screen *xwl_screen)
|
||||
|
@ -98,52 +99,6 @@ xwl_eglstream_get(struct xwl_screen *xwl_screen)
|
|||
&xwl_eglstream_private_key);
|
||||
}
|
||||
|
||||
static inline struct xwl_eglstream_pending_stream *
|
||||
xwl_eglstream_window_get_pending(WindowPtr window)
|
||||
{
|
||||
return dixLookupPrivate(&window->devPrivates,
|
||||
&xwl_eglstream_window_private_key);
|
||||
}
|
||||
|
||||
static inline void
|
||||
xwl_eglstream_window_set_pending(WindowPtr window,
|
||||
struct xwl_eglstream_pending_stream *stream)
|
||||
{
|
||||
dixSetPrivate(&window->devPrivates,
|
||||
&xwl_eglstream_window_private_key, stream);
|
||||
}
|
||||
|
||||
static GLint
|
||||
xwl_eglstream_compile_glsl_prog(GLenum type, const char *source)
|
||||
{
|
||||
GLint ok;
|
||||
GLint prog;
|
||||
|
||||
prog = glCreateShader(type);
|
||||
glShaderSource(prog, 1, (const GLchar **) &source, NULL);
|
||||
glCompileShader(prog);
|
||||
glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
|
||||
if (!ok) {
|
||||
GLchar *info;
|
||||
GLint size;
|
||||
|
||||
glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
|
||||
info = malloc(size);
|
||||
if (info) {
|
||||
glGetShaderInfoLog(prog, size, NULL, info);
|
||||
ErrorF("Failed to compile %s: %s\n",
|
||||
type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
|
||||
ErrorF("Program source:\n%s", source);
|
||||
free(info);
|
||||
}
|
||||
else
|
||||
ErrorF("Failed to get shader compilation info.\n");
|
||||
FatalError("GLSL compile failure\n");
|
||||
}
|
||||
|
||||
return prog;
|
||||
}
|
||||
|
||||
static GLuint
|
||||
xwl_eglstream_build_glsl_prog(GLuint vs, GLuint fs)
|
||||
{
|
||||
|
@ -273,7 +228,7 @@ xwl_glamor_egl_device_has_egl_extensions(void *device,
|
|||
}
|
||||
|
||||
static void
|
||||
xwl_eglstream_unref_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
|
||||
xwl_eglstream_destroy_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
|
||||
|
||||
|
@ -289,31 +244,29 @@ xwl_eglstream_unref_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
|
|||
xwl_screen->egl_context);
|
||||
}
|
||||
|
||||
if (xwl_pixmap->surface)
|
||||
if (xwl_pixmap->surface != EGL_NO_SURFACE)
|
||||
eglDestroySurface(xwl_screen->egl_display, xwl_pixmap->surface);
|
||||
|
||||
eglDestroyStreamKHR(xwl_screen->egl_display, xwl_pixmap->stream);
|
||||
if (xwl_pixmap->stream != EGL_NO_STREAM_KHR)
|
||||
eglDestroyStreamKHR(xwl_screen->egl_display, xwl_pixmap->stream);
|
||||
|
||||
if (xwl_pixmap->buffer)
|
||||
wl_buffer_destroy(xwl_pixmap->buffer);
|
||||
|
||||
if (xwl_pixmap->image != EGL_NO_IMAGE_KHR)
|
||||
eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
|
||||
|
||||
wl_buffer_destroy(xwl_pixmap->buffer);
|
||||
free(xwl_pixmap);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_glamor_eglstream_del_pending_stream_cb(struct xwl_pixmap *xwl_pixmap)
|
||||
xwl_eglstream_destroy_pending_cb(PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_eglstream_private *xwl_eglstream =
|
||||
xwl_eglstream_get(xwl_pixmap->xwl_screen);
|
||||
struct xwl_eglstream_pending_stream *pending;
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
xorg_list_for_each_entry(pending,
|
||||
&xwl_eglstream->pending_streams, link) {
|
||||
if (pending->xwl_pixmap == xwl_pixmap) {
|
||||
wl_callback_destroy(pending->cb);
|
||||
xwl_eglstream_window_set_pending(pending->window, NULL);
|
||||
xorg_list_del(&pending->link);
|
||||
free(pending);
|
||||
break;
|
||||
}
|
||||
if (xwl_pixmap && xwl_pixmap->pending_cb) {
|
||||
wl_callback_destroy(xwl_pixmap->pending_cb);
|
||||
xwl_pixmap->pending_cb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,9 +276,9 @@ xwl_glamor_eglstream_destroy_pixmap(PixmapPtr pixmap)
|
|||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
if (xwl_pixmap && pixmap->refcnt == 1) {
|
||||
xwl_glamor_eglstream_del_pending_stream_cb(xwl_pixmap);
|
||||
xwl_eglstream_destroy_pending_cb(pixmap);
|
||||
xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
|
||||
xwl_pixmap_del_buffer_release_cb(pixmap);
|
||||
xwl_eglstream_unref_pixmap_stream(xwl_pixmap);
|
||||
}
|
||||
return glamor_destroy_pixmap(pixmap);
|
||||
}
|
||||
|
@ -333,160 +286,142 @@ xwl_glamor_eglstream_destroy_pixmap(PixmapPtr pixmap)
|
|||
static struct wl_buffer *
|
||||
xwl_glamor_eglstream_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
|
||||
{
|
||||
return xwl_pixmap_get(pixmap)->buffer;
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
if (!xwl_pixmap)
|
||||
return NULL;
|
||||
|
||||
return xwl_pixmap->buffer;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
|
||||
static const char *
|
||||
xwl_eglstream_get_error_str(EGLint error)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(window->drawable.pScreen);
|
||||
struct xwl_eglstream_private *xwl_eglstream =
|
||||
xwl_eglstream_get(xwl_screen);
|
||||
struct xwl_eglstream_pending_stream *pending;
|
||||
switch (error) {
|
||||
case EGL_BAD_PARAMETER:
|
||||
return "EGL_BAD_PARAMETER";
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
return "EGL_BAD_ATTRIBUTE";
|
||||
case EGL_BAD_MATCH:
|
||||
return "EGL_BAD_MATCH";
|
||||
case EGL_BAD_ACCESS:
|
||||
return "EGL_BAD_ACCESS";
|
||||
case EGL_BAD_STATE_KHR:
|
||||
return "EGL_BAD_STATE_KHR";
|
||||
case EGL_BAD_STREAM_KHR:
|
||||
return "EGL_BAD_STREAM_KHR";
|
||||
case EGL_BAD_DISPLAY:
|
||||
return "EGL_BAD_DISPLAY";
|
||||
case EGL_NOT_INITIALIZED:
|
||||
return "EGL_NOT_INITIALIZED";
|
||||
default:
|
||||
return "Unknown error";
|
||||
}
|
||||
}
|
||||
|
||||
pending = xwl_eglstream_window_get_pending(window);
|
||||
if (pending) {
|
||||
/* The pixmap for this window has changed before the compositor
|
||||
* finished attaching the consumer for the window's pixmap's original
|
||||
* eglstream. A producer can no longer be attached, so the stream's
|
||||
* useless
|
||||
*/
|
||||
pending->is_valid = FALSE;
|
||||
static const char *
|
||||
xwl_eglstream_get_stream_state_str(EGLint state)
|
||||
{
|
||||
switch (state) {
|
||||
case EGL_STREAM_STATE_CREATED_KHR:
|
||||
return "EGL_STREAM_STATE_CREATED_KHR";
|
||||
case EGL_STREAM_STATE_CONNECTING_KHR:
|
||||
return "EGL_STREAM_STATE_CONNECTING_KHR";
|
||||
case EGL_STREAM_STATE_EMPTY_KHR:
|
||||
return "EGL_STREAM_STATE_EMPTY_KHR";
|
||||
case EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR:
|
||||
return "EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR";
|
||||
case EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR:
|
||||
return "EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR";
|
||||
case EGL_STREAM_STATE_DISCONNECTED_KHR:
|
||||
return "EGL_STREAM_STATE_DISCONNECTED_KHR";
|
||||
default:
|
||||
return "Unknown state";
|
||||
}
|
||||
}
|
||||
|
||||
static EGLint
|
||||
xwl_eglstream_get_state(EGLDisplay egl_display, EGLStreamKHR egl_stream)
|
||||
{
|
||||
EGLint state;
|
||||
|
||||
eglQueryStreamKHR(egl_display, egl_stream, EGL_STREAM_STATE_KHR, &state);
|
||||
if (!eglQueryStreamKHR(egl_display, egl_stream,
|
||||
EGL_STREAM_STATE_KHR, &state)) {
|
||||
EGLint state_error = eglGetError();
|
||||
ErrorF("eglstream: Failed to query state - error 0x%X: %s\n",
|
||||
state_error, xwl_eglstream_get_error_str(state_error));
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
|
||||
(*xwl_screen->screen->SetWindowPixmap)(window, pixmap);
|
||||
xwl_eglstream->SetWindowPixmap = xwl_screen->screen->SetWindowPixmap;
|
||||
xwl_screen->screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xwl_eglstream_print_error(EGLDisplay egl_display,
|
||||
EGLStreamKHR egl_stream, EGLint error)
|
||||
{
|
||||
ErrorF("eglstream: error 0x%X: %s\n", error,
|
||||
xwl_eglstream_get_error_str(error));
|
||||
|
||||
if (error == EGL_BAD_STATE_KHR) {
|
||||
EGLint state = xwl_eglstream_get_state(egl_display, egl_stream);
|
||||
ErrorF("eglstream: stream state 0x%X: %s\n", state,
|
||||
xwl_eglstream_get_stream_state_str(state));
|
||||
}
|
||||
}
|
||||
|
||||
/* Because we run asynchronously with our wayland compositor, it's possible
|
||||
* that an X client event could cause us to begin creating a stream for a
|
||||
* pixmap/window combo before the stream for the pixmap this window
|
||||
* previously used has been fully initialized. An example:
|
||||
*
|
||||
* - Start processing X client events.
|
||||
* - X window receives resize event, causing us to create a new pixmap and
|
||||
* begin creating the corresponding eglstream. This pixmap is known as
|
||||
* pixmap A.
|
||||
* - X window receives another resize event, and again changes its current
|
||||
* pixmap causing us to create another corresponding eglstream for the same
|
||||
* window. This pixmap is known as pixmap B.
|
||||
* - Start handling events from the wayland compositor.
|
||||
*
|
||||
* Since both pixmap A and B will have scheduled wl_display_sync events to
|
||||
* indicate when their respective streams are connected, we will receive each
|
||||
* callback in the original order the pixmaps were created. This means the
|
||||
* following would happen:
|
||||
*
|
||||
* - Receive pixmap A's stream callback, attach its stream to the surface of
|
||||
* the window that just orphaned it.
|
||||
* - Receive pixmap B's stream callback, fall over and fail because the
|
||||
* window's surface now incorrectly has pixmap A's stream attached to it.
|
||||
*
|
||||
* We work around this problem by keeping a queue of pending streams, and
|
||||
* only allowing one queue entry to exist for each window. In the scenario
|
||||
* listed above, this should happen:
|
||||
*
|
||||
* - Begin processing X events...
|
||||
* - A window is resized, causing us to add an eglstream (known as eglstream
|
||||
* A) waiting for its consumer to finish attachment to be added to the
|
||||
* queue.
|
||||
* - Resize on same window happens. We invalidate the previously pending
|
||||
* stream and add another one to the pending queue (known as eglstream B).
|
||||
* - Begin processing Wayland events...
|
||||
* - Receive invalidated callback from compositor for eglstream A, destroy
|
||||
* stream.
|
||||
* - Receive callback from compositor for eglstream B, create producer.
|
||||
* - Success!
|
||||
*/
|
||||
static void
|
||||
xwl_eglstream_consumer_ready_callback(void *data,
|
||||
struct wl_callback *callback,
|
||||
uint32_t time)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
PixmapPtr pixmap = data;
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
|
||||
struct xwl_eglstream_private *xwl_eglstream =
|
||||
xwl_eglstream_get(xwl_screen);
|
||||
struct xwl_pixmap *xwl_pixmap;
|
||||
struct xwl_eglstream_pending_stream *pending;
|
||||
Bool found = FALSE;
|
||||
|
||||
wl_callback_destroy(callback);
|
||||
|
||||
xorg_list_for_each_entry(pending, &xwl_eglstream->pending_streams, link) {
|
||||
if (pending->cb == callback) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(found);
|
||||
|
||||
if (!pending->is_valid) {
|
||||
xwl_eglstream_unref_pixmap_stream(pending->xwl_pixmap);
|
||||
goto out;
|
||||
}
|
||||
xwl_eglstream_destroy_pending_cb(pixmap);
|
||||
|
||||
xwl_glamor_egl_make_current(xwl_screen);
|
||||
|
||||
xwl_pixmap = pending->xwl_pixmap;
|
||||
xwl_pixmap->surface = eglCreateStreamProducerSurfaceKHR(
|
||||
xwl_screen->egl_display, xwl_eglstream->config,
|
||||
xwl_pixmap->stream, (int[]) {
|
||||
EGL_WIDTH, pending->pixmap->drawable.width,
|
||||
EGL_HEIGHT, pending->pixmap->drawable.height,
|
||||
EGL_WIDTH, pixmap->drawable.width,
|
||||
EGL_HEIGHT, pixmap->drawable.height,
|
||||
EGL_NONE
|
||||
});
|
||||
|
||||
DebugF("eglstream: win %d completes eglstream for pixmap %p, congrats!\n",
|
||||
pending->window->drawable.id, pending->pixmap);
|
||||
|
||||
out:
|
||||
xwl_eglstream_window_set_pending(pending->window, NULL);
|
||||
xorg_list_del(&pending->link);
|
||||
free(pending);
|
||||
if (xwl_pixmap->surface == EGL_NO_SURFACE) {
|
||||
ErrorF("eglstream: Failed to create EGLSurface for pixmap\n");
|
||||
xwl_eglstream_print_error(xwl_screen->egl_display,
|
||||
xwl_pixmap->stream, eglGetError());
|
||||
} else {
|
||||
DebugF("eglstream: completes eglstream for pixmap %p, congrats!\n",
|
||||
pixmap);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener consumer_ready_listener = {
|
||||
xwl_eglstream_consumer_ready_callback
|
||||
};
|
||||
|
||||
static void
|
||||
xwl_eglstream_queue_pending_stream(struct xwl_screen *xwl_screen,
|
||||
WindowPtr window, PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_eglstream_private *xwl_eglstream =
|
||||
xwl_eglstream_get(xwl_screen);
|
||||
struct xwl_eglstream_pending_stream *pending_stream;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!xwl_eglstream_window_get_pending(window))
|
||||
DebugF("eglstream: win %d begins new eglstream for pixmap %p\n",
|
||||
window->drawable.id, pixmap);
|
||||
else
|
||||
DebugF("eglstream: win %d interrupts and replaces pending eglstream for pixmap %p\n",
|
||||
window->drawable.id, pixmap);
|
||||
#endif
|
||||
|
||||
pending_stream = malloc(sizeof(*pending_stream));
|
||||
pending_stream->window = window;
|
||||
pending_stream->pixmap = pixmap;
|
||||
pending_stream->xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
pending_stream->is_valid = TRUE;
|
||||
xorg_list_init(&pending_stream->link);
|
||||
xorg_list_add(&pending_stream->link, &xwl_eglstream->pending_streams);
|
||||
xwl_eglstream_window_set_pending(window, pending_stream);
|
||||
|
||||
pending_stream->cb = wl_display_sync(xwl_screen->display);
|
||||
wl_callback_add_listener(pending_stream->cb, &consumer_ready_listener,
|
||||
xwl_screen);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_eglstream_buffer_release_callback(void *data)
|
||||
{
|
||||
/* drop the reference we took in post_damage, freeing if necessary */
|
||||
dixDestroyPixmap(data, 0);
|
||||
PixmapPtr pixmap = data;
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
assert(xwl_pixmap);
|
||||
|
||||
if (xwl_pixmap->wait_for_buffer_release) {
|
||||
xwl_pixmap->wait_for_buffer_release = FALSE;
|
||||
/* drop the reference we took in the ready callback, freeing if necessary */
|
||||
dixDestroyPixmap(pixmap, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
|
||||
|
@ -494,8 +429,8 @@ static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
|
|||
};
|
||||
|
||||
static void
|
||||
xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
|
||||
WindowPtr window, PixmapPtr pixmap)
|
||||
xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
|
||||
WindowPtr window, PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_eglstream_private *xwl_eglstream =
|
||||
xwl_eglstream_get(xwl_screen);
|
||||
|
@ -504,17 +439,30 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
|
|||
struct wl_array stream_attribs;
|
||||
int stream_fd = -1;
|
||||
|
||||
xwl_pixmap = calloc(sizeof(*xwl_pixmap), 1);
|
||||
xwl_pixmap = calloc(1, sizeof(*xwl_pixmap));
|
||||
if (!xwl_pixmap)
|
||||
FatalError("Not enough memory to create pixmap\n");
|
||||
xwl_pixmap_set_private(pixmap, xwl_pixmap);
|
||||
|
||||
xwl_pixmap->type = XWL_PIXMAP_EGLSTREAM;
|
||||
xwl_pixmap->image = EGL_NO_IMAGE;
|
||||
|
||||
xwl_glamor_egl_make_current(xwl_screen);
|
||||
|
||||
xwl_pixmap->wait_for_buffer_release = FALSE;
|
||||
xwl_pixmap->xwl_screen = xwl_screen;
|
||||
xwl_pixmap->surface = EGL_NO_SURFACE;
|
||||
xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
|
||||
if (xwl_pixmap->stream == EGL_NO_STREAM_KHR) {
|
||||
ErrorF("eglstream: Couldn't create EGL stream.\n");
|
||||
goto fail;
|
||||
}
|
||||
stream_fd = eglGetStreamFileDescriptorKHR(xwl_screen->egl_display,
|
||||
xwl_pixmap->stream);
|
||||
if (stream_fd == EGL_NO_FILE_DESCRIPTOR_KHR) {
|
||||
ErrorF("eglstream: Couldn't get EGL stream file descriptor.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wl_array_init(&stream_attribs);
|
||||
xwl_pixmap->buffer =
|
||||
|
@ -524,6 +472,10 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
|
|||
stream_fd,
|
||||
WL_EGLSTREAM_HANDLE_TYPE_FD,
|
||||
&stream_attribs);
|
||||
if (!xwl_pixmap->buffer) {
|
||||
ErrorF("eglstream: Failed to create buffer\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wl_buffer_add_listener(xwl_pixmap->buffer,
|
||||
&xwl_eglstream_buffer_release_listener,
|
||||
|
@ -536,46 +488,51 @@ xwl_eglstream_create_pending_stream(struct xwl_screen *xwl_screen,
|
|||
wl_eglstream_controller_attach_eglstream_consumer(
|
||||
xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
|
||||
|
||||
xwl_eglstream_queue_pending_stream(xwl_screen, window, pixmap);
|
||||
|
||||
close(stream_fd);
|
||||
xwl_pixmap->pending_cb = wl_display_sync(xwl_screen->display);
|
||||
wl_callback_add_listener(xwl_pixmap->pending_cb, &consumer_ready_listener,
|
||||
pixmap);
|
||||
fail:
|
||||
if (stream_fd >= 0)
|
||||
close(stream_fd);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
struct xwl_eglstream_pending_stream *pending =
|
||||
xwl_eglstream_window_get_pending(xwl_window->window);
|
||||
PixmapPtr pixmap =
|
||||
(*xwl_screen->screen->GetWindowPixmap)(xwl_window->window);
|
||||
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
||||
|
||||
if (xwl_pixmap) {
|
||||
if (pending) {
|
||||
if (xwl_pixmap->pending_cb) {
|
||||
/* Wait for the compositor to finish connecting the consumer for
|
||||
* this eglstream */
|
||||
if (pending->is_valid)
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The pixmap for this window was changed before the compositor
|
||||
* finished connecting the eglstream for the window's previous
|
||||
* pixmap. Begin creating a new eglstream. */
|
||||
} else {
|
||||
if (xwl_pixmap->surface != EGL_NO_SURFACE ||
|
||||
xwl_pixmap->type == XWL_PIXMAP_DMA_BUF) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* The pending stream got removed, we have a xwl_pixmap and
|
||||
* yet we do not have a surface.
|
||||
* So something went wrong with the surface creation, retry.
|
||||
*/
|
||||
xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
|
||||
}
|
||||
|
||||
/* Glamor pixmap has no backing stream yet; begin making one and disallow
|
||||
* commits until then
|
||||
*/
|
||||
xwl_eglstream_create_pending_stream(xwl_screen, xwl_window->window,
|
||||
pixmap);
|
||||
xwl_eglstream_create_pixmap_and_stream(xwl_screen, xwl_window->window,
|
||||
pixmap);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
static Bool
|
||||
xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region)
|
||||
{
|
||||
|
@ -589,11 +546,21 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
|
|||
box->x2 - box->x1, box->y2 - box->y1
|
||||
};
|
||||
GLint saved_vao;
|
||||
int status;
|
||||
|
||||
if (xwl_pixmap->type != XWL_PIXMAP_EGLSTREAM)
|
||||
/* This can happen if a client does X11 rendering on a
|
||||
* flipping OpenGL or Vulkan window. In that case, we don't
|
||||
* need to do the copy below.
|
||||
*/
|
||||
return TRUE;
|
||||
|
||||
/* Unbind the framebuffer BEFORE binding the EGLSurface, otherwise we
|
||||
* won't actually draw to it
|
||||
*/
|
||||
xwl_glamor_egl_make_current(xwl_screen);
|
||||
glamor_set_alu(xwl_screen->screen, GXcopy);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
if (eglGetCurrentSurface(EGL_READ) != xwl_pixmap->surface ||
|
||||
|
@ -615,22 +582,55 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
|
|||
glUniform1i(xwl_eglstream->blit_is_rgba_pos,
|
||||
pixmap->drawable.depth >= 32);
|
||||
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
ErrorF("eglstream: Framebuffer incomplete 0x%X, not posting damage\n", status);
|
||||
status = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Blit rendered image into EGLStream surface */
|
||||
glDrawBuffer(GL_BACK);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
if (xwl_eglstream->have_egl_damage)
|
||||
eglSwapBuffersWithDamageKHR(xwl_screen->egl_display,
|
||||
xwl_pixmap->surface, egl_damage, 1);
|
||||
status = eglSwapBuffersWithDamageKHR(xwl_screen->egl_display,
|
||||
xwl_pixmap->surface,
|
||||
egl_damage, 1);
|
||||
else
|
||||
eglSwapBuffers(xwl_screen->egl_display, xwl_pixmap->surface);
|
||||
status = eglSwapBuffers(xwl_screen->egl_display,
|
||||
xwl_pixmap->surface);
|
||||
|
||||
if (!status) {
|
||||
ErrorF("eglstream: buffer swap failed, not posting damage\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef EGL_NV_stream_flush
|
||||
if (xwl_eglstream->have_egl_stream_flush)
|
||||
/* block until stream state is updated on the compositor's side */
|
||||
eglStreamFlushNV(xwl_screen->egl_display,
|
||||
xwl_pixmap->stream);
|
||||
#endif
|
||||
|
||||
if (!xwl_pixmap->wait_for_buffer_release) {
|
||||
/* hang onto the pixmap until the compositor has released it */
|
||||
pixmap->refcnt++;
|
||||
xwl_pixmap->wait_for_buffer_release = TRUE;
|
||||
}
|
||||
|
||||
out:
|
||||
/* Restore previous state */
|
||||
glBindVertexArray(saved_vao);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
/* hang onto the pixmap until the compositor has released it */
|
||||
pixmap->refcnt++;
|
||||
return status;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_eglstream_check_flip(PixmapPtr pixmap)
|
||||
{
|
||||
return xwl_pixmap_get(pixmap)->type == XWL_PIXMAP_DMA_BUF;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -675,6 +675,9 @@ xwl_glamor_eglstream_init_wl_registry(struct xwl_screen *xwl_screen,
|
|||
xwl_eglstream->controller = wl_registry_bind(
|
||||
wl_registry, id, &wl_eglstream_controller_interface, version);
|
||||
return TRUE;
|
||||
} else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0) {
|
||||
xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* no match */
|
||||
|
@ -688,12 +691,14 @@ xwl_glamor_eglstream_has_wl_interfaces(struct xwl_screen *xwl_screen)
|
|||
xwl_eglstream_get(xwl_screen);
|
||||
|
||||
if (xwl_eglstream->display == NULL) {
|
||||
ErrorF("glamor: 'wl_eglstream_display' not supported\n");
|
||||
LogMessageVerb(X_INFO, 3,
|
||||
"glamor: 'wl_eglstream_display' not supported\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (xwl_eglstream->controller == NULL) {
|
||||
ErrorF("glamor: 'wl_eglstream_controller' not supported\n");
|
||||
LogMessageVerb(X_INFO, 3,
|
||||
"glamor: 'wl_eglstream_controller' not supported\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -741,8 +746,8 @@ xwl_eglstream_init_shaders(struct xwl_screen *xwl_screen)
|
|||
0, 0,
|
||||
};
|
||||
|
||||
vs = xwl_eglstream_compile_glsl_prog(GL_VERTEX_SHADER, blit_vs_src);
|
||||
fs = xwl_eglstream_compile_glsl_prog(GL_FRAGMENT_SHADER, blit_fs_src);
|
||||
vs = glamor_compile_glsl_prog(GL_VERTEX_SHADER, blit_vs_src);
|
||||
fs = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, blit_fs_src);
|
||||
|
||||
xwl_eglstream->blit_prog = xwl_eglstream_build_glsl_prog(vs, fs);
|
||||
glDeleteShader(vs);
|
||||
|
@ -773,6 +778,163 @@ xwl_eglstream_init_shaders(struct xwl_screen *xwl_screen)
|
|||
glGetUniformLocation(xwl_eglstream->blit_prog, "is_rgba");
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_dri3_open_client(ClientPtr client,
|
||||
ScreenPtr screen,
|
||||
RRProviderPtr provider,
|
||||
int *pfd)
|
||||
{
|
||||
/* Not supported with this backend. */
|
||||
return BadImplementation;
|
||||
}
|
||||
|
||||
static PixmapPtr
|
||||
xwl_dri3_pixmap_from_fds(ScreenPtr screen,
|
||||
CARD8 num_fds, const int *fds,
|
||||
CARD16 width, CARD16 height,
|
||||
const CARD32 *strides, const CARD32 *offsets,
|
||||
CARD8 depth, CARD8 bpp,
|
||||
uint64_t modifier)
|
||||
{
|
||||
PixmapPtr pixmap;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_pixmap *xwl_pixmap;
|
||||
unsigned int texture;
|
||||
EGLint image_attribs[48];
|
||||
uint32_t mod_hi = modifier >> 32, mod_lo = modifier & 0xffffffff, format;
|
||||
int attrib = 0, i;
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
|
||||
format = wl_drm_format_for_depth(depth);
|
||||
if (!xwl_glamor_is_modifier_supported(xwl_screen, format, modifier)) {
|
||||
ErrorF("glamor: unsupported format modifier\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xwl_pixmap = calloc(1, sizeof (*xwl_pixmap));
|
||||
if (!xwl_pixmap)
|
||||
return NULL;
|
||||
xwl_pixmap->type = XWL_PIXMAP_DMA_BUF;
|
||||
xwl_pixmap->xwl_screen = xwl_screen;
|
||||
|
||||
xwl_pixmap->buffer = NULL;
|
||||
xwl_pixmap->stream = EGL_NO_STREAM_KHR;
|
||||
xwl_pixmap->surface = EGL_NO_SURFACE;
|
||||
|
||||
params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
|
||||
for (i = 0; i < num_fds; i++) {
|
||||
zwp_linux_buffer_params_v1_add(params, fds[i], i,
|
||||
offsets[i], strides[i],
|
||||
mod_hi, mod_lo);
|
||||
}
|
||||
xwl_pixmap->buffer =
|
||||
zwp_linux_buffer_params_v1_create_immed(params, width, height,
|
||||
format, 0);
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
|
||||
|
||||
image_attribs[attrib++] = EGL_WIDTH;
|
||||
image_attribs[attrib++] = width;
|
||||
image_attribs[attrib++] = EGL_HEIGHT;
|
||||
image_attribs[attrib++] = height;
|
||||
image_attribs[attrib++] = EGL_LINUX_DRM_FOURCC_EXT;
|
||||
image_attribs[attrib++] = drm_format_for_depth(depth, bpp);
|
||||
|
||||
if (num_fds > 0) {
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_FD_EXT;
|
||||
image_attribs[attrib++] = fds[0];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
|
||||
image_attribs[attrib++] = offsets[0];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
|
||||
image_attribs[attrib++] = strides[0];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
|
||||
image_attribs[attrib++] = mod_hi;
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
|
||||
image_attribs[attrib++] = mod_lo;
|
||||
}
|
||||
if (num_fds > 1) {
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_FD_EXT;
|
||||
image_attribs[attrib++] = fds[1];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_OFFSET_EXT;
|
||||
image_attribs[attrib++] = offsets[1];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_PITCH_EXT;
|
||||
image_attribs[attrib++] = strides[1];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT;
|
||||
image_attribs[attrib++] = mod_hi;
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT;
|
||||
image_attribs[attrib++] = mod_lo;
|
||||
}
|
||||
if (num_fds > 2) {
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_FD_EXT;
|
||||
image_attribs[attrib++] = fds[2];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_OFFSET_EXT;
|
||||
image_attribs[attrib++] = offsets[2];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_PITCH_EXT;
|
||||
image_attribs[attrib++] = strides[2];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT;
|
||||
image_attribs[attrib++] = mod_hi;
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT;
|
||||
image_attribs[attrib++] = mod_lo;
|
||||
}
|
||||
if (num_fds > 3) {
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_FD_EXT;
|
||||
image_attribs[attrib++] = fds[3];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_OFFSET_EXT;
|
||||
image_attribs[attrib++] = offsets[3];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_PITCH_EXT;
|
||||
image_attribs[attrib++] = strides[3];
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT;
|
||||
image_attribs[attrib++] = mod_hi;
|
||||
image_attribs[attrib++] = EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT;
|
||||
image_attribs[attrib++] = mod_lo;
|
||||
}
|
||||
image_attribs[attrib++] = EGL_NONE;
|
||||
|
||||
xwl_glamor_egl_make_current(xwl_screen);
|
||||
|
||||
/* eglCreateImageKHR will close fds */
|
||||
xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
|
||||
EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
NULL, image_attribs);
|
||||
if (xwl_pixmap->image == EGL_NO_IMAGE_KHR) {
|
||||
ErrorF("eglCreateImageKHR failed!\n");
|
||||
if (xwl_pixmap->buffer)
|
||||
wl_buffer_destroy(xwl_pixmap->buffer);
|
||||
free(xwl_pixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
pixmap = glamor_create_pixmap(screen, width, height, depth,
|
||||
GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
|
||||
glamor_set_pixmap_texture(pixmap, texture);
|
||||
glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
|
||||
wl_buffer_add_listener(xwl_pixmap->buffer,
|
||||
&xwl_eglstream_buffer_release_listener,
|
||||
pixmap);
|
||||
xwl_pixmap_set_private(pixmap, xwl_pixmap);
|
||||
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
static const dri3_screen_info_rec xwl_dri3_info = {
|
||||
.version = 2,
|
||||
.open = NULL,
|
||||
.pixmap_from_fds = xwl_dri3_pixmap_from_fds,
|
||||
.fds_from_pixmap = NULL,
|
||||
.open_client = xwl_dri3_open_client,
|
||||
.get_formats = xwl_glamor_get_formats,
|
||||
.get_modifiers = xwl_glamor_get_modifiers,
|
||||
.get_drawable_modifiers = glamor_get_drawable_modifiers,
|
||||
};
|
||||
|
||||
static Bool
|
||||
xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
|
@ -829,8 +991,10 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
|
|||
#endif
|
||||
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
xwl_screen->egl_context = eglCreateContext(
|
||||
xwl_screen->egl_display, config, EGL_NO_CONTEXT, attrib_list);
|
||||
xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
|
||||
EGL_NO_CONFIG_KHR,
|
||||
EGL_NO_CONTEXT,
|
||||
attrib_list);
|
||||
if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
|
||||
ErrorF("Failed to create main EGL context: 0x%x\n", eglGetError());
|
||||
goto error;
|
||||
|
@ -850,8 +1014,29 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen)
|
|||
ErrorF("Driver lacks EGL_KHR_swap_buffers_with_damage, performance "
|
||||
"will be affected\n");
|
||||
|
||||
#ifdef EGL_NV_stream_flush
|
||||
xwl_eglstream->have_egl_stream_flush =
|
||||
epoxy_has_egl_extension(xwl_screen->egl_display,
|
||||
"EGL_NV_stream_flush");
|
||||
#else
|
||||
xwl_eglstream->have_egl_stream_flush = FALSE;
|
||||
#endif /* EGL_NV_stream_flush */
|
||||
|
||||
if (!xwl_eglstream->have_egl_stream_flush)
|
||||
ErrorF("EGL_NV_stream_flush not available, "
|
||||
"this may cause visible corruption.\n");
|
||||
|
||||
xwl_eglstream_init_shaders(xwl_screen);
|
||||
|
||||
if (epoxy_has_gl_extension("GL_OES_EGL_image")) {
|
||||
if (dri3_screen_init(xwl_screen->screen, &xwl_dri3_info))
|
||||
xwl_screen->glvnd_vendor = "nvidia";
|
||||
else
|
||||
ErrorF("DRI3 initialization failed. Performance will be affected.\n");
|
||||
} else {
|
||||
ErrorF("Driver lacks GL_OES_EGL_image, performance will be affected.\n");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
xwl_eglstream_cleanup(xwl_screen);
|
||||
|
@ -861,20 +1046,11 @@ error:
|
|||
static Bool
|
||||
xwl_glamor_eglstream_init_screen(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_eglstream_private *xwl_eglstream =
|
||||
xwl_eglstream_get(xwl_screen);
|
||||
ScreenPtr screen = xwl_screen->screen;
|
||||
|
||||
/* We can just let glamor handle CreatePixmap */
|
||||
screen->DestroyPixmap = xwl_glamor_eglstream_destroy_pixmap;
|
||||
|
||||
xwl_eglstream->SetWindowPixmap = screen->SetWindowPixmap;
|
||||
screen->SetWindowPixmap = xwl_eglstream_set_window_pixmap;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_eglstream_window_private_key,
|
||||
PRIVATE_WINDOW, 0))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -905,7 +1081,7 @@ xwl_eglstream_get_device(struct xwl_screen *xwl_screen)
|
|||
free(devices);
|
||||
out:
|
||||
if (!device)
|
||||
ErrorF("glamor: No eglstream capable devices found\n");
|
||||
LogMessageVerb(X_INFO, 3, "glamor: No eglstream capable devices found\n");
|
||||
return device;
|
||||
}
|
||||
|
||||
|
@ -933,7 +1109,6 @@ xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
|||
&xwl_eglstream_private_key, xwl_eglstream);
|
||||
|
||||
xwl_eglstream->egl_device = egl_device;
|
||||
xorg_list_init(&xwl_eglstream->pending_streams);
|
||||
|
||||
xwl_screen->eglstream_backend.init_egl = xwl_glamor_eglstream_init_egl;
|
||||
xwl_screen->eglstream_backend.init_wl_registry = xwl_glamor_eglstream_init_wl_registry;
|
||||
|
@ -942,6 +1117,7 @@ xwl_glamor_init_eglstream(struct xwl_screen *xwl_screen)
|
|||
xwl_screen->eglstream_backend.get_wl_buffer_for_pixmap = xwl_glamor_eglstream_get_wl_buffer_for_pixmap;
|
||||
xwl_screen->eglstream_backend.post_damage = xwl_glamor_eglstream_post_damage;
|
||||
xwl_screen->eglstream_backend.allow_commits = xwl_glamor_eglstream_allow_commits;
|
||||
xwl_screen->eglstream_backend.check_flip = xwl_glamor_eglstream_check_flip;
|
||||
xwl_screen->eglstream_backend.is_available = TRUE;
|
||||
xwl_screen->eglstream_backend.backend_flags = XWL_EGL_BACKEND_NO_FLAG;
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@ struct xwl_gbm_private {
|
|||
char *device_name;
|
||||
struct gbm_device *gbm;
|
||||
struct wl_drm *drm;
|
||||
struct zwp_linux_dmabuf_v1 *dmabuf;
|
||||
int drm_fd;
|
||||
int fd_render_node;
|
||||
Bool drm_authenticated;
|
||||
|
@ -98,25 +97,6 @@ gbm_format_for_depth(int depth)
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
wl_drm_format_for_depth(int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 15:
|
||||
return WL_DRM_FORMAT_XRGB1555;
|
||||
case 16:
|
||||
return WL_DRM_FORMAT_RGB565;
|
||||
case 24:
|
||||
return WL_DRM_FORMAT_XRGB8888;
|
||||
case 30:
|
||||
return WL_DRM_FORMAT_ARGB2101010;
|
||||
default:
|
||||
ErrorF("unexpected depth: %d\n", depth);
|
||||
case 32:
|
||||
return WL_DRM_FORMAT_ARGB8888;
|
||||
}
|
||||
}
|
||||
|
||||
static char
|
||||
is_device_path_render_node (const char *device_path)
|
||||
{
|
||||
|
@ -140,6 +120,55 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo,
|
|||
PixmapPtr pixmap;
|
||||
struct xwl_pixmap *xwl_pixmap;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
#ifdef GBM_BO_FD_FOR_PLANE
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
uint64_t modifier = gbm_bo_get_modifier(bo);
|
||||
const int num_planes = gbm_bo_get_plane_count(bo);
|
||||
int fds[GBM_MAX_PLANES];
|
||||
int plane;
|
||||
int attr_num = 0;
|
||||
EGLint img_attrs[64] = {0};
|
||||
enum PlaneAttrs {
|
||||
PLANE_FD,
|
||||
PLANE_OFFSET,
|
||||
PLANE_PITCH,
|
||||
PLANE_MODIFIER_LO,
|
||||
PLANE_MODIFIER_HI,
|
||||
NUM_PLANE_ATTRS
|
||||
};
|
||||
static const EGLint planeAttrs[][NUM_PLANE_ATTRS] = {
|
||||
{
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE0_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE0_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT,
|
||||
},
|
||||
{
|
||||
EGL_DMA_BUF_PLANE1_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE1_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE1_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT,
|
||||
},
|
||||
{
|
||||
EGL_DMA_BUF_PLANE2_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE2_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE2_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT,
|
||||
},
|
||||
{
|
||||
EGL_DMA_BUF_PLANE3_FD_EXT,
|
||||
EGL_DMA_BUF_PLANE3_OFFSET_EXT,
|
||||
EGL_DMA_BUF_PLANE3_PITCH_EXT,
|
||||
EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT,
|
||||
EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT,
|
||||
},
|
||||
};
|
||||
|
||||
for (plane = 0; plane < num_planes; plane++) fds[plane] = -1;
|
||||
#endif
|
||||
|
||||
xwl_pixmap = calloc(1, sizeof(*xwl_pixmap));
|
||||
if (xwl_pixmap == NULL)
|
||||
|
@ -158,10 +187,57 @@ xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo,
|
|||
xwl_glamor_egl_make_current(xwl_screen);
|
||||
xwl_pixmap->bo = bo;
|
||||
xwl_pixmap->buffer = NULL;
|
||||
xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
|
||||
xwl_screen->egl_context,
|
||||
EGL_NATIVE_PIXMAP_KHR,
|
||||
xwl_pixmap->bo, NULL);
|
||||
|
||||
#ifdef GBM_BO_FD_FOR_PLANE
|
||||
if (xwl_gbm->dmabuf_capable) {
|
||||
#define ADD_ATTR(attrs, num, attr) \
|
||||
do { \
|
||||
assert(((num) + 1) < (sizeof(attrs) / sizeof((attrs)[0]))); \
|
||||
(attrs)[(num)++] = (attr); \
|
||||
} while (0)
|
||||
ADD_ATTR(img_attrs, attr_num, EGL_WIDTH);
|
||||
ADD_ATTR(img_attrs, attr_num, gbm_bo_get_width(bo));
|
||||
ADD_ATTR(img_attrs, attr_num, EGL_HEIGHT);
|
||||
ADD_ATTR(img_attrs, attr_num, gbm_bo_get_height(bo));
|
||||
ADD_ATTR(img_attrs, attr_num, EGL_LINUX_DRM_FOURCC_EXT);
|
||||
ADD_ATTR(img_attrs, attr_num, gbm_bo_get_format(bo));
|
||||
|
||||
for (plane = 0; plane < num_planes; plane++) {
|
||||
fds[plane] = gbm_bo_get_fd_for_plane(bo, plane);
|
||||
ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_FD]);
|
||||
ADD_ATTR(img_attrs, attr_num, fds[plane]);
|
||||
ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_OFFSET]);
|
||||
ADD_ATTR(img_attrs, attr_num, gbm_bo_get_offset(bo, plane));
|
||||
ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_PITCH]);
|
||||
ADD_ATTR(img_attrs, attr_num, gbm_bo_get_stride_for_plane(bo, plane));
|
||||
ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_LO]);
|
||||
ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier & 0xFFFFFFFFULL));
|
||||
ADD_ATTR(img_attrs, attr_num, planeAttrs[plane][PLANE_MODIFIER_HI]);
|
||||
ADD_ATTR(img_attrs, attr_num, (uint32_t)(modifier >> 32ULL));
|
||||
}
|
||||
ADD_ATTR(img_attrs, attr_num, EGL_NONE);
|
||||
#undef ADD_ATTR
|
||||
|
||||
xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
|
||||
EGL_NO_CONTEXT,
|
||||
EGL_LINUX_DMA_BUF_EXT,
|
||||
NULL,
|
||||
img_attrs);
|
||||
|
||||
for (plane = 0; plane < num_planes; plane++) {
|
||||
close(fds[plane]);
|
||||
fds[plane] = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
|
||||
xwl_screen->egl_context,
|
||||
EGL_NATIVE_PIXMAP_KHR,
|
||||
xwl_pixmap->bo, NULL);
|
||||
}
|
||||
|
||||
if (xwl_pixmap->image == EGL_NO_IMAGE_KHR)
|
||||
goto error;
|
||||
|
||||
|
@ -215,7 +291,7 @@ xwl_glamor_gbm_create_pixmap(ScreenPtr screen,
|
|||
uint32_t num_modifiers;
|
||||
uint64_t *modifiers = NULL;
|
||||
|
||||
glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
|
||||
xwl_glamor_get_modifiers(screen, format, &num_modifiers, &modifiers);
|
||||
bo = gbm_bo_create_with_modifiers(xwl_gbm->gbm, width, height,
|
||||
format, modifiers, num_modifiers);
|
||||
free(modifiers);
|
||||
|
@ -278,8 +354,6 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
|
|||
unsigned short width = pixmap->drawable.width;
|
||||
unsigned short height = pixmap->drawable.height;
|
||||
uint32_t format;
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
Bool modifier_supported = FALSE;
|
||||
int prime_fd;
|
||||
int num_planes;
|
||||
uint32_t strides[4];
|
||||
|
@ -318,26 +392,11 @@ xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
|
|||
offsets[0] = 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_format) {
|
||||
for (i = 0; i < xwl_format->num_modifiers; i++) {
|
||||
if (xwl_format->modifiers[i] == modifier) {
|
||||
modifier_supported = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_gbm->dmabuf && modifier_supported) {
|
||||
if (xwl_screen->dmabuf &&
|
||||
xwl_glamor_is_modifier_supported(xwl_screen, format, modifier)) {
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
|
||||
params = zwp_linux_dmabuf_v1_create_params(xwl_gbm->dmabuf);
|
||||
params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
|
||||
for (i = 0; i < num_planes; i++) {
|
||||
zwp_linux_buffer_params_v1_add(params, prime_fd, i,
|
||||
offsets[i], strides[i],
|
||||
|
@ -593,83 +652,14 @@ glamor_egl_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
|
|||
return -1;
|
||||
}
|
||||
|
||||
_X_EXPORT Bool
|
||||
glamor_get_formats(ScreenPtr screen,
|
||||
CARD32 *num_formats, CARD32 **formats)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
int i;
|
||||
|
||||
/* Explicitly zero the count as the caller may ignore the return value */
|
||||
*num_formats = 0;
|
||||
|
||||
if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->num_formats == 0)
|
||||
return TRUE;
|
||||
|
||||
*formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
|
||||
if (*formats == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++)
|
||||
(*formats)[i] = xwl_screen->formats[i].format;
|
||||
*num_formats = xwl_screen->num_formats;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_X_EXPORT Bool
|
||||
glamor_get_modifiers(ScreenPtr screen, uint32_t format,
|
||||
uint32_t *num_modifiers, uint64_t **modifiers)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
/* Explicitly zero the count as the caller may ignore the return value */
|
||||
*num_modifiers = 0;
|
||||
|
||||
if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->num_formats == 0)
|
||||
return TRUE;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xwl_format ||
|
||||
(xwl_format->num_modifiers == 1 &&
|
||||
xwl_format->modifiers[0] == DRM_FORMAT_MOD_INVALID))
|
||||
return FALSE;
|
||||
|
||||
*modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
|
||||
if (*modifiers == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < xwl_format->num_modifiers; i++)
|
||||
(*modifiers)[i] = xwl_format->modifiers[i];
|
||||
*num_modifiers = xwl_format->num_modifiers;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const dri3_screen_info_rec xwl_dri3_info = {
|
||||
.version = 2,
|
||||
.open = NULL,
|
||||
.pixmap_from_fds = glamor_pixmap_from_fds,
|
||||
.fds_from_pixmap = glamor_fds_from_pixmap,
|
||||
.open_client = xwl_dri3_open_client,
|
||||
.get_formats = glamor_get_formats,
|
||||
.get_modifiers = glamor_get_modifiers,
|
||||
.get_formats = xwl_glamor_get_formats,
|
||||
.get_modifiers = xwl_glamor_get_modifiers,
|
||||
.get_drawable_modifiers = glamor_get_drawable_modifiers,
|
||||
};
|
||||
|
||||
|
@ -797,54 +787,6 @@ static const struct wl_drm_listener xwl_drm_listener = {
|
|||
xwl_drm_handle_capabilities
|
||||
};
|
||||
|
||||
static void
|
||||
xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format, uint32_t modifier_hi,
|
||||
uint32_t modifier_lo)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_format == NULL) {
|
||||
xwl_screen->num_formats++;
|
||||
xwl_screen->formats = realloc(xwl_screen->formats,
|
||||
xwl_screen->num_formats * sizeof(*xwl_format));
|
||||
if (!xwl_screen->formats)
|
||||
return;
|
||||
xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
|
||||
xwl_format->format = format;
|
||||
xwl_format->num_modifiers = 0;
|
||||
xwl_format->modifiers = NULL;
|
||||
}
|
||||
|
||||
xwl_format->num_modifiers++;
|
||||
xwl_format->modifiers = realloc(xwl_format->modifiers,
|
||||
xwl_format->num_modifiers * sizeof(uint64_t));
|
||||
if (!xwl_format->modifiers)
|
||||
return;
|
||||
xwl_format->modifiers[xwl_format->num_modifiers - 1] = (uint64_t) modifier_lo;
|
||||
xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
|
||||
}
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
|
||||
.format = xwl_dmabuf_handle_format,
|
||||
.modifier = xwl_dmabuf_handle_modifier
|
||||
};
|
||||
|
||||
Bool
|
||||
xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
|
@ -862,22 +804,6 @@ xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
{
|
||||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
|
||||
if (version < 3)
|
||||
return FALSE;
|
||||
|
||||
xwl_gbm->dmabuf =
|
||||
wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
|
||||
zwp_linux_dmabuf_v1_add_listener(xwl_gbm->dmabuf, &xwl_dmabuf_listener, xwl_screen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *wl_registry,
|
||||
|
@ -909,7 +835,7 @@ xwl_glamor_gbm_has_wl_interfaces(struct xwl_screen *xwl_screen)
|
|||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
|
||||
if (xwl_gbm->drm == NULL) {
|
||||
ErrorF("glamor: 'wl_drm' not supported\n");
|
||||
LogMessageVerb(X_INFO, 3, "glamor: 'wl_drm' not supported\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -955,12 +881,12 @@ xwl_glamor_try_big_gl_api(struct xwl_screen *xwl_screen)
|
|||
eglBindAPI(EGL_OPENGL_API);
|
||||
|
||||
xwl_screen->egl_context =
|
||||
eglCreateContext(xwl_screen->egl_display, NULL,
|
||||
eglCreateContext(xwl_screen->egl_display, EGL_NO_CONFIG_KHR,
|
||||
EGL_NO_CONTEXT, config_attribs_core);
|
||||
|
||||
if (xwl_screen->egl_context == EGL_NO_CONTEXT)
|
||||
xwl_screen->egl_context =
|
||||
eglCreateContext(xwl_screen->egl_display, NULL,
|
||||
eglCreateContext(xwl_screen->egl_display, EGL_NO_CONFIG_KHR,
|
||||
EGL_NO_CONTEXT, NULL);
|
||||
|
||||
if (!xwl_glamor_try_to_make_context_current(xwl_screen)) {
|
||||
|
@ -994,7 +920,8 @@ xwl_glamor_try_gles_api(struct xwl_screen *xwl_screen)
|
|||
|
||||
eglBindAPI(EGL_OPENGL_ES_API);
|
||||
|
||||
xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display, NULL,
|
||||
xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
|
||||
EGL_NO_CONFIG_KHR,
|
||||
EGL_NO_CONTEXT, gles_attribs);
|
||||
|
||||
if (!xwl_glamor_try_to_make_context_current(xwl_screen)) {
|
||||
|
@ -1012,6 +939,7 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
|
|||
struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
|
||||
EGLint major, minor;
|
||||
const GLubyte *renderer;
|
||||
const char *gbm_backend_name;
|
||||
|
||||
if (!xwl_gbm->fd_render_node && !xwl_gbm->drm_authenticated) {
|
||||
ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
|
||||
|
@ -1063,6 +991,11 @@ xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
|
|||
"EXT_image_dma_buf_import_modifiers"))
|
||||
xwl_gbm->dmabuf_capable = TRUE;
|
||||
|
||||
gbm_backend_name = gbm_device_get_backend_name(xwl_gbm->gbm);
|
||||
/* Mesa uses "drm" as backend name, in that case, just do nothing */
|
||||
if (gbm_backend_name && strcmp(gbm_backend_name, "drm") != 0)
|
||||
xwl_screen->glvnd_vendor = gbm_backend_name;
|
||||
|
||||
return TRUE;
|
||||
error:
|
||||
if (xwl_screen->egl_display != EGL_NO_DISPLAY) {
|
||||
|
@ -1137,8 +1070,8 @@ xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
|
|||
xwl_screen->gbm_backend.init_egl = xwl_glamor_gbm_init_egl;
|
||||
xwl_screen->gbm_backend.init_screen = xwl_glamor_gbm_init_screen;
|
||||
xwl_screen->gbm_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
|
||||
xwl_screen->gbm_backend.check_flip = NULL;
|
||||
xwl_screen->gbm_backend.is_available = TRUE;
|
||||
xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_HAS_PRESENT_FLIP |
|
||||
XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH |
|
||||
xwl_screen->gbm_backend.backend_flags = XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH |
|
||||
XWL_EGL_BACKEND_NEEDS_N_BUFFERING;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
#include "glx_extinit.h"
|
||||
#endif
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "drm-client-protocol.h"
|
||||
#include <drm_fourcc.h>
|
||||
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-glx.h"
|
||||
#include "xwayland-screen.h"
|
||||
|
@ -54,10 +58,12 @@ glamor_egl_make_current(struct glamor_context *glamor_ctx)
|
|||
void
|
||||
xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
if (lastGLContext == xwl_screen->glamor_ctx)
|
||||
EGLContext ctx = xwl_screen->glamor_ctx->ctx;
|
||||
|
||||
if (lastGLContext == ctx)
|
||||
return;
|
||||
|
||||
lastGLContext = xwl_screen->glamor_ctx;
|
||||
lastGLContext = ctx;
|
||||
xwl_screen->glamor_ctx->make_current(xwl_screen->glamor_ctx);
|
||||
}
|
||||
|
||||
|
@ -75,6 +81,193 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
|
|||
xwl_screen->glamor_ctx = glamor_ctx;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_check_flip(PixmapPtr pixmap)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
||||
|
||||
if (!xwl_glamor_pixmap_get_wl_buffer(pixmap))
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->egl_backend->check_flip)
|
||||
return xwl_screen->egl_backend->check_flip(pixmap);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
|
||||
uint32_t format, uint64_t modifier)
|
||||
{
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_format) {
|
||||
for (i = 0; i < xwl_format->num_modifiers; i++) {
|
||||
if (xwl_format->modifiers[i] == modifier) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
wl_drm_format_for_depth(int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 15:
|
||||
return WL_DRM_FORMAT_XRGB1555;
|
||||
case 16:
|
||||
return WL_DRM_FORMAT_RGB565;
|
||||
case 24:
|
||||
return WL_DRM_FORMAT_XRGB8888;
|
||||
case 30:
|
||||
return WL_DRM_FORMAT_ARGB2101010;
|
||||
default:
|
||||
ErrorF("unexpected depth: %d\n", depth);
|
||||
case 32:
|
||||
return WL_DRM_FORMAT_ARGB8888;
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_get_formats(ScreenPtr screen,
|
||||
CARD32 *num_formats, CARD32 **formats)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
int i;
|
||||
|
||||
/* Explicitly zero the count as the caller may ignore the return value */
|
||||
*num_formats = 0;
|
||||
|
||||
if (!xwl_screen->dmabuf)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->num_formats == 0)
|
||||
return TRUE;
|
||||
|
||||
*formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
|
||||
if (*formats == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++)
|
||||
(*formats)[i] = xwl_screen->formats[i].format;
|
||||
*num_formats = xwl_screen->num_formats;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format,
|
||||
uint32_t *num_modifiers, uint64_t **modifiers)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
/* Explicitly zero the count as the caller may ignore the return value */
|
||||
*num_modifiers = 0;
|
||||
|
||||
if (!xwl_screen->dmabuf)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->num_formats == 0)
|
||||
return TRUE;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xwl_format ||
|
||||
(xwl_format->num_modifiers == 1 &&
|
||||
xwl_format->modifiers[0] == DRM_FORMAT_MOD_INVALID))
|
||||
return FALSE;
|
||||
|
||||
*modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
|
||||
if (*modifiers == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < xwl_format->num_modifiers; i++)
|
||||
(*modifiers)[i] = xwl_format->modifiers[i];
|
||||
*num_modifiers = xwl_format->num_modifiers;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
|
||||
uint32_t format, uint32_t modifier_hi,
|
||||
uint32_t modifier_lo)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
struct xwl_format *xwl_format = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < xwl_screen->num_formats; i++) {
|
||||
if (xwl_screen->formats[i].format == format) {
|
||||
xwl_format = &xwl_screen->formats[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_format == NULL) {
|
||||
xwl_screen->num_formats++;
|
||||
xwl_screen->formats = realloc(xwl_screen->formats,
|
||||
xwl_screen->num_formats * sizeof(*xwl_format));
|
||||
if (!xwl_screen->formats)
|
||||
return;
|
||||
xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
|
||||
xwl_format->format = format;
|
||||
xwl_format->num_modifiers = 0;
|
||||
xwl_format->modifiers = NULL;
|
||||
}
|
||||
|
||||
xwl_format->num_modifiers++;
|
||||
xwl_format->modifiers = realloc(xwl_format->modifiers,
|
||||
xwl_format->num_modifiers * sizeof(uint64_t));
|
||||
if (!xwl_format->modifiers)
|
||||
return;
|
||||
xwl_format->modifiers[xwl_format->num_modifiers - 1] = (uint64_t) modifier_lo;
|
||||
xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t) modifier_hi << 32;
|
||||
}
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
|
||||
.format = xwl_dmabuf_handle_format,
|
||||
.modifier = xwl_dmabuf_handle_modifier
|
||||
};
|
||||
|
||||
Bool
|
||||
xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
{
|
||||
if (version < 3)
|
||||
return FALSE;
|
||||
|
||||
xwl_screen->dmabuf =
|
||||
wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 3);
|
||||
zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
|
||||
struct wl_registry *registry,
|
||||
|
@ -89,11 +282,11 @@ xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
|
|||
version)) {
|
||||
/* no-op */
|
||||
} else if (xwl_screen->eglstream_backend.is_available &&
|
||||
xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
|
||||
registry,
|
||||
id,
|
||||
interface,
|
||||
version)) {
|
||||
xwl_screen->eglstream_backend.init_wl_registry(xwl_screen,
|
||||
registry,
|
||||
id,
|
||||
interface,
|
||||
version)) {
|
||||
/* no-op */
|
||||
}
|
||||
}
|
||||
|
@ -116,14 +309,16 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Bool
|
||||
xwl_glamor_post_damage(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
|
||||
|
||||
if (xwl_screen->egl_backend->post_damage)
|
||||
xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
|
||||
return xwl_screen->egl_backend->post_damage(xwl_window, pixmap, region);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Bool
|
||||
|
@ -174,16 +369,6 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
|||
return 0;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_has_present_flip(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
|
||||
return FALSE;
|
||||
|
||||
return (xwl_screen->egl_backend->backend_flags &
|
||||
XWL_EGL_BACKEND_HAS_PRESENT_FLIP);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
|
@ -227,10 +412,12 @@ xwl_glamor_select_gbm_backend(struct xwl_screen *xwl_screen)
|
|||
if (xwl_screen->gbm_backend.is_available &&
|
||||
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->gbm_backend)) {
|
||||
xwl_screen->egl_backend = &xwl_screen->gbm_backend;
|
||||
LogMessageVerb(X_INFO, 3, "glamor: Using GBM backend\n");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
ErrorF("Missing Wayland requirements for glamor GBM backend\n");
|
||||
LogMessageVerb(X_INFO, 3,
|
||||
"Missing Wayland requirements for glamor GBM backend\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
|
@ -242,13 +429,13 @@ xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
|
|||
#ifdef XWL_HAS_EGLSTREAM
|
||||
if (xwl_screen->eglstream_backend.is_available &&
|
||||
xwl_glamor_has_wl_interfaces(xwl_screen, &xwl_screen->eglstream_backend)) {
|
||||
ErrorF("glamor: Using nvidia's EGLStream interface, direct rendering impossible.\n");
|
||||
ErrorF("glamor: Performance may be affected. Ask your vendor to support GBM!\n");
|
||||
xwl_screen->egl_backend = &xwl_screen->eglstream_backend;
|
||||
LogMessageVerb(X_INFO, 3, "glamor: Using EGLStream backend\n");
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
ErrorF("Missing Wayland requirements for glamor EGLStream backend\n");
|
||||
LogMessageVerb(X_INFO, 3,
|
||||
"Missing Wayland requirements for glamor EGLStream backend\n");
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
|
@ -257,14 +444,10 @@ xwl_glamor_select_eglstream_backend(struct xwl_screen *xwl_screen)
|
|||
void
|
||||
xwl_glamor_select_backend(struct xwl_screen *xwl_screen, Bool use_eglstream)
|
||||
{
|
||||
if (use_eglstream) {
|
||||
if (!xwl_glamor_select_eglstream_backend(xwl_screen))
|
||||
if (!xwl_glamor_select_eglstream_backend(xwl_screen)) {
|
||||
if (!use_eglstream)
|
||||
xwl_glamor_select_gbm_backend(xwl_screen);
|
||||
}
|
||||
else {
|
||||
if (!xwl_glamor_select_gbm_backend(xwl_screen))
|
||||
xwl_glamor_select_eglstream_backend(xwl_screen);
|
||||
}
|
||||
}
|
||||
|
||||
Bool
|
||||
|
|
|
@ -34,9 +34,8 @@
|
|||
|
||||
typedef enum _xwl_egl_backend_flags {
|
||||
XWL_EGL_BACKEND_NO_FLAG = 0,
|
||||
XWL_EGL_BACKEND_HAS_PRESENT_FLIP = (1 << 0),
|
||||
XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH = (1 << 1),
|
||||
XWL_EGL_BACKEND_NEEDS_N_BUFFERING = (1 << 2),
|
||||
XWL_EGL_BACKEND_NEEDS_BUFFER_FLUSH = (1 << 0),
|
||||
XWL_EGL_BACKEND_NEEDS_N_BUFFERING = (1 << 1),
|
||||
} xwl_egl_backend_flags;
|
||||
|
||||
struct xwl_egl_backend {
|
||||
|
@ -84,7 +83,7 @@ struct xwl_egl_backend {
|
|||
* you should implement blitting from the glamor pixmap to the wayland
|
||||
* pixmap here. Otherwise, this callback is optional.
|
||||
*/
|
||||
void (*post_damage)(struct xwl_window *xwl_window,
|
||||
Bool (*post_damage)(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region);
|
||||
|
||||
/* Called by Xwayland to confirm with the egl backend that the given
|
||||
|
@ -92,6 +91,11 @@ struct xwl_egl_backend {
|
|||
* callback is optional.
|
||||
*/
|
||||
Bool (*allow_commits)(struct xwl_window *xwl_window);
|
||||
|
||||
/* Called by Xwayland to check whether the given pixmap can be
|
||||
* presented by xwl_present_flip. If not implemented, assumed TRUE.
|
||||
*/
|
||||
Bool (*check_flip)(PixmapPtr pixmap);
|
||||
};
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
|
@ -113,14 +117,20 @@ void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
|
|||
uint32_t version);
|
||||
Bool xwl_glamor_has_wl_interfaces(struct xwl_screen *xwl_screen,
|
||||
struct xwl_egl_backend *xwl_egl_backend);
|
||||
void xwl_glamor_post_damage(struct xwl_window *xwl_window,
|
||||
Bool xwl_glamor_post_damage(struct xwl_window *xwl_window,
|
||||
PixmapPtr pixmap, RegionPtr region);
|
||||
Bool xwl_glamor_allow_commits(struct xwl_window *xwl_window);
|
||||
void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_glamor_has_present_flip(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_glamor_needs_buffer_flush(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_glamor_needs_n_buffering(struct xwl_screen *xwl_screen);
|
||||
|
||||
Bool xwl_glamor_is_modifier_supported(struct xwl_screen *xwl_screen,
|
||||
uint32_t format, uint64_t modifier);
|
||||
uint32_t wl_drm_format_for_depth(int depth);
|
||||
Bool xwl_glamor_get_formats(ScreenPtr screen,
|
||||
CARD32 *num_formats, CARD32 **formats);
|
||||
Bool xwl_glamor_get_modifiers(ScreenPtr screen, uint32_t format,
|
||||
uint32_t *num_modifiers, uint64_t **modifiers);
|
||||
Bool xwl_glamor_check_flip(PixmapPtr pixmap);
|
||||
|
||||
#ifdef XV
|
||||
/* glamor Xv Adaptor */
|
||||
|
|
|
@ -138,7 +138,6 @@ egl_create_glx_drawable(ClientPtr client, __GLXscreen *screen,
|
|||
/*
|
||||
* TODO:
|
||||
*
|
||||
* - figure out sRGB
|
||||
* - bindToTextureTargets is suspicious
|
||||
* - better channel mask setup
|
||||
* - drawable type masks is suspicious
|
||||
|
@ -146,7 +145,8 @@ egl_create_glx_drawable(ClientPtr client, __GLXscreen *screen,
|
|||
static struct egl_config *
|
||||
translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
|
||||
struct egl_config *chain, Bool direct_color,
|
||||
Bool double_buffer, Bool duplicate_for_composite)
|
||||
Bool double_buffer, Bool duplicate_for_composite,
|
||||
Bool srgb_only)
|
||||
{
|
||||
EGLint value;
|
||||
struct egl_config *c = calloc(1, sizeof *c);
|
||||
|
@ -167,7 +167,6 @@ translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
|
|||
c->base.optimalPbufferHeight = 0;
|
||||
c->base.bindToMipmapTexture = 0;
|
||||
c->base.bindToTextureTargets = GLX_DONT_CARE;
|
||||
c->base.sRGBCapable = 0;
|
||||
c->base.swapMethod = GLX_SWAP_UNDEFINED_OML;
|
||||
|
||||
/* this is... suspect */
|
||||
|
@ -242,6 +241,19 @@ translate_eglconfig(struct egl_screen *screen, EGLConfig hc,
|
|||
/* else panic */
|
||||
}
|
||||
|
||||
/* derived state: sRGB. EGL doesn't put this in the fbconfig at all,
|
||||
* it's a property of the surface specified at creation time, so we have
|
||||
* to infer it from the GL's extensions. only makes sense at 8bpc though.
|
||||
*/
|
||||
if (srgb_only) {
|
||||
if (c->base.redBits == 8) {
|
||||
c->base.sRGBCapable = GL_TRUE;
|
||||
} else {
|
||||
free(c);
|
||||
return chain;
|
||||
}
|
||||
}
|
||||
|
||||
/* map to the backend's config */
|
||||
c->config = hc;
|
||||
|
||||
|
@ -314,6 +326,9 @@ egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen)
|
|||
int i, j, k, nconfigs;
|
||||
struct egl_config *c = NULL;
|
||||
EGLConfig *host_configs = NULL;
|
||||
bool can_srgb = epoxy_has_gl_extension("GL_ARB_framebuffer_sRGB") ||
|
||||
epoxy_has_gl_extension("GL_EXT_framebuffer_sRGB") ||
|
||||
epoxy_has_gl_extension("GL_EXT_sRGB_write_control");
|
||||
|
||||
eglGetConfigs(screen->display, NULL, 0, &nconfigs);
|
||||
if (!(host_configs = calloc(nconfigs, sizeof *host_configs)))
|
||||
|
@ -326,11 +341,20 @@ egl_mirror_configs(ScreenPtr pScreen, struct egl_screen *screen)
|
|||
*/
|
||||
for (i = nconfigs - 1; i > 0; i--)
|
||||
for (j = 0; j < 3; j++) /* direct_color */
|
||||
for (k = 0; k < 2; k++) /* double_buffer */
|
||||
for (k = 0; k < 2; k++) /* double_buffer */ {
|
||||
if (can_srgb)
|
||||
c = translate_eglconfig(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,
|
||||
/* direct_color */ j == 1,
|
||||
/* double_buffer */ k > 0,
|
||||
/* duplicate_for_composite */ j == 0);
|
||||
/* duplicate_for_composite */ j == 0,
|
||||
/* srgb_only */ false);
|
||||
}
|
||||
|
||||
screen->configs = host_configs;
|
||||
return c ? &c->base : NULL;
|
||||
|
@ -378,6 +402,9 @@ egl_screen_probe(ScreenPtr pScreen)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (!screen->base.glvnd && xwl_screen->glvnd_vendor)
|
||||
screen->base.glvnd = strdup(xwl_screen->glvnd_vendor);
|
||||
|
||||
if (!screen->base.glvnd)
|
||||
screen->base.glvnd = strdup("mesa");
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "relative-pointer-unstable-v1-client-protocol.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
|
||||
|
||||
struct axis_discrete_pending {
|
||||
|
@ -242,6 +243,51 @@ xwl_pointer_proc_relative(DeviceIntPtr device, int what)
|
|||
#undef NAXES
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_pointer_proc_pointer_gestures(DeviceIntPtr device, int what)
|
||||
{
|
||||
#define NTOUCHPOINTS 20
|
||||
#define NAXES 2
|
||||
Atom axes_labels[NAXES] = { 0 };
|
||||
|
||||
switch (what) {
|
||||
case DEVICE_INIT:
|
||||
device->public.on = FALSE;
|
||||
|
||||
/* We need to setup a pointer device so that the device is attached to
|
||||
master pointer device.
|
||||
*/
|
||||
axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
|
||||
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
|
||||
|
||||
if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
|
||||
GetMotionHistorySize(), Relative))
|
||||
return BadValue;
|
||||
|
||||
InitValuatorAxisStruct(device, 0, axes_labels[0],
|
||||
NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
|
||||
InitValuatorAxisStruct(device, 1, axes_labels[1],
|
||||
NO_AXIS_LIMITS, NO_AXIS_LIMITS, 0, 0, 0, Relative);
|
||||
|
||||
InitGestureClassDeviceStruct(device, NTOUCHPOINTS);
|
||||
return Success;
|
||||
|
||||
case DEVICE_ON:
|
||||
device->public.on = TRUE;
|
||||
return Success;
|
||||
|
||||
case DEVICE_OFF:
|
||||
case DEVICE_CLOSE:
|
||||
device->public.on = FALSE;
|
||||
return Success;
|
||||
}
|
||||
|
||||
return BadMatch;
|
||||
|
||||
#undef NTOUCHPOINTS
|
||||
#undef NAXES
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_keyboard_control(DeviceIntPtr device, KeybdCtrl *ctrl)
|
||||
{
|
||||
|
@ -427,6 +473,9 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
|
|||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
if (!is_surface_from_xwl_window(surface))
|
||||
return;
|
||||
|
||||
xwl_seat->xwl_screen->serial = serial;
|
||||
xwl_seat->pointer_enter_serial = serial;
|
||||
|
||||
|
@ -463,11 +512,8 @@ pointer_handle_enter(void *data, struct wl_pointer *pointer,
|
|||
* of our surfaces might not have been shown. In that case we'll
|
||||
* have a cursor surface frame callback pending which we need to
|
||||
* clear so that we can continue submitting new cursor frames. */
|
||||
if (xwl_seat->cursor.frame_cb) {
|
||||
wl_callback_destroy(xwl_seat->cursor.frame_cb);
|
||||
xwl_seat->cursor.frame_cb = NULL;
|
||||
if (xwl_cursor_clear_frame_cb(&xwl_seat->cursor))
|
||||
xwl_seat_set_cursor(xwl_seat);
|
||||
}
|
||||
|
||||
if (xwl_seat->pointer_warp_emulator) {
|
||||
xwl_pointer_warp_emulator_maybe_lock(xwl_seat->pointer_warp_emulator,
|
||||
|
@ -758,6 +804,138 @@ static const struct zwp_relative_pointer_v1_listener relative_pointer_listener =
|
|||
relative_pointer_handle_relative_motion,
|
||||
};
|
||||
|
||||
static void
|
||||
pointer_gesture_swipe_handle_begin(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *swipe,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
struct wl_surface *surface,
|
||||
uint32_t fingers)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
|
||||
if (surface != NULL && !is_surface_from_xwl_window(surface))
|
||||
return;
|
||||
|
||||
xwl_seat->pointer_gesture_swipe_fingers = fingers;
|
||||
QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
|
||||
XI_GestureSwipeBegin, fingers, 0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_gesture_swipe_handle_update(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *swipe,
|
||||
uint32_t time,
|
||||
wl_fixed_t dxf,
|
||||
wl_fixed_t dyf)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
double dx = wl_fixed_to_double(dxf);
|
||||
double dy = wl_fixed_to_double(dyf);
|
||||
|
||||
QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
|
||||
XI_GestureSwipeUpdate,
|
||||
xwl_seat->pointer_gesture_swipe_fingers,
|
||||
0,
|
||||
dx, dy,
|
||||
dx, dy);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_gesture_swipe_handle_end(void *data,
|
||||
struct zwp_pointer_gesture_swipe_v1 *swipe,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
int32_t cancelled)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (cancelled)
|
||||
flags |= XIGestureSwipeEventCancelled;
|
||||
|
||||
QueueGestureSwipeEvents(xwl_seat->pointer_gestures,
|
||||
XI_GestureSwipeEnd,
|
||||
xwl_seat->pointer_gesture_swipe_fingers,
|
||||
flags, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_swipe_v1_listener pointer_gesture_swipe_listener = {
|
||||
pointer_gesture_swipe_handle_begin,
|
||||
pointer_gesture_swipe_handle_update,
|
||||
pointer_gesture_swipe_handle_end
|
||||
};
|
||||
|
||||
static void
|
||||
pointer_gesture_pinch_handle_begin(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *pinch,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
struct wl_surface *surface,
|
||||
uint32_t fingers)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
|
||||
if (surface != NULL && !is_surface_from_xwl_window(surface))
|
||||
return;
|
||||
|
||||
xwl_seat->pointer_gesture_pinch_fingers = fingers;
|
||||
xwl_seat->pointer_gesture_pinch_last_scale = 1.0;
|
||||
QueueGesturePinchEvents(xwl_seat->pointer_gestures,
|
||||
XI_GesturePinchBegin, fingers, 0, 0.0, 0.0, 0.0, 0.0,
|
||||
1.0, 0.0);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_gesture_pinch_handle_update(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *pinch,
|
||||
uint32_t time,
|
||||
wl_fixed_t dxf,
|
||||
wl_fixed_t dyf,
|
||||
wl_fixed_t scalef,
|
||||
wl_fixed_t rotation)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
double dx = wl_fixed_to_double(dxf);
|
||||
double dy = wl_fixed_to_double(dyf);
|
||||
double scale = wl_fixed_to_double(scalef);
|
||||
|
||||
xwl_seat->pointer_gesture_pinch_last_scale = scale;
|
||||
QueueGesturePinchEvents(xwl_seat->pointer_gestures,
|
||||
XI_GesturePinchUpdate,
|
||||
xwl_seat->pointer_gesture_pinch_fingers,
|
||||
0,
|
||||
dx, dy,
|
||||
dx, dy,
|
||||
scale, wl_fixed_to_double(rotation));
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_gesture_pinch_handle_end(void *data,
|
||||
struct zwp_pointer_gesture_pinch_v1 *pinch,
|
||||
uint32_t serial,
|
||||
uint32_t time,
|
||||
int32_t cancelled)
|
||||
{
|
||||
struct xwl_seat *xwl_seat = data;
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (cancelled)
|
||||
flags |= XIGesturePinchEventCancelled;
|
||||
|
||||
QueueGesturePinchEvents(xwl_seat->pointer_gestures,
|
||||
XI_GesturePinchEnd,
|
||||
xwl_seat->pointer_gesture_pinch_fingers,
|
||||
flags, 0.0, 0.0, 0.0, 0.0,
|
||||
xwl_seat->pointer_gesture_pinch_last_scale, 0.0);
|
||||
}
|
||||
|
||||
static const struct zwp_pointer_gesture_pinch_v1_listener pointer_gesture_pinch_listener = {
|
||||
pointer_gesture_pinch_handle_begin,
|
||||
pointer_gesture_pinch_handle_update,
|
||||
pointer_gesture_pinch_handle_end
|
||||
};
|
||||
|
||||
static void
|
||||
keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial,
|
||||
uint32_t time, uint32_t key, uint32_t state)
|
||||
|
@ -834,6 +1012,9 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
|
|||
struct xwl_seat *xwl_seat = data;
|
||||
uint32_t *k;
|
||||
|
||||
if (surface != NULL && !is_surface_from_xwl_window(surface))
|
||||
return;
|
||||
|
||||
xwl_seat->xwl_screen->serial = serial;
|
||||
xwl_seat->keyboard_focus = surface;
|
||||
|
||||
|
@ -1049,6 +1230,9 @@ touch_handle_down(void *data, struct wl_touch *wl_touch,
|
|||
if (surface == NULL)
|
||||
return;
|
||||
|
||||
if (!is_surface_from_xwl_window(surface))
|
||||
return;
|
||||
|
||||
xwl_touch = calloc(1, sizeof *xwl_touch);
|
||||
if (xwl_touch == NULL) {
|
||||
ErrorF("%s: ENOMEM\n", __func__);
|
||||
|
@ -1300,6 +1484,18 @@ release_pointer(struct xwl_seat *xwl_seat)
|
|||
|
||||
static void
|
||||
init_relative_pointer(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
if (xwl_seat->relative_pointer == NULL) {
|
||||
xwl_seat->relative_pointer =
|
||||
add_device(xwl_seat, "xwayland-relative-pointer",
|
||||
xwl_pointer_proc_relative);
|
||||
ActivateDevice(xwl_seat->relative_pointer, TRUE);
|
||||
}
|
||||
enable_device(xwl_seat, xwl_seat->relative_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
init_relative_pointer_listener(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager =
|
||||
xwl_seat->xwl_screen->relative_pointer_manager;
|
||||
|
@ -1312,14 +1508,6 @@ init_relative_pointer(struct xwl_seat *xwl_seat)
|
|||
&relative_pointer_listener,
|
||||
xwl_seat);
|
||||
}
|
||||
|
||||
if (xwl_seat->relative_pointer == NULL) {
|
||||
xwl_seat->relative_pointer =
|
||||
add_device(xwl_seat, "xwayland-relative-pointer",
|
||||
xwl_pointer_proc_relative);
|
||||
ActivateDevice(xwl_seat->relative_pointer, TRUE);
|
||||
}
|
||||
enable_device(xwl_seat, xwl_seat->relative_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1334,6 +1522,64 @@ release_relative_pointer(struct xwl_seat *xwl_seat)
|
|||
disable_device(xwl_seat->relative_pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
init_pointer_gestures_device(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
if (xwl_seat->pointer_gestures == NULL) {
|
||||
xwl_seat->pointer_gestures =
|
||||
add_device(xwl_seat, "xwayland-pointer-gestures",
|
||||
xwl_pointer_proc_pointer_gestures);
|
||||
ActivateDevice(xwl_seat->pointer_gestures, TRUE);
|
||||
}
|
||||
enable_device(xwl_seat, xwl_seat->pointer_gestures);
|
||||
}
|
||||
|
||||
static void
|
||||
init_pointer_gestures_listener(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
struct zwp_pointer_gestures_v1 *pointer_gestures =
|
||||
xwl_seat->xwl_screen->pointer_gestures;
|
||||
|
||||
if (pointer_gestures && !xwl_seat->wp_pointer_gesture_swipe) {
|
||||
xwl_seat->wp_pointer_gesture_swipe =
|
||||
zwp_pointer_gestures_v1_get_swipe_gesture(pointer_gestures,
|
||||
xwl_seat->wl_pointer);
|
||||
zwp_pointer_gesture_swipe_v1_set_user_data(xwl_seat->wp_pointer_gesture_swipe,
|
||||
xwl_seat);
|
||||
zwp_pointer_gesture_swipe_v1_add_listener(xwl_seat->wp_pointer_gesture_swipe,
|
||||
&pointer_gesture_swipe_listener,
|
||||
xwl_seat);
|
||||
}
|
||||
|
||||
if (pointer_gestures && !xwl_seat->wp_pointer_gesture_pinch) {
|
||||
xwl_seat->wp_pointer_gesture_pinch =
|
||||
zwp_pointer_gestures_v1_get_pinch_gesture(pointer_gestures,
|
||||
xwl_seat->wl_pointer);
|
||||
zwp_pointer_gesture_pinch_v1_set_user_data(xwl_seat->wp_pointer_gesture_pinch,
|
||||
xwl_seat);
|
||||
zwp_pointer_gesture_pinch_v1_add_listener(xwl_seat->wp_pointer_gesture_pinch,
|
||||
&pointer_gesture_pinch_listener,
|
||||
xwl_seat);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
release_pointer_gestures_device(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
if (xwl_seat->wp_pointer_gesture_swipe) {
|
||||
zwp_pointer_gesture_swipe_v1_destroy(xwl_seat->wp_pointer_gesture_swipe);
|
||||
xwl_seat->wp_pointer_gesture_swipe = NULL;
|
||||
}
|
||||
|
||||
if (xwl_seat->wp_pointer_gesture_pinch) {
|
||||
zwp_pointer_gesture_pinch_v1_destroy(xwl_seat->wp_pointer_gesture_pinch);
|
||||
xwl_seat->wp_pointer_gesture_pinch = NULL;
|
||||
}
|
||||
|
||||
if (xwl_seat->pointer_gestures)
|
||||
disable_device(xwl_seat->pointer_gestures);
|
||||
}
|
||||
|
||||
static void
|
||||
init_keyboard(struct xwl_seat *xwl_seat)
|
||||
{
|
||||
|
@ -1406,9 +1652,13 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
|
|||
if (caps & WL_SEAT_CAPABILITY_POINTER && xwl_seat->wl_pointer == NULL) {
|
||||
init_pointer(xwl_seat);
|
||||
init_relative_pointer(xwl_seat);
|
||||
init_relative_pointer_listener(xwl_seat);
|
||||
init_pointer_gestures_device(xwl_seat);
|
||||
init_pointer_gestures_listener(xwl_seat);
|
||||
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && xwl_seat->wl_pointer) {
|
||||
release_pointer(xwl_seat);
|
||||
release_relative_pointer(xwl_seat);
|
||||
release_pointer_gestures_device(xwl_seat);
|
||||
}
|
||||
|
||||
if (caps & WL_SEAT_CAPABILITY_KEYBOARD && xwl_seat->wl_keyboard == NULL) {
|
||||
|
@ -1448,14 +1698,6 @@ xwl_cursor_init(struct xwl_cursor *xwl_cursor, struct xwl_screen *xwl_screen,
|
|||
xwl_cursor->needs_update = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_release(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
wl_surface_destroy(xwl_cursor->surface);
|
||||
if (xwl_cursor->frame_cb)
|
||||
wl_callback_destroy(xwl_cursor->frame_cb);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_seat_update_cursor(struct xwl_cursor *xwl_cursor)
|
||||
{
|
||||
|
@ -1674,9 +1916,16 @@ tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool,
|
|||
if (wl_surface == NULL)
|
||||
return;
|
||||
|
||||
if (!is_surface_from_xwl_window(wl_surface))
|
||||
return;
|
||||
|
||||
xwl_tablet_tool->proximity_in_serial = serial;
|
||||
xwl_seat->tablet_focus_window = wl_surface_get_user_data(wl_surface);
|
||||
|
||||
/* If there is a cursor surface frame callback pending, we need to clear it
|
||||
* so that we can continue submitting new cursor frames.
|
||||
*/
|
||||
xwl_cursor_clear_frame_cb(&xwl_tablet_tool->cursor);
|
||||
xwl_tablet_tool_set_cursor(xwl_tablet_tool);
|
||||
}
|
||||
|
||||
|
@ -2268,7 +2517,7 @@ tablet_pad_group(void *data,
|
|||
struct xwl_tablet_pad_group *group;
|
||||
|
||||
group = calloc(1, sizeof *group);
|
||||
if (pad == NULL) {
|
||||
if (group == NULL) {
|
||||
ErrorF("%s ENOMEM\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
@ -2562,6 +2811,16 @@ init_pointer_constraints(struct xwl_screen *xwl_screen,
|
|||
1);
|
||||
}
|
||||
|
||||
static void
|
||||
init_pointer_gestures(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
{
|
||||
xwl_screen->pointer_gestures =
|
||||
wl_registry_bind(xwl_screen->registry, id,
|
||||
&zwp_pointer_gestures_v1_interface,
|
||||
1);
|
||||
}
|
||||
|
||||
static void
|
||||
init_keyboard_grab(struct xwl_screen *xwl_screen,
|
||||
uint32_t id, uint32_t version)
|
||||
|
@ -2583,6 +2842,34 @@ init_keyboard_grab(struct xwl_screen *xwl_screen,
|
|||
}
|
||||
}
|
||||
|
||||
/* The compositor may send us wl_seat and its capabilities before sending e.g.
|
||||
relative_pointer_manager or pointer_gesture interfaces. This would result in
|
||||
devices being created in capabilities handler, but listeners not, because
|
||||
the interfaces weren't available at the time. So we manually attempt to setup
|
||||
listeners again.
|
||||
*/
|
||||
static void
|
||||
maybe_init_relative_pointer_listeners_after_capabilities(struct xwl_screen* xwl_screen)
|
||||
{
|
||||
struct xwl_seat *xwl_seat;
|
||||
xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
|
||||
if (xwl_seat->wl_pointer) {
|
||||
init_relative_pointer_listener(xwl_seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_init_pointer_gesture_listeners_after_capabilities(struct xwl_screen* xwl_screen)
|
||||
{
|
||||
struct xwl_seat *xwl_seat;
|
||||
xorg_list_for_each_entry(xwl_seat, &xwl_screen->seat_list, link) {
|
||||
if (xwl_seat->wl_pointer) {
|
||||
init_pointer_gestures_listener(xwl_seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
input_handler(void *data, struct wl_registry *registry, uint32_t id,
|
||||
const char *interface, uint32_t version)
|
||||
|
@ -2594,8 +2881,12 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id,
|
|||
xwl_screen->expecting_event++;
|
||||
} else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
|
||||
init_relative_pointer_manager(xwl_screen, id, version);
|
||||
maybe_init_relative_pointer_listeners_after_capabilities(xwl_screen);
|
||||
} else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
|
||||
init_pointer_constraints(xwl_screen, id, version);
|
||||
} else if (strcmp(interface, "zwp_pointer_gestures_v1") == 0) {
|
||||
init_pointer_gestures(xwl_screen, id, version);
|
||||
maybe_init_pointer_gesture_listeners_after_capabilities(xwl_screen);
|
||||
} else if (strcmp(interface, "zwp_tablet_manager_v2") == 0) {
|
||||
init_tablet_manager(xwl_screen, id, version);
|
||||
} else if (strcmp(interface, "zwp_xwayland_keyboard_grab_manager_v1") == 0) {
|
||||
|
@ -2662,7 +2953,7 @@ sprite_check_lost_focus(SpritePtr sprite, WindowPtr window)
|
|||
|
||||
if (xwl_seat->focus_window == NULL &&
|
||||
xwl_seat->last_xwindow != NullWindow &&
|
||||
IsParent(xwl_seat->last_xwindow, window))
|
||||
(IsParent(xwl_seat->last_xwindow, window) || xwl_seat->last_xwindow == window))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
|
|
|
@ -56,6 +56,7 @@ struct xwl_cursor {
|
|||
struct xwl_seat {
|
||||
DeviceIntPtr pointer;
|
||||
DeviceIntPtr relative_pointer;
|
||||
DeviceIntPtr pointer_gestures;
|
||||
DeviceIntPtr keyboard;
|
||||
DeviceIntPtr touch;
|
||||
DeviceIntPtr stylus;
|
||||
|
@ -65,6 +66,8 @@ struct xwl_seat {
|
|||
struct wl_seat *seat;
|
||||
struct wl_pointer *wl_pointer;
|
||||
struct zwp_relative_pointer_v1 *wp_relative_pointer;
|
||||
struct zwp_pointer_gesture_swipe_v1 *wp_pointer_gesture_swipe;
|
||||
struct zwp_pointer_gesture_pinch_v1 *wp_pointer_gesture_pinch;
|
||||
struct wl_keyboard *wl_keyboard;
|
||||
struct wl_touch *wl_touch;
|
||||
struct zwp_tablet_seat_v2 *tablet_seat;
|
||||
|
@ -80,6 +83,10 @@ struct xwl_seat {
|
|||
struct xwl_cursor cursor;
|
||||
WindowPtr last_xwindow;
|
||||
|
||||
uint32_t pointer_gesture_swipe_fingers;
|
||||
uint32_t pointer_gesture_pinch_fingers;
|
||||
double pointer_gesture_pinch_last_scale;
|
||||
|
||||
struct xorg_list touches;
|
||||
|
||||
size_t keymap_size;
|
||||
|
|
|
@ -35,13 +35,6 @@
|
|||
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | \
|
||||
RR_Rotate_90 | \
|
||||
RR_Rotate_180 | \
|
||||
RR_Rotate_270 | \
|
||||
RR_Reflect_X | \
|
||||
RR_Reflect_Y)
|
||||
|
||||
static void xwl_output_get_xdg_output(struct xwl_output *xwl_output);
|
||||
|
||||
static Rotation
|
||||
|
@ -216,6 +209,8 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)
|
|||
}
|
||||
|
||||
update_desktop_dimensions();
|
||||
|
||||
RRTellChanged(xwl_screen->screen);
|
||||
}
|
||||
|
||||
struct xwl_emulated_mode *
|
||||
|
@ -466,6 +461,85 @@ xwl_output_set_randr_emu_props(struct xwl_screen *xwl_screen, ClientPtr client)
|
|||
xwl_output_set_randr_emu_prop_callback, &prop);
|
||||
}
|
||||
|
||||
static inline void
|
||||
xwl_output_get_emulated_root_size(struct xwl_output *xwl_output,
|
||||
ClientPtr client,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
|
||||
struct xwl_emulated_mode *emulated_mode;
|
||||
|
||||
emulated_mode = xwl_output_get_emulated_mode_for_client(xwl_output, client);
|
||||
/* If not an emulated mode, just return the actual screen size */
|
||||
if (!emulated_mode) {
|
||||
*width = xwl_screen->width;
|
||||
*height = xwl_screen->height;
|
||||
return;
|
||||
}
|
||||
|
||||
if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
|
||||
*width = emulated_mode->width;
|
||||
*height = emulated_mode->height;
|
||||
} else {
|
||||
*width = emulated_mode->height;
|
||||
*height = emulated_mode->width;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_output_get_rr_event_mask(WindowPtr pWin, ClientPtr client)
|
||||
{
|
||||
RREventPtr pRREvent, *pHead;
|
||||
|
||||
dixLookupResourceByType((void **) &pHead, pWin->drawable.id,
|
||||
RREventType, client, DixReadAccess);
|
||||
|
||||
pRREvent = NULL;
|
||||
if (pHead) {
|
||||
for (pRREvent = *pHead; pRREvent; pRREvent = pRREvent->next)
|
||||
if (pRREvent->client == client)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pRREvent)
|
||||
return pRREvent->mask;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_output_notify_emulated_root_size(struct xwl_output *xwl_output,
|
||||
ClientPtr client,
|
||||
int new_emulated_root_width,
|
||||
int new_emulated_root_height)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
|
||||
ScreenPtr pScreen = xwl_screen->screen;
|
||||
WindowPtr pRoot = pScreen->root;
|
||||
xEvent event = {
|
||||
.u.configureNotify.event = pRoot->drawable.id,
|
||||
.u.configureNotify.window = pRoot->drawable.id,
|
||||
.u.configureNotify.aboveSibling = None,
|
||||
.u.configureNotify.x = 0,
|
||||
.u.configureNotify.y = 0,
|
||||
.u.configureNotify.width = new_emulated_root_width,
|
||||
.u.configureNotify.height = new_emulated_root_height,
|
||||
.u.configureNotify.borderWidth = pRoot->borderWidth,
|
||||
.u.configureNotify.override = pRoot->overrideRedirect
|
||||
};
|
||||
event.u.u.type = ConfigureNotify;
|
||||
|
||||
if (!client || client == serverClient || client->clientGone)
|
||||
return;
|
||||
|
||||
if (EventMaskForClient(pRoot, client) & StructureNotifyMask)
|
||||
WriteEventsToClient(client, 1, &event);
|
||||
|
||||
if (xwl_output_get_rr_event_mask(pRoot, client) & RRScreenChangeNotifyMask)
|
||||
RRDeliverScreenEvent(client, pRoot, pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
|
||||
WindowPtr window)
|
||||
|
@ -480,10 +554,16 @@ void
|
|||
xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
|
||||
RRModePtr mode, Bool from_vidmode)
|
||||
{
|
||||
int old_emulated_width, old_emulated_height;
|
||||
int new_emulated_width, new_emulated_height;
|
||||
|
||||
DebugF("XWAYLAND: xwl_output_set_emulated_mode from %s: %dx%d\n",
|
||||
from_vidmode ? "vidmode" : "randr",
|
||||
mode->mode.width, mode->mode.height);
|
||||
|
||||
xwl_output_get_emulated_root_size(xwl_output, client,
|
||||
&old_emulated_width, &old_emulated_height);
|
||||
|
||||
/* modes[0] is the actual (not-emulated) output mode */
|
||||
if (mode == xwl_output->randr_output->modes[0])
|
||||
xwl_output_remove_emulated_mode_for_client(xwl_output, client);
|
||||
|
@ -493,6 +573,15 @@ xwl_output_set_emulated_mode(struct xwl_output *xwl_output, ClientPtr client,
|
|||
xwl_screen_check_resolution_change_emulation(xwl_output->xwl_screen);
|
||||
|
||||
xwl_output_set_randr_emu_props(xwl_output->xwl_screen, client);
|
||||
|
||||
xwl_output_get_emulated_root_size(xwl_output, client,
|
||||
&new_emulated_width, &new_emulated_height);
|
||||
|
||||
if (new_emulated_width != old_emulated_width ||
|
||||
new_emulated_height != old_emulated_height)
|
||||
xwl_output_notify_emulated_root_size(xwl_output, client,
|
||||
new_emulated_width,
|
||||
new_emulated_height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -631,11 +720,31 @@ static const struct zxdg_output_v1_listener xdg_output_listener = {
|
|||
xdg_output_handle_description,
|
||||
};
|
||||
|
||||
#define XRANDR_EMULATION_PROP "RANDR Emulation"
|
||||
static Atom
|
||||
get_rand_emulation_property(void)
|
||||
{
|
||||
const char *emulStr = XRANDR_EMULATION_PROP;
|
||||
|
||||
return MakeAtom(emulStr, strlen(emulStr), TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_output_set_emulated(struct xwl_output *xwl_output)
|
||||
{
|
||||
int32_t val = TRUE;
|
||||
|
||||
RRChangeOutputProperty(xwl_output->randr_output,
|
||||
get_rand_emulation_property(),
|
||||
XA_INTEGER,
|
||||
32, PropModeReplace, 1,
|
||||
&val, FALSE, FALSE);
|
||||
}
|
||||
|
||||
struct xwl_output *
|
||||
xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
|
||||
{
|
||||
struct xwl_output *xwl_output;
|
||||
static int serial;
|
||||
char name[256];
|
||||
|
||||
xwl_output = calloc(1, sizeof *xwl_output);
|
||||
|
@ -654,7 +763,7 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
|
|||
xwl_output->server_output_id = id;
|
||||
wl_output_add_listener(xwl_output->output, &output_listener, xwl_output);
|
||||
|
||||
snprintf(name, sizeof name, "XWAYLAND%d", serial++);
|
||||
snprintf(name, sizeof name, "XWAYLAND%d", xwl_get_next_output_serial());
|
||||
|
||||
xwl_output->xwl_screen = xwl_screen;
|
||||
xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output);
|
||||
|
@ -670,10 +779,12 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
|
|||
ErrorF("Failed creating RandR Output\n");
|
||||
goto err;
|
||||
}
|
||||
xwl_output_set_emulated(xwl_output);
|
||||
|
||||
RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
|
||||
RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
|
||||
RROutputSetConnection(xwl_output->randr_output, RR_Connected);
|
||||
RRTellChanged(xwl_screen->screen);
|
||||
|
||||
/* We want the output to be in the list as soon as created so we can
|
||||
* use it when binding to the xdg-output protocol...
|
||||
|
@ -698,7 +809,12 @@ err:
|
|||
void
|
||||
xwl_output_destroy(struct xwl_output *xwl_output)
|
||||
{
|
||||
wl_output_destroy(xwl_output->output);
|
||||
if (xwl_output->lease_connector)
|
||||
wp_drm_lease_connector_v1_destroy(xwl_output->lease_connector);
|
||||
if (xwl_output->xdg_output)
|
||||
zxdg_output_v1_destroy(xwl_output->xdg_output);
|
||||
if (xwl_output->output)
|
||||
wl_output_destroy(xwl_output->output);
|
||||
free(xwl_output);
|
||||
}
|
||||
|
||||
|
@ -711,12 +827,15 @@ xwl_output_remove(struct xwl_output *xwl_output)
|
|||
|
||||
xorg_list_del(&xwl_output->link);
|
||||
|
||||
RROutputSetConnection(xwl_output->randr_output, RR_Disconnected);
|
||||
|
||||
xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
|
||||
output_get_new_size(it, &width, &height);
|
||||
update_screen_size(xwl_output, width, height);
|
||||
|
||||
RRCrtcDestroy(xwl_output->randr_crtc);
|
||||
RROutputDestroy(xwl_output->randr_output);
|
||||
RRTellChanged(xwl_screen->screen);
|
||||
|
||||
xwl_output_destroy(xwl_output);
|
||||
}
|
||||
|
@ -801,6 +920,10 @@ xwl_randr_output_set_property(ScreenPtr pScreen,
|
|||
Atom property,
|
||||
RRPropertyValuePtr value)
|
||||
{
|
||||
/* RANDR Emulation property is read-only. */
|
||||
if (get_rand_emulation_property() == property)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -846,6 +969,10 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)
|
|||
rp->rrModeDestroy = xwl_randr_mode_destroy;
|
||||
#endif
|
||||
|
||||
rp->rrRequestLease = xwl_randr_request_lease;
|
||||
rp->rrGetLease = xwl_randr_get_lease;
|
||||
rp->rrTerminateLease = xwl_randr_terminate_lease;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -854,6 +981,12 @@ xwl_output_get_xdg_output(struct xwl_output *xwl_output)
|
|||
{
|
||||
struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
|
||||
|
||||
if (!xwl_output->output) {
|
||||
/* This can happen when an output is created from a leasable DRM
|
||||
* connector */
|
||||
return;
|
||||
}
|
||||
|
||||
xwl_output->xdg_output =
|
||||
zxdg_output_manager_v1_get_xdg_output (xwl_screen->xdg_output_manager,
|
||||
xwl_output->output);
|
||||
|
@ -873,3 +1006,10 @@ xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen)
|
|||
xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
|
||||
xwl_output_get_xdg_output(it);
|
||||
}
|
||||
|
||||
int
|
||||
xwl_get_next_output_serial(void)
|
||||
{
|
||||
static int output_name_serial = 0;
|
||||
return output_name_serial++;
|
||||
}
|
||||
|
|
|
@ -34,19 +34,34 @@
|
|||
#include <randrstr.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-drm-lease.h"
|
||||
|
||||
#define ALL_ROTATIONS (RR_Rotate_0 | \
|
||||
RR_Rotate_90 | \
|
||||
RR_Rotate_180 | \
|
||||
RR_Rotate_270 | \
|
||||
RR_Reflect_X | \
|
||||
RR_Reflect_Y)
|
||||
|
||||
struct xwl_output {
|
||||
struct xorg_list link;
|
||||
struct wl_output *output;
|
||||
struct zxdg_output_v1 *xdg_output;
|
||||
uint32_t server_output_id;
|
||||
struct xwl_screen *xwl_screen;
|
||||
RROutputPtr randr_output;
|
||||
RRCrtcPtr randr_crtc;
|
||||
|
||||
/* only for regular outputs */
|
||||
struct wl_output *output;
|
||||
struct zxdg_output_v1 *xdg_output;
|
||||
uint32_t server_output_id;
|
||||
int32_t x, y, width, height, refresh;
|
||||
Rotation rotation;
|
||||
Bool wl_output_done;
|
||||
Bool xdg_output_done;
|
||||
|
||||
/* only for lease-able DRM connectors */
|
||||
struct wp_drm_lease_connector_v1 *lease_connector;
|
||||
struct xwl_drm_lease *lease;
|
||||
struct xwl_drm_lease_device *lease_device;
|
||||
};
|
||||
|
||||
/* Per client per output emulated randr/vidmode resolution info. */
|
||||
|
@ -79,4 +94,6 @@ void xwl_output_set_window_randr_emu_props(struct xwl_screen *xwl_screen,
|
|||
|
||||
void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen);
|
||||
|
||||
int xwl_get_next_output_serial(void);
|
||||
|
||||
#endif /* XWAYLAND_OUTPUT_H */
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
#include "xwayland-pixmap.h"
|
||||
#include "glamor.h"
|
||||
|
||||
|
||||
#define XWL_PRESENT_CAPS PresentCapabilityAsync
|
||||
|
||||
|
||||
/*
|
||||
* When not flipping let Present copy with 60fps.
|
||||
* When flipping wait on frame_callback, otherwise
|
||||
|
@ -68,7 +72,8 @@ xwl_present_window_get_priv(WindowPtr window)
|
|||
|
||||
xorg_list_init(&xwl_present_window->frame_callback_list);
|
||||
xorg_list_init(&xwl_present_window->wait_list);
|
||||
xorg_list_init(&xwl_present_window->release_list);
|
||||
xorg_list_init(&xwl_present_window->flip_queue);
|
||||
xorg_list_init(&xwl_present_window->idle_queue);
|
||||
|
||||
dixSetPrivate(&window->devPrivates,
|
||||
&xwl_present_window_private_key,
|
||||
|
@ -78,11 +83,18 @@ xwl_present_window_get_priv(WindowPtr window)
|
|||
return xwl_present_window;
|
||||
}
|
||||
|
||||
static struct xwl_present_event *
|
||||
xwl_present_event_from_id(uint64_t event_id)
|
||||
{
|
||||
return (struct xwl_present_event*)(uintptr_t)event_id;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_free_timer(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
TimerFree(xwl_present_window->frame_timer);
|
||||
xwl_present_window->frame_timer = NULL;
|
||||
xwl_present_window->timer_armed = 0;
|
||||
}
|
||||
|
||||
static CARD32
|
||||
|
@ -90,24 +102,61 @@ xwl_present_timer_callback(OsTimerPtr timer,
|
|||
CARD32 time,
|
||||
void *arg);
|
||||
|
||||
static present_vblank_ptr
|
||||
xwl_present_get_pending_flip(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
present_vblank_ptr flip_pending;
|
||||
|
||||
if (xorg_list_is_empty(&xwl_present_window->flip_queue))
|
||||
return NULL;
|
||||
|
||||
flip_pending = xorg_list_first_entry(&xwl_present_window->flip_queue, present_vblank_rec,
|
||||
event_queue);
|
||||
|
||||
if (flip_pending->queued)
|
||||
return NULL;
|
||||
|
||||
return flip_pending;
|
||||
}
|
||||
|
||||
static inline Bool
|
||||
xwl_present_has_pending_events(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
return !!xwl_present_window->sync_flip ||
|
||||
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
|
||||
|
||||
return (flip_pending && flip_pending->sync_flip) ||
|
||||
!xorg_list_is_empty(&xwl_present_window->wait_list);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
if (xwl_present_has_pending_events(xwl_present_window)) {
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(xwl_present_window->window);
|
||||
CARD32 now = GetTimeInMillis();
|
||||
CARD32 timeout;
|
||||
|
||||
if (!xorg_list_is_empty(&xwl_present_window->frame_callback_list))
|
||||
if (xwl_window && xwl_window->frame_callback &&
|
||||
!xorg_list_is_empty(&xwl_present_window->frame_callback_list))
|
||||
timeout = TIMER_LEN_FLIP;
|
||||
else
|
||||
timeout = TIMER_LEN_COPY;
|
||||
|
||||
/* Make sure the timer callback runs if at least a second has passed
|
||||
* since we first armed the timer. This can happen e.g. if the Wayland
|
||||
* compositor doesn't send a pending frame event, e.g. because the
|
||||
* Wayland surface isn't visible anywhere.
|
||||
*/
|
||||
if (xwl_present_window->timer_armed) {
|
||||
if ((int)(now - xwl_present_window->timer_armed) > 1000) {
|
||||
xwl_present_timer_callback(xwl_present_window->frame_timer, now,
|
||||
xwl_present_window);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
xwl_present_window->timer_armed = now;
|
||||
}
|
||||
|
||||
xwl_present_window->frame_timer = TimerSet(xwl_present_window->frame_timer,
|
||||
0, timeout,
|
||||
&xwl_present_timer_callback,
|
||||
|
@ -117,6 +166,58 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc);
|
||||
|
||||
static uint32_t
|
||||
xwl_present_query_capabilities(present_screen_priv_ptr screen_priv)
|
||||
{
|
||||
return XWL_PRESENT_CAPS;
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_present_get_ust_msc(ScreenPtr screen,
|
||||
WindowPtr present_window,
|
||||
uint64_t *ust,
|
||||
uint64_t *msc)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
|
||||
if (!xwl_present_window)
|
||||
return BadAlloc;
|
||||
|
||||
*ust = xwl_present_window->ust;
|
||||
*msc = xwl_present_window->msc;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
* When the wait fence or previous flip is completed, it's time
|
||||
* to re-try the request
|
||||
*/
|
||||
static void
|
||||
xwl_present_re_execute(present_vblank_ptr vblank)
|
||||
{
|
||||
uint64_t ust = 0, crtc_msc = 0;
|
||||
|
||||
(void) xwl_present_get_ust_msc(vblank->screen, vblank->window, &ust, &crtc_msc);
|
||||
xwl_present_execute(vblank, ust, crtc_msc);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_flip_try_ready(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
present_vblank_ptr vblank;
|
||||
|
||||
xorg_list_for_each_entry(vblank, &xwl_present_window->flip_queue, event_queue) {
|
||||
if (vblank->queued) {
|
||||
xwl_present_re_execute(vblank);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_release_pixmap(struct xwl_present_event *event)
|
||||
{
|
||||
|
@ -131,18 +232,131 @@ xwl_present_release_pixmap(struct xwl_present_event *event)
|
|||
static void
|
||||
xwl_present_free_event(struct xwl_present_event *event)
|
||||
{
|
||||
if (!event)
|
||||
xwl_present_release_pixmap(event);
|
||||
xorg_list_del(&event->vblank.event_queue);
|
||||
present_vblank_destroy(&event->vblank);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_free_idle_vblank(present_vblank_ptr vblank)
|
||||
{
|
||||
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
|
||||
xwl_present_free_event(xwl_present_event_from_id((uintptr_t)vblank));
|
||||
}
|
||||
|
||||
static WindowPtr
|
||||
xwl_present_toplvl_pixmap_window(WindowPtr window)
|
||||
{
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
PixmapPtr pixmap = (*screen->GetWindowPixmap)(window);
|
||||
WindowPtr w = window;
|
||||
WindowPtr next_w;
|
||||
|
||||
while(w->parent) {
|
||||
next_w = w->parent;
|
||||
if ( (*screen->GetWindowPixmap)(next_w) != pixmap) {
|
||||
break;
|
||||
}
|
||||
w = next_w;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_flips_stop(WindowPtr window)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
present_vblank_ptr vblank, tmp;
|
||||
|
||||
/* Change back to the fast refresh rate */
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
|
||||
/* Free any left over idle vblanks */
|
||||
xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->idle_queue, event_queue)
|
||||
xwl_present_free_idle_vblank(vblank);
|
||||
|
||||
if (xwl_present_window->flip_active) {
|
||||
struct xwl_present_event *event;
|
||||
|
||||
vblank = xwl_present_window->flip_active;
|
||||
event = xwl_present_event_from_id((uintptr_t)vblank);
|
||||
if (event->pixmap)
|
||||
xwl_present_free_idle_vblank(vblank);
|
||||
else
|
||||
xwl_present_free_event(event);
|
||||
|
||||
xwl_present_window->flip_active = NULL;
|
||||
}
|
||||
|
||||
xwl_present_flip_try_ready(xwl_present_window);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_flip_notify_vblank(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
|
||||
{
|
||||
WindowPtr window = vblank->window;
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
|
||||
DebugPresent(("\tn %" PRIu64 " %p %" PRIu64 " %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
|
||||
vblank->event_id, vblank, vblank->exec_msc, vblank->target_msc,
|
||||
vblank->pixmap ? vblank->pixmap->drawable.id : 0,
|
||||
vblank->window ? vblank->window->drawable.id : 0));
|
||||
|
||||
assert (&vblank->event_queue == xwl_present_window->flip_queue.next);
|
||||
|
||||
xorg_list_del(&vblank->event_queue);
|
||||
|
||||
if (xwl_present_window->flip_active) {
|
||||
struct xwl_present_event *event =
|
||||
xwl_present_event_from_id((uintptr_t)xwl_present_window->flip_active);
|
||||
|
||||
if (!event->pixmap)
|
||||
xwl_present_free_event(event);
|
||||
else
|
||||
/* Put the previous flip in the idle_queue and wait for further notice from
|
||||
* the Wayland compositor
|
||||
*/
|
||||
xorg_list_append(&xwl_present_window->flip_active->event_queue, &xwl_present_window->idle_queue);
|
||||
}
|
||||
|
||||
xwl_present_window->flip_active = vblank;
|
||||
|
||||
present_vblank_notify(vblank, PresentCompleteKindPixmap, PresentCompleteModeFlip, ust, crtc_msc);
|
||||
|
||||
if (vblank->abort_flip)
|
||||
xwl_present_flips_stop(window);
|
||||
|
||||
xwl_present_flip_try_ready(xwl_present_window);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_update_window_crtc(present_window_priv_ptr window_priv, RRCrtcPtr crtc, uint64_t new_msc)
|
||||
{
|
||||
/* Crtc unchanged, no offset. */
|
||||
if (crtc == window_priv->crtc)
|
||||
return;
|
||||
|
||||
xwl_present_release_pixmap(event);
|
||||
xorg_list_del(&event->list);
|
||||
free(event);
|
||||
/* No crtc earlier to offset against, just set the crtc. */
|
||||
if (window_priv->crtc == PresentCrtcNeverSet) {
|
||||
window_priv->msc_offset = 0;
|
||||
window_priv->crtc = crtc;
|
||||
return;
|
||||
}
|
||||
|
||||
/* In window-mode the last correct msc-offset is always kept
|
||||
* in window-priv struct because msc is saved per window and
|
||||
* not per crtc as in screen-mode.
|
||||
*/
|
||||
window_priv->msc_offset += new_msc - window_priv->msc;
|
||||
window_priv->crtc = crtc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xwl_present_cleanup(WindowPtr window)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
present_window_priv_ptr window_priv = present_window_priv(window);
|
||||
struct xwl_present_event *event, *tmp;
|
||||
|
||||
if (!xwl_present_window)
|
||||
|
@ -156,12 +370,7 @@ xwl_present_cleanup(WindowPtr window)
|
|||
}
|
||||
|
||||
/* Clear remaining events */
|
||||
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->wait_list, list)
|
||||
xwl_present_free_event(event);
|
||||
|
||||
xwl_present_free_event(xwl_present_window->sync_flip);
|
||||
|
||||
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_list, list)
|
||||
xorg_list_for_each_entry_safe(event, tmp, &window_priv->vblank, vblank.window_list)
|
||||
xwl_present_free_event(event);
|
||||
|
||||
/* Clear timer */
|
||||
|
@ -178,53 +387,44 @@ xwl_present_cleanup(WindowPtr window)
|
|||
static void
|
||||
xwl_present_buffer_release(void *data)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window;
|
||||
struct xwl_present_event *event = data;
|
||||
present_vblank_ptr vblank;
|
||||
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
xwl_present_release_pixmap(event);
|
||||
vblank = &event->vblank;
|
||||
present_pixmap_idle(vblank->pixmap, vblank->window, vblank->serial, vblank->idle_fence);
|
||||
|
||||
if (!event->abort)
|
||||
present_wnmd_idle_notify(event->xwl_present_window->window, event->event_id);
|
||||
|
||||
if (!event->pending)
|
||||
xwl_present_window = xwl_present_window_priv(vblank->window);
|
||||
if (xwl_present_window->flip_active == vblank ||
|
||||
xwl_present_get_pending_flip(xwl_present_window) == vblank)
|
||||
xwl_present_release_pixmap(event);
|
||||
else
|
||||
xwl_present_free_event(event);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
|
||||
{
|
||||
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
|
||||
uint64_t msc = ++xwl_present_window->msc;
|
||||
struct xwl_present_event *event, *tmp;
|
||||
present_vblank_ptr vblank, tmp;
|
||||
|
||||
xwl_present_window->ust = GetTimeInMicros();
|
||||
|
||||
event = xwl_present_window->sync_flip;
|
||||
xwl_present_window->sync_flip = NULL;
|
||||
if (event) {
|
||||
event->pending = FALSE;
|
||||
xwl_present_window->timer_armed = 0;
|
||||
|
||||
present_wnmd_flip_notify(xwl_present_window->window, event->event_id,
|
||||
xwl_present_window->ust, msc);
|
||||
if (flip_pending && flip_pending->sync_flip)
|
||||
xwl_present_flip_notify_vblank(flip_pending, xwl_present_window->ust, msc);
|
||||
|
||||
if (!event->pixmap) {
|
||||
/* If the buffer was already released, clean up now */
|
||||
xwl_present_free_event(event);
|
||||
} else {
|
||||
xorg_list_add(&event->list, &xwl_present_window->release_list);
|
||||
}
|
||||
}
|
||||
xorg_list_for_each_entry_safe(vblank, tmp, &xwl_present_window->wait_list, event_queue) {
|
||||
if (vblank->exec_msc <= msc) {
|
||||
DebugPresent(("\te %" PRIu64 " ust %" PRIu64 " msc %" PRIu64 "\n",
|
||||
vblank->event_id, xwl_present_window->ust, msc));
|
||||
|
||||
xorg_list_for_each_entry_safe(event, tmp,
|
||||
&xwl_present_window->wait_list,
|
||||
list) {
|
||||
if (event->target_msc <= msc) {
|
||||
present_wnmd_event_notify(xwl_present_window->window,
|
||||
event->event_id,
|
||||
xwl_present_window->ust,
|
||||
msc);
|
||||
xwl_present_free_event(event);
|
||||
xwl_present_execute(vblank, xwl_present_window->ust, msc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,20 +465,13 @@ xwl_present_sync_callback(void *data,
|
|||
struct wl_callback *callback,
|
||||
uint32_t time)
|
||||
{
|
||||
struct xwl_present_event *event = data;
|
||||
struct xwl_present_window *xwl_present_window = event->xwl_present_window;
|
||||
present_vblank_ptr vblank = data;
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(vblank->window);
|
||||
|
||||
wl_callback_destroy(xwl_present_window->sync_callback);
|
||||
xwl_present_window->sync_callback = NULL;
|
||||
|
||||
event->pending = FALSE;
|
||||
|
||||
if (!event->abort)
|
||||
present_wnmd_flip_notify(xwl_present_window->window, event->event_id,
|
||||
xwl_present_window->ust, xwl_present_window->msc);
|
||||
|
||||
if (!event->pixmap)
|
||||
xwl_present_free_event(event);
|
||||
xwl_present_flip_notify_vblank(vblank, xwl_present_window->ust, xwl_present_window->msc);
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener xwl_present_sync_listener = {
|
||||
|
@ -286,7 +479,8 @@ static const struct wl_callback_listener xwl_present_sync_listener = {
|
|||
};
|
||||
|
||||
static RRCrtcPtr
|
||||
xwl_present_get_crtc(WindowPtr present_window)
|
||||
xwl_present_get_crtc(present_screen_priv_ptr screen_priv,
|
||||
WindowPtr present_window)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
|
||||
rrScrPrivPtr rr_private;
|
||||
|
@ -302,46 +496,28 @@ xwl_present_get_crtc(WindowPtr present_window)
|
|||
return rr_private->crtcs[0];
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_present_get_ust_msc(WindowPtr present_window, uint64_t *ust, uint64_t *msc)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
|
||||
if (!xwl_present_window)
|
||||
return BadAlloc;
|
||||
|
||||
*ust = xwl_present_window->ust;
|
||||
*msc = xwl_present_window->msc;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
/*
|
||||
* Queue an event to report back to the Present extension when the specified
|
||||
* MSC has past
|
||||
* MSC has passed
|
||||
*/
|
||||
static int
|
||||
xwl_present_queue_vblank(WindowPtr present_window,
|
||||
xwl_present_queue_vblank(ScreenPtr screen,
|
||||
WindowPtr present_window,
|
||||
RRCrtcPtr crtc,
|
||||
uint64_t event_id,
|
||||
uint64_t msc)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
struct xwl_present_event *event;
|
||||
struct xwl_present_event *event = xwl_present_event_from_id(event_id);
|
||||
|
||||
event = malloc(sizeof *event);
|
||||
if (!event)
|
||||
return BadAlloc;
|
||||
event->vblank.exec_msc = msc;
|
||||
|
||||
event->event_id = event_id;
|
||||
event->pixmap = NULL;
|
||||
event->xwl_present_window = xwl_present_window;
|
||||
event->target_msc = msc;
|
||||
xorg_list_del(&event->vblank.event_queue);
|
||||
xorg_list_append(&event->vblank.event_queue, &xwl_present_window->wait_list);
|
||||
|
||||
xorg_list_append(&event->list, &xwl_present_window->wait_list);
|
||||
|
||||
/* If there's a pending frame callback, use that */
|
||||
if (xwl_window && xwl_window->frame_callback &&
|
||||
/* Hook up to frame callback */
|
||||
if (xwl_window &&
|
||||
xorg_list_is_empty(&xwl_present_window->frame_callback_list)) {
|
||||
xorg_list_add(&xwl_present_window->frame_callback_list,
|
||||
&xwl_window->frame_callback_list);
|
||||
|
@ -359,30 +535,22 @@ xwl_present_queue_vblank(WindowPtr present_window,
|
|||
* to the extension
|
||||
*/
|
||||
static void
|
||||
xwl_present_abort_vblank(WindowPtr present_window,
|
||||
xwl_present_abort_vblank(ScreenPtr screen,
|
||||
WindowPtr present_window,
|
||||
RRCrtcPtr crtc,
|
||||
uint64_t event_id,
|
||||
uint64_t msc)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window);
|
||||
struct xwl_present_event *event, *tmp;
|
||||
static Bool called;
|
||||
|
||||
if (!xwl_present_window)
|
||||
if (called)
|
||||
return;
|
||||
|
||||
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->wait_list, list) {
|
||||
if (event->event_id == event_id) {
|
||||
xwl_present_free_event(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
xorg_list_for_each_entry(event, &xwl_present_window->release_list, list) {
|
||||
if (event->event_id == event_id) {
|
||||
event->abort = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* xwl_present_cleanup should have cleaned up everything,
|
||||
* present_free_window_vblank shouldn't need to call this.
|
||||
*/
|
||||
ErrorF("Unexpected call to %s:\n", __func__);
|
||||
xorg_backtrace();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -392,18 +560,52 @@ xwl_present_flush(WindowPtr window)
|
|||
}
|
||||
|
||||
static Bool
|
||||
xwl_present_check_flip2(RRCrtcPtr crtc,
|
||||
WindowPtr present_window,
|
||||
PixmapPtr pixmap,
|
||||
Bool sync_flip,
|
||||
PresentFlipReason *reason)
|
||||
xwl_present_check_flip(RRCrtcPtr crtc,
|
||||
WindowPtr present_window,
|
||||
PixmapPtr pixmap,
|
||||
Bool sync_flip,
|
||||
RegionPtr valid,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
PresentFlipReason *reason)
|
||||
{
|
||||
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(present_window);
|
||||
struct xwl_window *xwl_window = xwl_window_from_window(present_window);
|
||||
ScreenPtr screen = pixmap->drawable.pScreen;
|
||||
|
||||
if (reason)
|
||||
*reason = PRESENT_FLIP_REASON_UNKNOWN;
|
||||
|
||||
if (!xwl_window)
|
||||
return FALSE;
|
||||
|
||||
if (!crtc)
|
||||
return FALSE;
|
||||
|
||||
/* Source pixmap must align with window exactly */
|
||||
if (x_off || y_off)
|
||||
return FALSE;
|
||||
|
||||
/* Valid area must contain window (for simplicity for now just never flip when one is set). */
|
||||
if (valid)
|
||||
return FALSE;
|
||||
|
||||
/* Flip pixmap must have same dimensions as window */
|
||||
if (present_window->drawable.width != pixmap->drawable.width ||
|
||||
present_window->drawable.height != pixmap->drawable.height)
|
||||
return FALSE;
|
||||
|
||||
/* Window must be same region as toplevel window */
|
||||
if ( !RegionEqual(&present_window->winSize, &toplvl_window->winSize) )
|
||||
return FALSE;
|
||||
|
||||
/* Can't flip if window clipped by children */
|
||||
if (!RegionEqual(&present_window->clipList, &present_window->winSize))
|
||||
return FALSE;
|
||||
|
||||
if (!xwl_glamor_check_flip(pixmap))
|
||||
return FALSE;
|
||||
|
||||
/* Can't flip if the window pixmap doesn't match the xwl_window parent
|
||||
* window's, e.g. because a client redirected this window or one of its
|
||||
* parents.
|
||||
|
@ -422,11 +624,63 @@ xwl_present_check_flip2(RRCrtcPtr crtc,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 'window' is being reconfigured. Check to see if it is involved
|
||||
* in flipping and clean up as necessary.
|
||||
*/
|
||||
static void
|
||||
xwl_present_check_flip_window (WindowPtr window)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
present_window_priv_ptr window_priv = present_window_priv(window);
|
||||
present_vblank_ptr flip_pending;
|
||||
present_vblank_ptr flip_active;
|
||||
present_vblank_ptr vblank;
|
||||
PresentFlipReason reason;
|
||||
|
||||
/* If this window hasn't ever been used with Present, it can't be
|
||||
* flipping
|
||||
*/
|
||||
if (!xwl_present_window || !window_priv)
|
||||
return;
|
||||
|
||||
flip_pending = xwl_present_get_pending_flip(xwl_present_window);
|
||||
flip_active = xwl_present_window->flip_active;
|
||||
|
||||
if (flip_pending) {
|
||||
if (!xwl_present_check_flip(flip_pending->crtc, flip_pending->window, flip_pending->pixmap,
|
||||
flip_pending->sync_flip, flip_pending->valid, 0, 0, NULL))
|
||||
flip_pending->abort_flip = TRUE;
|
||||
} else if (flip_active) {
|
||||
if (!xwl_present_check_flip(flip_active->crtc, flip_active->window, flip_active->pixmap,
|
||||
flip_active->sync_flip, flip_active->valid, 0, 0, NULL))
|
||||
xwl_present_flips_stop(window);
|
||||
}
|
||||
|
||||
/* Now check any queued vblanks */
|
||||
xorg_list_for_each_entry(vblank, &window_priv->vblank, window_list) {
|
||||
if (vblank->queued && vblank->flip &&
|
||||
!xwl_present_check_flip(vblank->crtc, window, vblank->pixmap,
|
||||
vblank->sync_flip, vblank->valid, 0, 0, &reason)) {
|
||||
vblank->flip = FALSE;
|
||||
vblank->reason = reason;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up any pending or current flips for this window
|
||||
*/
|
||||
static void
|
||||
xwl_present_clear_window_flip(WindowPtr window)
|
||||
{
|
||||
/* xwl_present_cleanup cleaned up everything */
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_present_flip(WindowPtr present_window,
|
||||
RRCrtcPtr crtc,
|
||||
uint64_t event_id,
|
||||
uint64_t target_msc,
|
||||
PixmapPtr pixmap,
|
||||
Bool sync_flip,
|
||||
RegionPtr damage)
|
||||
|
@ -435,49 +689,35 @@ xwl_present_flip(WindowPtr present_window,
|
|||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(present_window);
|
||||
BoxPtr damage_box;
|
||||
struct wl_buffer *buffer;
|
||||
struct xwl_present_event *event;
|
||||
struct xwl_present_event *event = xwl_present_event_from_id(event_id);
|
||||
|
||||
if (!xwl_window)
|
||||
return FALSE;
|
||||
|
||||
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
|
||||
if (!buffer) {
|
||||
ErrorF("present: Error getting buffer\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
damage_box = RegionExtents(damage);
|
||||
|
||||
event = malloc(sizeof *event);
|
||||
if (!event)
|
||||
return FALSE;
|
||||
|
||||
pixmap->refcnt++;
|
||||
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap);
|
||||
|
||||
event->event_id = event_id;
|
||||
event->xwl_present_window = xwl_present_window;
|
||||
event->pixmap = pixmap;
|
||||
event->target_msc = target_msc;
|
||||
event->pending = TRUE;
|
||||
event->abort = FALSE;
|
||||
|
||||
if (sync_flip) {
|
||||
xorg_list_init(&event->list);
|
||||
xwl_present_window->sync_flip = event;
|
||||
} else {
|
||||
xorg_list_add(&event->list, &xwl_present_window->release_list);
|
||||
}
|
||||
|
||||
xwl_pixmap_set_buffer_release_cb(pixmap, xwl_present_buffer_release, event);
|
||||
|
||||
/* We can flip directly to the main surface (full screen window without clips) */
|
||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||
|
||||
if (!xwl_window->frame_callback)
|
||||
xwl_window_create_frame_callback(xwl_window);
|
||||
|
||||
if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) {
|
||||
xorg_list_add(&xwl_present_window->frame_callback_list,
|
||||
&xwl_window->frame_callback_list);
|
||||
}
|
||||
|
||||
/* Realign timer */
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
if (!xwl_window->frame_callback)
|
||||
xwl_window_create_frame_callback(xwl_window);
|
||||
|
||||
xwl_surface_damage(xwl_window->xwl_screen, xwl_window->surface,
|
||||
damage_box->x1 - present_window->drawable.x,
|
||||
|
@ -492,7 +732,7 @@ xwl_present_flip(WindowPtr present_window,
|
|||
wl_display_sync(xwl_window->xwl_screen->display);
|
||||
wl_callback_add_listener(xwl_present_window->sync_callback,
|
||||
&xwl_present_sync_listener,
|
||||
event);
|
||||
&event->vblank);
|
||||
}
|
||||
|
||||
wl_display_flush(xwl_window->xwl_screen->display);
|
||||
|
@ -500,13 +740,210 @@ xwl_present_flip(WindowPtr present_window,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Once the required MSC has been reached, execute the pending request.
|
||||
*
|
||||
* For requests to actually present something, either blt contents to
|
||||
* the window pixmap or queue a window buffer swap on the backend.
|
||||
*
|
||||
* For requests to just get the current MSC/UST combo, skip that part and
|
||||
* go straight to event delivery.
|
||||
*/
|
||||
static void
|
||||
xwl_present_flips_stop(WindowPtr window)
|
||||
xwl_present_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_msc)
|
||||
{
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
|
||||
WindowPtr window = vblank->window;
|
||||
struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(window);
|
||||
present_vblank_ptr flip_pending = xwl_present_get_pending_flip(xwl_present_window);
|
||||
|
||||
/* Change back to the fast refresh rate */
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
xorg_list_del(&vblank->event_queue);
|
||||
|
||||
if (present_execute_wait(vblank, crtc_msc))
|
||||
return;
|
||||
|
||||
if (flip_pending && vblank->flip && vblank->pixmap && vblank->window) {
|
||||
DebugPresent(("\tr %" PRIu64 " %p (pending %p)\n",
|
||||
vblank->event_id, vblank, flip_pending));
|
||||
xorg_list_append(&vblank->event_queue, &xwl_present_window->flip_queue);
|
||||
vblank->flip_ready = TRUE;
|
||||
return;
|
||||
}
|
||||
|
||||
vblank->queued = FALSE;
|
||||
|
||||
if (vblank->pixmap && vblank->window) {
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
|
||||
if (vblank->flip) {
|
||||
RegionPtr damage;
|
||||
|
||||
DebugPresent(("\tf %" PRIu64 " %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
|
||||
vblank->event_id, vblank, crtc_msc,
|
||||
vblank->pixmap->drawable.id, vblank->window->drawable.id));
|
||||
|
||||
/* Set update region as damaged */
|
||||
if (vblank->update) {
|
||||
damage = RegionDuplicate(vblank->update);
|
||||
/* Translate update region to screen space */
|
||||
assert(vblank->x_off == 0 && vblank->y_off == 0);
|
||||
RegionTranslate(damage, window->drawable.x, window->drawable.y);
|
||||
RegionIntersect(damage, damage, &window->clipList);
|
||||
} else
|
||||
damage = RegionDuplicate(&window->clipList);
|
||||
|
||||
if (xwl_present_flip(vblank->window, vblank->crtc, vblank->event_id,
|
||||
vblank->pixmap, vblank->sync_flip, damage)) {
|
||||
WindowPtr toplvl_window = xwl_present_toplvl_pixmap_window(vblank->window);
|
||||
PixmapPtr old_pixmap = screen->GetWindowPixmap(window);
|
||||
|
||||
/* Replace window pixmap with flip pixmap */
|
||||
#ifdef COMPOSITE
|
||||
vblank->pixmap->screen_x = old_pixmap->screen_x;
|
||||
vblank->pixmap->screen_y = old_pixmap->screen_y;
|
||||
#endif
|
||||
present_set_tree_pixmap(toplvl_window, old_pixmap, vblank->pixmap);
|
||||
vblank->pixmap->refcnt++;
|
||||
dixDestroyPixmap(old_pixmap, old_pixmap->drawable.id);
|
||||
|
||||
/* Report damage */
|
||||
DamageDamageRegion(&vblank->window->drawable, damage);
|
||||
RegionDestroy(damage);
|
||||
|
||||
/* Put pending flip at the flip queue head */
|
||||
xorg_list_add(&vblank->event_queue, &xwl_present_window->flip_queue);
|
||||
|
||||
/* Realign timer */
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
vblank->flip = FALSE;
|
||||
}
|
||||
DebugPresent(("\tc %p %" PRIu64 ": %08" PRIx32 " -> %08" PRIx32 "\n",
|
||||
vblank, crtc_msc, vblank->pixmap->drawable.id, vblank->window->drawable.id));
|
||||
|
||||
if (flip_pending)
|
||||
flip_pending->abort_flip = TRUE;
|
||||
else if (xwl_present_window->flip_active)
|
||||
xwl_present_flips_stop(window);
|
||||
|
||||
present_execute_copy(vblank, crtc_msc);
|
||||
assert(!vblank->queued);
|
||||
|
||||
/* Clear the pixmap field, so this will fall through to present_execute_post next time */
|
||||
dixDestroyPixmap(vblank->pixmap, vblank->pixmap->drawable.id);
|
||||
vblank->pixmap = NULL;
|
||||
|
||||
if (xwl_present_queue_vblank(screen, window, vblank->crtc,
|
||||
vblank->event_id, crtc_msc + 1)
|
||||
== Success)
|
||||
return;
|
||||
}
|
||||
|
||||
present_execute_post(vblank, ust, crtc_msc);
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_present_pixmap(WindowPtr window,
|
||||
PixmapPtr pixmap,
|
||||
CARD32 serial,
|
||||
RegionPtr valid,
|
||||
RegionPtr update,
|
||||
int16_t x_off,
|
||||
int16_t y_off,
|
||||
RRCrtcPtr target_crtc,
|
||||
SyncFence *wait_fence,
|
||||
SyncFence *idle_fence,
|
||||
uint32_t options,
|
||||
uint64_t target_window_msc,
|
||||
uint64_t divisor,
|
||||
uint64_t remainder,
|
||||
present_notify_ptr notifies,
|
||||
int num_notifies)
|
||||
{
|
||||
uint64_t ust = 0;
|
||||
uint64_t target_msc;
|
||||
uint64_t crtc_msc = 0;
|
||||
int ret;
|
||||
present_vblank_ptr vblank, tmp;
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
present_window_priv_ptr window_priv = present_get_window_priv(window, TRUE);
|
||||
present_screen_priv_ptr screen_priv = present_screen_priv(screen);
|
||||
struct xwl_present_event *event;
|
||||
|
||||
if (!window_priv)
|
||||
return BadAlloc;
|
||||
|
||||
target_crtc = xwl_present_get_crtc(screen_priv, window);
|
||||
|
||||
ret = xwl_present_get_ust_msc(screen, window, &ust, &crtc_msc);
|
||||
|
||||
xwl_present_update_window_crtc(window_priv, target_crtc, crtc_msc);
|
||||
|
||||
if (ret == Success) {
|
||||
/* Stash the current MSC away in case we need it later
|
||||
*/
|
||||
window_priv->msc = crtc_msc;
|
||||
}
|
||||
|
||||
target_msc = present_get_target_msc(target_window_msc + window_priv->msc_offset,
|
||||
crtc_msc,
|
||||
divisor,
|
||||
remainder,
|
||||
options);
|
||||
|
||||
/*
|
||||
* Look for a matching presentation already on the list...
|
||||
*/
|
||||
|
||||
if (!update && pixmap) {
|
||||
xorg_list_for_each_entry_safe(vblank, tmp, &window_priv->vblank, window_list) {
|
||||
|
||||
if (!vblank->pixmap)
|
||||
continue;
|
||||
|
||||
if (!vblank->queued)
|
||||
continue;
|
||||
|
||||
if (vblank->target_msc != target_msc)
|
||||
continue;
|
||||
|
||||
present_vblank_scrap(vblank);
|
||||
if (vblank->flip_ready)
|
||||
xwl_present_re_execute(vblank);
|
||||
}
|
||||
}
|
||||
|
||||
event = calloc(1, sizeof(*event));
|
||||
if (!event)
|
||||
return BadAlloc;
|
||||
|
||||
vblank = &event->vblank;
|
||||
if (!present_vblank_init(vblank, window, pixmap, serial, valid, update, x_off, y_off,
|
||||
target_crtc, wait_fence, idle_fence, options, XWL_PRESENT_CAPS,
|
||||
notifies, num_notifies, target_msc, crtc_msc)) {
|
||||
present_vblank_destroy(vblank);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
vblank->event_id = (uintptr_t)event;
|
||||
|
||||
/* Xwayland presentations always complete (at least) one frame after they
|
||||
* are executed
|
||||
*/
|
||||
vblank->exec_msc = vblank->target_msc - 1;
|
||||
|
||||
vblank->queued = TRUE;
|
||||
if (crtc_msc < vblank->exec_msc) {
|
||||
if (xwl_present_queue_vblank(screen, window, target_crtc, vblank->event_id, vblank->exec_msc) == Success)
|
||||
return Success;
|
||||
|
||||
DebugPresent(("present_queue_vblank failed\n"));
|
||||
}
|
||||
|
||||
xwl_present_execute(vblank, ust, crtc_msc);
|
||||
return Success;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -516,35 +953,47 @@ xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window)
|
|||
* the frame timer interval.
|
||||
*/
|
||||
xorg_list_del(&xwl_present_window->frame_callback_list);
|
||||
|
||||
/* Make sure the timer callback doesn't get called */
|
||||
xwl_present_window->timer_armed = 0;
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
}
|
||||
|
||||
static present_wnmd_info_rec xwl_present_info = {
|
||||
.version = PRESENT_SCREEN_INFO_VERSION,
|
||||
.get_crtc = xwl_present_get_crtc,
|
||||
|
||||
.get_ust_msc = xwl_present_get_ust_msc,
|
||||
.queue_vblank = xwl_present_queue_vblank,
|
||||
.abort_vblank = xwl_present_abort_vblank,
|
||||
|
||||
.flush = xwl_present_flush,
|
||||
|
||||
.capabilities = PresentCapabilityAsync,
|
||||
.check_flip2 = xwl_present_check_flip2,
|
||||
.flip = xwl_present_flip,
|
||||
.flips_stop = xwl_present_flips_stop
|
||||
};
|
||||
|
||||
Bool
|
||||
xwl_present_init(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
present_screen_priv_ptr screen_priv;
|
||||
|
||||
if (!xwl_glamor_has_present_flip(xwl_screen))
|
||||
if (!xwl_screen->glamor || !xwl_screen->egl_backend)
|
||||
return FALSE;
|
||||
|
||||
if (!present_screen_register_priv_keys())
|
||||
return FALSE;
|
||||
|
||||
if (present_screen_priv(screen))
|
||||
return TRUE;
|
||||
|
||||
screen_priv = present_screen_priv_init(screen);
|
||||
if (!screen_priv)
|
||||
return FALSE;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_present_window_private_key, PRIVATE_WINDOW, 0))
|
||||
return FALSE;
|
||||
|
||||
return present_wnmd_screen_init(screen, &xwl_present_info);
|
||||
screen_priv->query_capabilities = xwl_present_query_capabilities;
|
||||
screen_priv->get_crtc = xwl_present_get_crtc;
|
||||
|
||||
screen_priv->check_flip = xwl_present_check_flip;
|
||||
screen_priv->check_flip_window = xwl_present_check_flip_window;
|
||||
screen_priv->clear_window_flip = xwl_present_clear_window_flip;
|
||||
|
||||
screen_priv->present_pixmap = xwl_present_pixmap;
|
||||
screen_priv->queue_vblank = xwl_present_queue_vblank;
|
||||
screen_priv->flush = xwl_present_flush;
|
||||
screen_priv->re_execute = xwl_present_re_execute;
|
||||
|
||||
screen_priv->abort_vblank = xwl_present_abort_vblank;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -29,39 +29,39 @@
|
|||
#include <xwayland-config.h>
|
||||
|
||||
#include <dix.h>
|
||||
#include <present_priv.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
struct xwl_present_window {
|
||||
struct xwl_present_event *sync_flip;
|
||||
WindowPtr window;
|
||||
|
||||
struct xorg_list frame_callback_list;
|
||||
|
||||
uint64_t msc;
|
||||
uint64_t ust;
|
||||
|
||||
OsTimerPtr frame_timer;
|
||||
/* Timestamp when the current timer was first armed */
|
||||
CARD32 timer_armed;
|
||||
|
||||
struct wl_callback *sync_callback;
|
||||
|
||||
struct xorg_list wait_list;
|
||||
struct xorg_list release_list;
|
||||
struct xorg_list flip_queue;
|
||||
struct xorg_list idle_queue;
|
||||
|
||||
present_vblank_ptr flip_active;
|
||||
};
|
||||
|
||||
struct xwl_present_event {
|
||||
uint64_t event_id;
|
||||
uint64_t target_msc;
|
||||
present_vblank_rec vblank;
|
||||
|
||||
Bool abort;
|
||||
Bool pending;
|
||||
|
||||
struct xwl_present_window *xwl_present_window;
|
||||
PixmapPtr pixmap;
|
||||
|
||||
struct xorg_list list;
|
||||
};
|
||||
|
||||
void xwl_present_reset_timer(struct xwl_present_window *xwl_present_window);
|
||||
void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window);
|
||||
Bool xwl_present_init(ScreenPtr screen);
|
||||
void xwl_present_cleanup(WindowPtr window);
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
#include "xwayland-present.h"
|
||||
#include "xwayland-shm.h"
|
||||
|
||||
#ifdef MITSHM
|
||||
#include "shmint.h"
|
||||
#endif
|
||||
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
@ -145,12 +149,31 @@ xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
|||
xwl_window_update_property(xwl_window, rec);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_root_window_finalized_callback(CallbackListPtr *pcbl,
|
||||
void *closure,
|
||||
void *calldata)
|
||||
{
|
||||
ScreenPtr screen = closure;
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_queued_drm_lease_device *queued_device, *next;
|
||||
|
||||
xorg_list_for_each_entry_safe(queued_device, next,
|
||||
&xwl_screen->queued_drm_lease_devices, link) {
|
||||
xwl_screen_add_drm_lease_device(xwl_screen, queued_device->id);
|
||||
xorg_list_del(&queued_device->link);
|
||||
free(queued_device);
|
||||
}
|
||||
DeleteCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, screen);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_close_screen(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_output *xwl_output, *next_xwl_output;
|
||||
struct xwl_seat *xwl_seat, *next_xwl_seat;
|
||||
struct xwl_wl_surface *xwl_wl_surface, *xwl_wl_surface_next;
|
||||
|
||||
DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
|
||||
|
||||
|
@ -164,6 +187,16 @@ xwl_close_screen(ScreenPtr screen)
|
|||
|
||||
xwl_screen_release_tablet_manager(xwl_screen);
|
||||
|
||||
struct xwl_drm_lease_device *device_data, *next;
|
||||
xorg_list_for_each_entry_safe(device_data, next,
|
||||
&xwl_screen->drm_lease_devices, link)
|
||||
xwl_screen_destroy_drm_lease_device(xwl_screen,
|
||||
device_data->drm_lease_device);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_wl_surface, xwl_wl_surface_next,
|
||||
&xwl_screen->pending_wl_surface_destroy, link)
|
||||
xwl_window_surface_do_destroy(xwl_wl_surface);
|
||||
|
||||
RemoveNotifyFd(xwl_screen->wayland_fd);
|
||||
|
||||
wl_display_disconnect(xwl_screen->display);
|
||||
|
@ -388,6 +421,15 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
|
|||
wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version);
|
||||
xwl_screen_init_xdg_output(xwl_screen);
|
||||
}
|
||||
else if (strcmp(interface, "wp_drm_lease_device_v1") == 0) {
|
||||
if (xwl_screen->screen->root == NULL) {
|
||||
struct xwl_queued_drm_lease_device *queued = malloc(sizeof(struct xwl_queued_drm_lease_device));
|
||||
queued->id = id;
|
||||
xorg_list_append(&queued->link, &xwl_screen->queued_drm_lease_devices);
|
||||
} else {
|
||||
xwl_screen_add_drm_lease_device(xwl_screen, id);
|
||||
}
|
||||
}
|
||||
else if (strcmp(interface, "wp_viewporter") == 0) {
|
||||
xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1);
|
||||
}
|
||||
|
@ -404,6 +446,7 @@ global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
|||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
struct xwl_output *xwl_output, *tmp_xwl_output;
|
||||
struct xwl_drm_lease_device *lease_device, *tmp_lease_device;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
|
||||
&xwl_screen->output_list, link) {
|
||||
|
@ -412,6 +455,14 @@ global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xorg_list_for_each_entry_safe(lease_device, tmp_lease_device,
|
||||
&xwl_screen->drm_lease_devices, link) {
|
||||
if (lease_device->id == name) {
|
||||
wp_drm_lease_device_v1_release(lease_device->drm_lease_device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
|
@ -471,13 +522,13 @@ xwl_dispatch_events (struct xwl_screen *xwl_screen)
|
|||
pollout:
|
||||
ready = xwl_display_pollout(xwl_screen, 5);
|
||||
if (ready == -1 && errno != EINTR)
|
||||
xwl_give_up("error polling on XWayland fd: %s\n", strerror(errno));
|
||||
xwl_give_up("error polling on Xwayland fd: %s\n", strerror(errno));
|
||||
|
||||
if (ready > 0)
|
||||
ret = wl_display_flush(xwl_screen->display);
|
||||
|
||||
if (ret == -1 && errno != EAGAIN)
|
||||
xwl_give_up("failed to write to XWayland fd: %s\n", strerror(errno));
|
||||
xwl_give_up("failed to write to Xwayland fd: %s\n", strerror(errno));
|
||||
|
||||
xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
|
||||
}
|
||||
|
@ -534,6 +585,53 @@ xwl_screen_roundtrip(struct xwl_screen *xwl_screen)
|
|||
xwl_give_up("could not connect to wayland server\n");
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_server_grab(ClientPtr client)
|
||||
{
|
||||
struct xwl_screen *xwl_screen;
|
||||
|
||||
/* Allow GrabServer for the X11 window manager.
|
||||
* Xwayland only has 1 screen (no Zaphod for Xwayland) so we check
|
||||
* for the first and only screen here.
|
||||
*/
|
||||
xwl_screen = xwl_screen_get(screenInfo.screens[0]);
|
||||
if (xwl_screen->wm_client_id == client->index)
|
||||
return xwl_screen->GrabServer(client);
|
||||
|
||||
/* For all other clients, just pretend it works for compatibility,
|
||||
but do nothing */
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_server_ungrab(ClientPtr client)
|
||||
{
|
||||
struct xwl_screen *xwl_screen;
|
||||
|
||||
/* Same as above, allow UngrabServer for the X11 window manager only */
|
||||
xwl_screen = xwl_screen_get(screenInfo.screens[0]);
|
||||
if (xwl_screen->wm_client_id == client->index)
|
||||
return xwl_screen->UngrabServer(client);
|
||||
|
||||
/* For all other clients, just pretend it works for compatibility,
|
||||
but do nothing */
|
||||
return Success;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_screen_setup_custom_vector(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
/* Rootfull Xwayland does not need a custom ProcVector (yet?) */
|
||||
if (!xwl_screen->rootless)
|
||||
return;
|
||||
|
||||
xwl_screen->GrabServer = ProcVector[X_GrabServer];
|
||||
xwl_screen->UngrabServer = ProcVector[X_UngrabServer];
|
||||
|
||||
ProcVector[X_GrabServer] = xwl_server_grab;
|
||||
ProcVector[X_UngrabServer] = xwl_server_ungrab;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
||||
{
|
||||
|
@ -545,10 +643,6 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
Bool use_eglstreams = FALSE;
|
||||
#endif
|
||||
|
||||
xwl_screen = calloc(1, sizeof *xwl_screen);
|
||||
if (xwl_screen == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
|
||||
return FALSE;
|
||||
if (!xwl_pixmap_init())
|
||||
|
@ -563,6 +657,10 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
sizeof(struct xwl_client)))
|
||||
return FALSE;
|
||||
|
||||
xwl_screen = calloc(1, sizeof *xwl_screen);
|
||||
if (xwl_screen == NULL)
|
||||
return FALSE;
|
||||
|
||||
dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
|
||||
xwl_screen->screen = pScreen;
|
||||
|
||||
|
@ -615,6 +713,10 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
xorg_list_init(&xwl_screen->seat_list);
|
||||
xorg_list_init(&xwl_screen->damage_window_list);
|
||||
xorg_list_init(&xwl_screen->window_list);
|
||||
xorg_list_init(&xwl_screen->drm_lease_devices);
|
||||
xorg_list_init(&xwl_screen->queued_drm_lease_devices);
|
||||
xorg_list_init(&xwl_screen->drm_leases);
|
||||
xorg_list_init(&xwl_screen->pending_wl_surface_destroy);
|
||||
xwl_screen->depth = 24;
|
||||
|
||||
if (!monitorResolution)
|
||||
|
@ -662,6 +764,10 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
|
||||
fbPictureInit(pScreen, 0, 0);
|
||||
|
||||
#ifdef MITSHM
|
||||
ShmRegisterFbFuncs(pScreen);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XSHMFENCE
|
||||
if (!miSyncShmScreenInit(pScreen))
|
||||
return FALSE;
|
||||
|
@ -736,6 +842,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
|||
return FALSE;
|
||||
|
||||
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
|
||||
AddCallback(&RootWindowFinalizeCallback, xwl_root_window_finalized_callback, pScreen);
|
||||
|
||||
xwl_screen_setup_custom_vector(xwl_screen);
|
||||
|
||||
xwl_screen_roundtrip(xwl_screen);
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "xwayland-types.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-drm-lease.h"
|
||||
|
||||
struct xwl_format {
|
||||
uint32_t format;
|
||||
|
@ -67,6 +68,9 @@ struct xwl_screen {
|
|||
ResizeWindowProcPtr ResizeWindow;
|
||||
MoveWindowProcPtr MoveWindow;
|
||||
|
||||
int (*GrabServer) (ClientPtr client);
|
||||
int (*UngrabServer) (ClientPtr client);
|
||||
|
||||
struct xorg_list output_list;
|
||||
struct xorg_list seat_list;
|
||||
struct xorg_list damage_window_list;
|
||||
|
@ -82,9 +86,15 @@ struct xwl_screen {
|
|||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
struct zwp_pointer_gestures_v1 *pointer_gestures;
|
||||
struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
|
||||
struct zwp_linux_dmabuf_v1 *dmabuf;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
struct xorg_list drm_lease_devices;
|
||||
struct xorg_list queued_drm_lease_devices;
|
||||
struct xorg_list drm_leases;
|
||||
struct xorg_list pending_wl_surface_destroy;
|
||||
uint32_t serial;
|
||||
|
||||
#define XWL_FORMAT_ARGB8888 (1 << 0)
|
||||
|
@ -106,6 +116,9 @@ struct xwl_screen {
|
|||
struct glamor_context *glamor_ctx;
|
||||
|
||||
Atom allow_commits_prop;
|
||||
|
||||
/* The preferred GLVND vendor. If NULL, "mesa" is assumed. */
|
||||
const char *glvnd_vendor;
|
||||
};
|
||||
|
||||
/* Apps which use randr/vidmode to change the mode when going fullscreen,
|
||||
|
|
|
@ -234,6 +234,15 @@ xwl_shm_create_pixmap(ScreenPtr screen,
|
|||
(width == 0 && height == 0) || depth < 15)
|
||||
return fbCreatePixmap(screen, width, height, depth, hint);
|
||||
|
||||
stride = PixmapBytePad(width, depth);
|
||||
size = stride * height;
|
||||
/* Size in the protocol is an integer, make sure we don't exceed
|
||||
* INT32_MAX or else the Wayland compositor will raise an error and
|
||||
* kill the Wayland connection!
|
||||
*/
|
||||
if (size > INT32_MAX)
|
||||
return NULL;
|
||||
|
||||
pixmap = fbCreatePixmap(screen, 0, 0, depth, hint);
|
||||
if (!pixmap)
|
||||
return NULL;
|
||||
|
@ -242,8 +251,6 @@ xwl_shm_create_pixmap(ScreenPtr screen,
|
|||
if (xwl_pixmap == NULL)
|
||||
goto err_destroy_pixmap;
|
||||
|
||||
stride = PixmapBytePad(width, depth);
|
||||
size = stride * height;
|
||||
xwl_pixmap->buffer = NULL;
|
||||
xwl_pixmap->size = size;
|
||||
fd = os_create_anonymous_file(size);
|
||||
|
|
|
@ -30,5 +30,6 @@ struct xwl_pixmap;
|
|||
struct xwl_window;
|
||||
struct xwl_screen;
|
||||
struct xwl_egl_backend;
|
||||
struct xwl_drm_lease;
|
||||
|
||||
#endif /* XWAYLAND_TYPES_H */
|
||||
|
|
|
@ -46,8 +46,11 @@
|
|||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
|
||||
#define DELAYED_WL_SURFACE_DESTROY 1000 /* ms */
|
||||
|
||||
static DevPrivateKeyRec xwl_window_private_key;
|
||||
static DevPrivateKeyRec xwl_damage_private_key;
|
||||
static const char *xwl_surface_tag = "xwl-surface";
|
||||
|
||||
static void
|
||||
xwl_window_set_allow_commits(struct xwl_window *xwl_window, Bool allow,
|
||||
|
@ -112,6 +115,24 @@ xwl_window_from_window(WindowPtr window)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_window_set_xwayland_tag(struct xwl_window *xwl_window)
|
||||
{
|
||||
wl_proxy_set_tag((struct wl_proxy *)xwl_window->surface, &xwl_surface_tag);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_window_clear_xwayland_tag(struct xwl_window *xwl_window)
|
||||
{
|
||||
wl_proxy_set_tag((struct wl_proxy *)xwl_window->surface, NULL);
|
||||
}
|
||||
|
||||
Bool
|
||||
is_surface_from_xwl_window(struct wl_surface *surface)
|
||||
{
|
||||
return wl_proxy_get_tag((struct wl_proxy *) surface) == &xwl_surface_tag;
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_update_property(struct xwl_window *xwl_window,
|
||||
PropertyStateRec *propstate)
|
||||
|
@ -480,6 +501,7 @@ ensure_surface_for_window(WindowPtr window)
|
|||
send_surface_id_event(xwl_window);
|
||||
|
||||
wl_surface_set_user_data(xwl_window->surface, xwl_window);
|
||||
xwl_window_set_xwayland_tag(xwl_window);
|
||||
|
||||
compRedirectWindow(serverClient, window, CompositeRedirectManual);
|
||||
|
||||
|
@ -522,6 +544,7 @@ Bool
|
|||
xwl_realize_window(WindowPtr window)
|
||||
{
|
||||
ScreenPtr screen = window->drawable.pScreen;
|
||||
CompScreenPtr comp_screen = GetCompScreen(screen);
|
||||
struct xwl_screen *xwl_screen;
|
||||
Bool ret;
|
||||
|
||||
|
@ -535,12 +558,20 @@ xwl_realize_window(WindowPtr window)
|
|||
if (!ret)
|
||||
return FALSE;
|
||||
|
||||
if (xwl_screen->rootless && !window->parent) {
|
||||
BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
|
||||
if (xwl_screen->rootless) {
|
||||
/* We do not want the COW to be mapped when rootless in Xwayland */
|
||||
if (window == comp_screen->pOverlayWin) {
|
||||
window->mapped = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
RegionReset(&window->winSize, &box);
|
||||
RegionNull(&window->clipList);
|
||||
RegionNull(&window->borderClip);
|
||||
if (!window->parent) {
|
||||
BoxRec box = { 0, 0, xwl_screen->width, xwl_screen->height };
|
||||
|
||||
RegionReset(&window->winSize, &box);
|
||||
RegionNull(&window->clipList);
|
||||
RegionNull(&window->borderClip);
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_screen->rootless ?
|
||||
|
@ -554,6 +585,62 @@ xwl_realize_window(WindowPtr window)
|
|||
return ensure_surface_for_window(window);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_surface_destroy_free_timer(struct xwl_wl_surface *xwl_wl_surface)
|
||||
{
|
||||
if (xwl_wl_surface->wl_surface_destroy_timer) {
|
||||
TimerFree(xwl_wl_surface->wl_surface_destroy_timer);
|
||||
xwl_wl_surface->wl_surface_destroy_timer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface)
|
||||
{
|
||||
wl_surface_destroy(xwl_wl_surface->wl_surface);
|
||||
xorg_list_del(&xwl_wl_surface->link);
|
||||
xwl_surface_destroy_free_timer(xwl_wl_surface);
|
||||
free(xwl_wl_surface);
|
||||
}
|
||||
|
||||
static CARD32
|
||||
xwl_surface_destroy_callback(OsTimerPtr timer, CARD32 now, void *arg)
|
||||
{
|
||||
struct xwl_wl_surface *xwl_wl_surface = arg;
|
||||
|
||||
xwl_window_surface_do_destroy(xwl_wl_surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
release_wl_surface_for_window(struct xwl_window *xwl_window)
|
||||
{
|
||||
struct xwl_wl_surface *xwl_wl_surface;
|
||||
|
||||
/* If the Xserver is terminating, destroy the surface immediately */
|
||||
if ((dispatchException & DE_TERMINATE) == DE_TERMINATE) {
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Break the wl_surface / xwl_window relationship */
|
||||
wl_surface_set_user_data(xwl_window->surface, NULL);
|
||||
xwl_window_clear_xwayland_tag(xwl_window);
|
||||
|
||||
/* Schedule the destruction later, to mitigate the race between X11
|
||||
* and Wayland processing so that the compositor has the time to
|
||||
* establish the association before the wl_surface is destroyed.
|
||||
*/
|
||||
xwl_wl_surface = xnfcalloc(1, sizeof *xwl_wl_surface);
|
||||
xwl_wl_surface->wl_surface = xwl_window->surface;
|
||||
xorg_list_add(&xwl_wl_surface->link,
|
||||
&xwl_window->xwl_screen->pending_wl_surface_destroy);
|
||||
xwl_wl_surface->wl_surface_destroy_timer =
|
||||
TimerSet(NULL, 0, DELAYED_WL_SURFACE_DESTROY,
|
||||
xwl_surface_destroy_callback, xwl_wl_surface);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_unrealize_window(WindowPtr window)
|
||||
{
|
||||
|
@ -596,16 +683,6 @@ xwl_unrealize_window(WindowPtr window)
|
|||
if (xwl_window_has_viewport_enabled(xwl_window))
|
||||
xwl_window_disable_viewport(xwl_window);
|
||||
|
||||
wl_surface_destroy(xwl_window->surface);
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
xorg_list_del(&xwl_window->link_window);
|
||||
unregister_damage(window);
|
||||
|
||||
xwl_window_buffers_dispose(xwl_window);
|
||||
|
||||
if (xwl_window->frame_callback)
|
||||
wl_callback_destroy(xwl_window->frame_callback);
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_screen->present) {
|
||||
struct xwl_present_window *xwl_present_window, *tmp;
|
||||
|
@ -618,6 +695,16 @@ xwl_unrealize_window(WindowPtr window)
|
|||
}
|
||||
#endif
|
||||
|
||||
release_wl_surface_for_window(xwl_window);
|
||||
xorg_list_del(&xwl_window->link_damage);
|
||||
xorg_list_del(&xwl_window->link_window);
|
||||
unregister_damage(window);
|
||||
|
||||
xwl_window_buffers_dispose(xwl_window);
|
||||
|
||||
if (xwl_window->frame_callback)
|
||||
wl_callback_destroy(xwl_window->frame_callback);
|
||||
|
||||
free(xwl_window);
|
||||
dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL);
|
||||
|
||||
|
@ -756,6 +843,18 @@ xwl_window_create_frame_callback(struct xwl_window *xwl_window)
|
|||
xwl_window->frame_callback = wl_surface_frame(xwl_window->surface);
|
||||
wl_callback_add_listener(xwl_window->frame_callback, &frame_listener,
|
||||
xwl_window);
|
||||
|
||||
#ifdef GLAMOR_HAS_GBM
|
||||
if (xwl_window->xwl_screen->present) {
|
||||
struct xwl_present_window *xwl_present_window, *tmp;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_present_window, tmp,
|
||||
&xwl_window->frame_callback_list,
|
||||
frame_callback_list) {
|
||||
xwl_present_reset_timer(xwl_present_window);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Bool
|
||||
|
@ -805,9 +904,18 @@ xwl_window_post_damage(struct xwl_window *xwl_window)
|
|||
#endif
|
||||
buffer = xwl_shm_pixmap_get_wl_buffer(pixmap);
|
||||
|
||||
if (!buffer) {
|
||||
ErrorF("Error getting buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor)
|
||||
xwl_glamor_post_damage(xwl_window, pixmap, region);
|
||||
if (xwl_screen->glamor) {
|
||||
if (!xwl_glamor_post_damage(xwl_window, pixmap, region)) {
|
||||
ErrorF("glamor: Failed to post damage\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wl_surface_attach(xwl_window->surface, buffer, 0, 0);
|
||||
|
|
|
@ -37,6 +37,12 @@
|
|||
|
||||
#include "xwayland-types.h"
|
||||
|
||||
struct xwl_wl_surface {
|
||||
OsTimerPtr wl_surface_destroy_timer;
|
||||
struct wl_surface *wl_surface;
|
||||
struct xorg_list link;
|
||||
};
|
||||
|
||||
struct xwl_window {
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct wl_surface *surface;
|
||||
|
@ -60,6 +66,8 @@ struct xwl_window {
|
|||
struct xwl_window *xwl_window_get(WindowPtr window);
|
||||
struct xwl_window *xwl_window_from_window(WindowPtr window);
|
||||
|
||||
Bool is_surface_from_xwl_window(struct wl_surface *surface);
|
||||
|
||||
void xwl_window_update_property(struct xwl_window *xwl_window,
|
||||
PropertyStateRec *propstate);
|
||||
Bool xwl_window_has_viewport_enabled(struct xwl_window *xwl_window);
|
||||
|
@ -81,6 +89,8 @@ void xwl_move_window(WindowPtr window,
|
|||
Bool xwl_destroy_window(WindowPtr window);
|
||||
void xwl_window_post_damage(struct xwl_window *xwl_window);
|
||||
void xwl_window_create_frame_callback(struct xwl_window *xwl_window);
|
||||
void xwl_window_surface_do_destroy(struct xwl_wl_surface *xwl_wl_surface);
|
||||
|
||||
Bool xwl_window_init(void);
|
||||
|
||||
#endif /* XWAYLAND_WINDOW_H */
|
||||
|
|
|
@ -25,7 +25,12 @@
|
|||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#if !defined(SYSV) && !defined(WIN32)
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <selection.h>
|
||||
|
@ -34,6 +39,7 @@
|
|||
#include <compositeext.h>
|
||||
#include <compint.h>
|
||||
#include <glx_extinit.h>
|
||||
#include <opaque.h>
|
||||
#include <os.h>
|
||||
#include <xserver_poll.h>
|
||||
#include <propertyst.h>
|
||||
|
@ -95,6 +101,7 @@ ddxUseMsg(void)
|
|||
ErrorF("-shm use shared memory for passing buffers\n");
|
||||
ErrorF("-verbose [n] verbose startup messages\n");
|
||||
ErrorF("-version show the server version and exit\n");
|
||||
ErrorF("-noTouchPointerEmulation disable touch pointer emulation\n");
|
||||
}
|
||||
|
||||
static int init_fd = -1;
|
||||
|
@ -114,6 +121,33 @@ xwl_show_version(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
try_raising_nofile_limit(void)
|
||||
{
|
||||
#ifdef RLIMIT_NOFILE
|
||||
struct rlimit rlim;
|
||||
|
||||
/* Only fiddle with the limit if not set explicitly from the command line */
|
||||
if (limitNoFile >= 0)
|
||||
return;
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||
ErrorF("Failed to get the current nofile limit: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
rlim.rlim_cur = rlim.rlim_max;
|
||||
|
||||
if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) {
|
||||
ErrorF("Failed to set the current nofile limit: %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
LogMessageVerb(X_INFO, 3, "Raising the file descriptors limit to %li\n",
|
||||
rlim.rlim_max);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_add_listen_fd(int argc, char *argv[], int i)
|
||||
{
|
||||
|
@ -185,6 +219,10 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
|||
xwl_show_version();
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(argv[i], "-noTouchPointerEmulation") == 0) {
|
||||
touchEmulatePointer = FALSE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -263,14 +301,13 @@ InitOutput(ScreenInfo * screen_info, int argc, char **argv)
|
|||
screen_info->bitmapBitOrder = BITMAP_BIT_ORDER;
|
||||
screen_info->numPixmapFormats = ARRAY_SIZE(depths);
|
||||
|
||||
if (serverGeneration == 1)
|
||||
if (serverGeneration == 1) {
|
||||
try_raising_nofile_limit();
|
||||
LoadExtensionList(xwayland_extensions,
|
||||
ARRAY_SIZE(xwayland_extensions), FALSE);
|
||||
}
|
||||
|
||||
/* Cast away warning from missing printf annotation for
|
||||
* wl_log_func_t. Wayland 1.5 will have the annotation, so we can
|
||||
* remove the cast and require that when it's released. */
|
||||
wl_log_set_handler_client((void *) xwl_log_handler);
|
||||
wl_log_set_handler_client(xwl_log_handler);
|
||||
|
||||
if (AddScreen(xwl_screen_init, argc, argv) == -1) {
|
||||
FatalError("Couldn't add screen\n");
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
|
||||
Name: Xwayland
|
||||
Description: X Server for Wayland
|
||||
Version: @PACKAGE_VERSION@
|
||||
|
@ -7,3 +10,5 @@ have_eglstream=@have_eglstream@
|
|||
have_initfd=true
|
||||
have_listenfd=true
|
||||
have_verbose=true
|
||||
have_terminate_delay=true
|
||||
have_no_touch_pointer_emulation=true
|
||||
|
|
|
@ -1,491 +0,0 @@
|
|||
/* dix-config.h.in: not at all generated. -*- c -*- */
|
||||
|
||||
#ifndef _DIX_CONFIG_H_
|
||||
#define _DIX_CONFIG_H_
|
||||
|
||||
/* Support BigRequests extension */
|
||||
#undef BIGREQS
|
||||
|
||||
/* Builder address */
|
||||
#undef BUILDERADDR
|
||||
|
||||
/* Builder string */
|
||||
#undef BUILDERSTRING
|
||||
|
||||
/* Default font path */
|
||||
#undef COMPILEDDEFAULTFONTPATH
|
||||
|
||||
/* Miscellaneous server configuration files path */
|
||||
#undef SERVER_MISC_CONFIG_PATH
|
||||
|
||||
/* Support Composite Extension */
|
||||
#undef COMPOSITE
|
||||
|
||||
/* Support Damage extension */
|
||||
#undef DAMAGE
|
||||
|
||||
/* Use OsVendorVErrorF */
|
||||
#undef DDXOSVERRORF
|
||||
|
||||
/* Use ddxBeforeReset */
|
||||
#undef DDXBEFORERESET
|
||||
|
||||
/* Build DPMS extension */
|
||||
#undef DPMSExtension
|
||||
|
||||
/* Build DRI3 extension */
|
||||
#undef DRI3
|
||||
|
||||
/* Build GLX extension */
|
||||
#undef GLXEXT
|
||||
|
||||
/* Build GLX DRI loader */
|
||||
#undef GLX_DRI
|
||||
|
||||
/* Path to DRI drivers */
|
||||
#undef DRI_DRIVER_PATH
|
||||
|
||||
/* Support XDM-AUTH*-1 */
|
||||
#undef HASXDMAUTH
|
||||
|
||||
/* Support SHM */
|
||||
#undef HAS_SHM
|
||||
|
||||
/* Has backtrace support */
|
||||
#undef HAVE_BACKTRACE
|
||||
|
||||
/* Has libunwind support */
|
||||
#undef HAVE_LIBUNWIND
|
||||
|
||||
/* Define to 1 if you have the `cbrt' function. */
|
||||
#undef HAVE_CBRT
|
||||
|
||||
/* Define to 1 if you have the declaration of `program_invocation_short_name', and
|
||||
to 0 if you don't. */
|
||||
#undef HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
|
||||
|
||||
/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_DIRENT_H
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Have execinfo.h */
|
||||
#undef HAVE_EXECINFO_H
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the `getdtablesize' function. */
|
||||
#undef HAVE_GETDTABLESIZE
|
||||
|
||||
/* Define to 1 if you have the `getifaddrs' function. */
|
||||
#undef HAVE_GETIFADDRS
|
||||
|
||||
/* Define to 1 if you have the `getpeereid' function. */
|
||||
#undef HAVE_GETPEEREID
|
||||
|
||||
/* Define to 1 if you have the `getpeerucred' function. */
|
||||
#undef HAVE_GETPEERUCRED
|
||||
|
||||
/* Define to 1 if you have the `getprogname' function. */
|
||||
#undef HAVE_GETPROGNAME
|
||||
|
||||
/* Define to 1 if you have the `getzoneid' function. */
|
||||
#undef HAVE_GETZONEID
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `bsd' library (-lbsd). */
|
||||
#undef HAVE_LIBBSD
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define to 1 if you have the <linux/fb.h> header file. */
|
||||
#undef HAVE_LINUX_FB_H
|
||||
|
||||
/* Define to 1 if you have the `memfd_create' function. */
|
||||
#undef HAVE_MEMFD_CREATE
|
||||
|
||||
/* Define to 1 if you have the `mkostemp' function. */
|
||||
#undef HAVE_MKOSTEMP
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have the function pthread_setname_np(const char*) */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID
|
||||
|
||||
/* Define to 1 if you have the function pthread_setname_np(pthread_t, const char*) */
|
||||
#undef HAVE_PTHREAD_SETNAME_NP_WITH_TID
|
||||
|
||||
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
|
||||
#undef HAVE_NDIR_H
|
||||
|
||||
/* Define to 1 if you have the `reallocarray' function. */
|
||||
#undef HAVE_REALLOCARRAY
|
||||
|
||||
/* Define to 1 if you have the `arc4random_buf' function. */
|
||||
#undef HAVE_ARC4RANDOM_BUF
|
||||
|
||||
/* Define to use libc SHA1 functions */
|
||||
#undef HAVE_SHA1_IN_LIBC
|
||||
|
||||
/* Define to use CommonCrypto SHA1 functions */
|
||||
#undef HAVE_SHA1_IN_COMMONCRYPTO
|
||||
|
||||
/* Define to use CryptoAPI SHA1 functions */
|
||||
#undef HAVE_SHA1_IN_CRYPTOAPI
|
||||
|
||||
/* Define to use libmd SHA1 functions */
|
||||
#undef HAVE_SHA1_IN_LIBMD
|
||||
|
||||
/* Define to use libgcrypt SHA1 functions */
|
||||
#undef HAVE_SHA1_IN_LIBGCRYPT
|
||||
|
||||
/* Define to use libnettle SHA1 functions */
|
||||
#undef HAVE_SHA1_IN_LIBNETTLE
|
||||
|
||||
/* Define to use libsha1 for SHA1 */
|
||||
#undef HAVE_SHA1_IN_LIBSHA1
|
||||
|
||||
/* Define to 1 if you have the `shmctl64' function. */
|
||||
#undef HAVE_SHMCTL64
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the `strcasecmp' function. */
|
||||
#undef HAVE_STRCASECMP
|
||||
|
||||
/* Define to 1 if you have the `strcasestr' function. */
|
||||
#undef HAVE_STRCASESTR
|
||||
|
||||
/* Define to 1 if you have the `strncasecmp' function. */
|
||||
#undef HAVE_STRNCASECMP
|
||||
|
||||
/* Define to 1 if you have the `strlcat' function. */
|
||||
#undef HAVE_STRLCAT
|
||||
|
||||
/* Define to 1 if you have the `strlcpy' function. */
|
||||
#undef HAVE_STRLCPY
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the `strndup' function. */
|
||||
#undef HAVE_STRNDUP
|
||||
|
||||
/* Define to 1 if libsystemd-daemon is available */
|
||||
#undef HAVE_SYSTEMD_DAEMON
|
||||
|
||||
/* Define to 1 if SYSV IPC is available */
|
||||
#undef HAVE_SYSV_IPC
|
||||
|
||||
/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_SYS_DIR_H
|
||||
|
||||
/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'.
|
||||
*/
|
||||
#undef HAVE_SYS_NDIR_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
||||
#undef HAVE_SYS_UTSNAME_H
|
||||
|
||||
/* Define to 1 if you have the `timingsafe_memcmp' function. */
|
||||
#undef HAVE_TIMINGSAFE_MEMCMP
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
||||
#undef HAVE_FNMATCH_H
|
||||
|
||||
/* Have /dev/urandom */
|
||||
#undef HAVE_URANDOM
|
||||
|
||||
/* Define to 1 if you have the `vasprintf' function. */
|
||||
#undef HAVE_VASPRINTF
|
||||
|
||||
/* Support IPv6 for TCP connections */
|
||||
#undef IPv6
|
||||
|
||||
/* Support os-specific local connections */
|
||||
#undef LOCALCONN
|
||||
|
||||
/* Support MIT-SHM Extension */
|
||||
#undef MITSHM
|
||||
|
||||
/* Enable some debugging code */
|
||||
#undef DEBUG
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Internal define for Xinerama */
|
||||
#undef PANORAMIX
|
||||
|
||||
/* Support Present extension */
|
||||
#undef PRESENT
|
||||
|
||||
/* Overall prefix */
|
||||
#undef PROJECTROOT
|
||||
|
||||
/* Support RANDR extension */
|
||||
#undef RANDR
|
||||
|
||||
/* Support Record extension */
|
||||
#undef XRECORD
|
||||
|
||||
/* Support RENDER extension */
|
||||
#undef RENDER
|
||||
|
||||
/* Support X resource extension */
|
||||
#undef RES
|
||||
|
||||
/* Support client ID tracking in X resource extension */
|
||||
#undef CLIENTIDS
|
||||
|
||||
/* Support MIT-SCREEN-SAVER extension */
|
||||
#undef SCREENSAVER
|
||||
|
||||
/* Support Secure RPC ("SUN-DES-1") authentication for X11 clients */
|
||||
#undef SECURE_RPC
|
||||
|
||||
/* Support SHAPE extension */
|
||||
#undef SHAPE
|
||||
|
||||
/* Define to 1 on systems derived from System V Release 4 */
|
||||
#undef SVR4
|
||||
|
||||
/* sysconfdir */
|
||||
#undef SYSCONFDIR
|
||||
|
||||
/* Support TCP socket connections */
|
||||
#undef TCPCONN
|
||||
|
||||
/* Support UNIX socket connections */
|
||||
#undef UNIXCONN
|
||||
|
||||
/* Build X string registry */
|
||||
#undef XREGISTRY
|
||||
|
||||
/* Build X-ACE extension */
|
||||
#undef XACE
|
||||
|
||||
/* Build SELinux extension */
|
||||
#undef XSELINUX
|
||||
|
||||
/* Support XCMisc extension */
|
||||
#undef XCMISC
|
||||
|
||||
/* Build Security extension */
|
||||
#undef XCSECURITY
|
||||
|
||||
/* Support Xdmcp */
|
||||
#undef XDMCP
|
||||
|
||||
/* Build XFree86 BigFont extension */
|
||||
#undef XF86BIGFONT
|
||||
|
||||
/* Support XFree86 Video Mode extension */
|
||||
#undef XF86VIDMODE
|
||||
|
||||
/* Support XFixes extension */
|
||||
#undef XFIXES
|
||||
|
||||
/* Support Xinerama extension */
|
||||
#undef XINERAMA
|
||||
|
||||
/* Current Xorg version */
|
||||
#undef XORG_VERSION_CURRENT
|
||||
|
||||
/* Build Xv Extension */
|
||||
#undef XvExtension
|
||||
|
||||
/* Support XSync extension */
|
||||
#undef XSYNC
|
||||
|
||||
/* Support XTest extension */
|
||||
#undef XTEST
|
||||
|
||||
/* Support Xv extension */
|
||||
#undef XV
|
||||
|
||||
/* Support DRI extension */
|
||||
#undef XF86DRI
|
||||
|
||||
/* Build DRI2 extension */
|
||||
#undef DRI2
|
||||
|
||||
/* Build DBE support */
|
||||
#undef DBE
|
||||
|
||||
/* Vendor name */
|
||||
#undef XVENDORNAME
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Enable GNU and other extensions to the C environment for GLIBC */
|
||||
#undef _GNU_SOURCE
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
#undef pid_t
|
||||
|
||||
/* Build Rootless code */
|
||||
#undef ROOTLESS
|
||||
|
||||
/* Define to 1 if unsigned long is 64 bits. */
|
||||
#undef _XSERVER64
|
||||
|
||||
/* System is BSD-like */
|
||||
#undef CSRG_BASED
|
||||
|
||||
/* Define to 1 if `struct sockaddr_in' has a `sin_len' member */
|
||||
#undef BSD44SOCKETS
|
||||
|
||||
/* Support D-Bus */
|
||||
#undef HAVE_DBUS
|
||||
|
||||
/* Use libudev for input hotplug */
|
||||
#undef CONFIG_UDEV
|
||||
|
||||
/* Use libudev for kms enumeration */
|
||||
#undef CONFIG_UDEV_KMS
|
||||
|
||||
/* Use udev_monitor_filter_add_match_tag() */
|
||||
#undef HAVE_UDEV_MONITOR_FILTER_ADD_MATCH_TAG
|
||||
|
||||
/* Use udev_enumerate_add_match_tag() */
|
||||
#undef HAVE_UDEV_ENUMERATE_ADD_MATCH_TAG
|
||||
|
||||
/* Enable D-Bus core */
|
||||
#undef NEED_DBUS
|
||||
|
||||
/* Support HAL for hotplug */
|
||||
#undef CONFIG_HAL
|
||||
|
||||
/* Enable systemd-logind integration */
|
||||
#undef SYSTEMD_LOGIND 1
|
||||
|
||||
/* Have a monotonic clock from clock_gettime() */
|
||||
#undef MONOTONIC_CLOCK
|
||||
|
||||
/* Define to 1 if the DTrace Xserver provider probes should be built in */
|
||||
#undef XSERVER_DTRACE
|
||||
|
||||
/* Define to 1 if typeof works with your compiler. */
|
||||
#undef HAVE_TYPEOF
|
||||
|
||||
/* Define to __typeof__ if your compiler spells it that way. */
|
||||
#undef typeof
|
||||
|
||||
/* Correctly set _XSERVER64 for OSX fat binaries */
|
||||
#ifdef __APPLE__
|
||||
#include "dix-config-apple-verbatim.h"
|
||||
#endif
|
||||
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
/* Defined if needed to expose struct msghdr.msg_control */
|
||||
#undef _XOPEN_SOURCE
|
||||
|
||||
/* Have support for X shared memory fence library (xshmfence) */
|
||||
#undef HAVE_XSHMFENCE
|
||||
|
||||
/* Use XTrans FD passing support */
|
||||
#undef XTRANS_SEND_FDS
|
||||
|
||||
/* Wrap SIGBUS to catch MIT-SHM faults */
|
||||
#undef BUSFAULT
|
||||
|
||||
/* Don't let Xdefs.h define 'pointer' */
|
||||
#define _XTYPEDEF_POINTER 1
|
||||
|
||||
/* Don't let XIproto define 'Pointer' */
|
||||
#define _XITYPEDEF_POINTER 1
|
||||
|
||||
/* Ask fontsproto to make font path element names const */
|
||||
#define FONT_PATH_ELEMENT_NAME_CONST 1
|
||||
|
||||
/* Build GLAMOR */
|
||||
#undef GLAMOR
|
||||
|
||||
/* Build glamor's GBM-based EGL support */
|
||||
#undef GLAMOR_HAS_GBM
|
||||
|
||||
/* Build glamor/gbm has linear support */
|
||||
#undef GLAMOR_HAS_GBM_LINEAR
|
||||
|
||||
/* GBM has modifiers support */
|
||||
#undef GBM_BO_WITH_MODIFIERS
|
||||
|
||||
/* Glamor can use eglQueryDmaBuf* functions */
|
||||
#undef GLAMOR_HAS_EGL_QUERY_DMABUF
|
||||
|
||||
/* Glamor can use EGL_MESA_query_driver functions */
|
||||
#undef GLAMOR_HAS_EGL_QUERY_DRIVER
|
||||
|
||||
/* byte order */
|
||||
#undef X_BYTE_ORDER
|
||||
|
||||
/* Listen on TCP socket */
|
||||
#undef LISTEN_TCP
|
||||
|
||||
/* Listen on Unix socket */
|
||||
#undef LISTEN_UNIX
|
||||
|
||||
/* Listen on local socket */
|
||||
#undef LISTEN_LOCAL
|
||||
|
||||
/* Define if no local socket credentials interface exists */
|
||||
#undef NO_LOCAL_CLIENT_CRED
|
||||
|
||||
/* Have setitimer support */
|
||||
#undef HAVE_SETITIMER
|
||||
|
||||
/* Have posix_fallocate() */
|
||||
#undef HAVE_POSIX_FALLOCATE
|
||||
|
||||
/* Use input thread */
|
||||
#undef INPUTTHREAD
|
||||
|
||||
/* Have poll() */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Have epoll_create1() */
|
||||
#undef HAVE_EPOLL_CREATE1
|
||||
|
||||
/* Have <sys/sysmacros.h> header */
|
||||
#undef HAVE_SYS_SYSMACROS_H
|
||||
|
||||
/* Have sigprocmask */
|
||||
#undef HAVE_SIGPROCMASK
|
||||
|
||||
/* Have isastream */
|
||||
#undef HAVE_ISASTREAM
|
||||
|
||||
#endif /* _DIX_CONFIG_H_ */
|
119
include/dix.h
119
include/dix.h
|
@ -61,60 +61,76 @@ SOFTWARE.
|
|||
#define LATER 1
|
||||
|
||||
#define NullClient ((ClientPtr) 0)
|
||||
#define REQUEST(type) \
|
||||
type *stuff = (type *)client->requestBuffer
|
||||
|
||||
#define REQUEST(type) \
|
||||
type * stuff = (type *)client->requestBuffer;
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
|
||||
|
||||
#define REQUEST_SIZE_MATCH(req)\
|
||||
if ((sizeof(req) >> 2) != client->req_len)\
|
||||
return(BadLength)
|
||||
#define REQUEST_SIZE_MATCH(req) \
|
||||
do { \
|
||||
if ((sizeof(req) >> 2) != client->req_len) \
|
||||
return(BadLength); \
|
||||
} while (0)
|
||||
|
||||
#define REQUEST_AT_LEAST_SIZE(req) \
|
||||
if ((sizeof(req) >> 2) > client->req_len )\
|
||||
return(BadLength)
|
||||
#define REQUEST_AT_LEAST_SIZE(req) \
|
||||
do { \
|
||||
if ((sizeof(req) >> 2) > client->req_len) \
|
||||
return(BadLength); \
|
||||
} while (0)
|
||||
|
||||
#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra) \
|
||||
if (((sizeof(req) + ((uint64_t) extra)) >> 2) > client->req_len ) \
|
||||
return(BadLength)
|
||||
#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra) \
|
||||
do { \
|
||||
if (((sizeof(req) + ((uint64_t) (extra))) >> 2) > client->req_len) \
|
||||
return(BadLength); \
|
||||
} while (0)
|
||||
|
||||
#define REQUEST_FIXED_SIZE(req, n)\
|
||||
if (((sizeof(req) >> 2) > client->req_len) || \
|
||||
(((n) >> 2) >= client->req_len) || \
|
||||
((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \
|
||||
return(BadLength)
|
||||
#define REQUEST_FIXED_SIZE(req, n) \
|
||||
do { \
|
||||
if ((((sizeof(req)) >> 2) > client->req_len) || \
|
||||
(((n) >> 2) >= client->req_len) || \
|
||||
((((uint64_t) sizeof(req) + (n) + 3) >> 2) != (uint64_t) client->req_len)) \
|
||||
return(BadLength); \
|
||||
} while (0)
|
||||
|
||||
#define LEGAL_NEW_RESOURCE(id,client)\
|
||||
if (!LegalNewID(id,client)) \
|
||||
{\
|
||||
client->errorValue = id;\
|
||||
return BadIDChoice;\
|
||||
}
|
||||
#define LEGAL_NEW_RESOURCE(id,client) \
|
||||
do { \
|
||||
if (!LegalNewID((id), (client))) { \
|
||||
(client)->errorValue = (id); \
|
||||
return BadIDChoice; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode)\
|
||||
{\
|
||||
int tmprc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode);\
|
||||
if (tmprc != Success)\
|
||||
return tmprc;\
|
||||
tmprc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess);\
|
||||
if (tmprc != Success)\
|
||||
return tmprc;\
|
||||
if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
|
||||
return BadMatch;\
|
||||
}\
|
||||
if (pGC->serialNumber != pDraw->serialNumber)\
|
||||
ValidateGC(pDraw, pGC);
|
||||
#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode) \
|
||||
do { \
|
||||
int tmprc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode); \
|
||||
if (tmprc != Success) \
|
||||
return tmprc; \
|
||||
tmprc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess); \
|
||||
if (tmprc != Success) \
|
||||
return tmprc; \
|
||||
if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen)) \
|
||||
return BadMatch; \
|
||||
if (pGC->serialNumber != pDraw->serialNumber) \
|
||||
ValidateGC(pDraw, pGC); \
|
||||
} while (0)
|
||||
|
||||
#define WriteReplyToClient(pClient, size, pReply) { \
|
||||
if ((pClient)->swapped) \
|
||||
(*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
|
||||
(pClient, (int)(size), pReply); \
|
||||
else WriteToClient(pClient, (int)(size), (pReply)); }
|
||||
#define WriteReplyToClient(pClient, size, pReply) \
|
||||
do { \
|
||||
if ((pClient)->swapped) \
|
||||
(*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
|
||||
(pClient, (int)(size), pReply); \
|
||||
else \
|
||||
WriteToClient(pClient, (int)(size), (pReply)); \
|
||||
} while (0)
|
||||
|
||||
#define WriteSwappedDataToClient(pClient, size, pbuf) \
|
||||
if ((pClient)->swapped) \
|
||||
(*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
|
||||
else WriteToClient(pClient, (int)(size), (pbuf));
|
||||
#define WriteSwappedDataToClient(pClient, size, pbuf) \
|
||||
do { \
|
||||
if ((pClient)->swapped) \
|
||||
(*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
|
||||
else \
|
||||
WriteToClient(pClient, (int)(size), (pbuf)); \
|
||||
} while (0)
|
||||
|
||||
typedef struct _TimeStamp *TimeStampPtr;
|
||||
|
||||
|
@ -130,6 +146,8 @@ extern _X_EXPORT ClientPtr clients[MAXCLIENTS];
|
|||
extern _X_EXPORT ClientPtr serverClient;
|
||||
extern _X_EXPORT int currentMaxClients;
|
||||
extern _X_EXPORT char dispatchExceptionAtReset;
|
||||
extern _X_EXPORT int terminateDelay;
|
||||
extern _X_EXPORT Bool touchEmulatePointer;
|
||||
|
||||
typedef int HWEventQueueType;
|
||||
typedef HWEventQueueType *HWEventQueuePtr;
|
||||
|
@ -421,6 +439,10 @@ DeliverTouchEvents(DeviceIntPtr /* dev */ ,
|
|||
InternalEvent * /* ev */ ,
|
||||
XID /* resource */ );
|
||||
|
||||
extern Bool
|
||||
DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi,
|
||||
InternalEvent *ev);
|
||||
|
||||
extern void
|
||||
InitializeSprite(DeviceIntPtr /* pDev */ ,
|
||||
WindowPtr /* pWin */ );
|
||||
|
@ -436,7 +458,7 @@ WindowHasNewCursor(WindowPtr /* pWin */ );
|
|||
|
||||
extern Bool
|
||||
CheckDeviceGrabs(DeviceIntPtr /* device */ ,
|
||||
DeviceEvent * /* event */ ,
|
||||
InternalEvent * /* event */ ,
|
||||
WindowPtr /* ancestor */ );
|
||||
|
||||
extern void
|
||||
|
@ -610,6 +632,13 @@ extern Bool
|
|||
IsPointerEvent(InternalEvent *event);
|
||||
extern Bool
|
||||
IsTouchEvent(InternalEvent *event);
|
||||
Bool
|
||||
IsGestureEvent(InternalEvent *event);
|
||||
Bool
|
||||
IsGestureBeginEvent(InternalEvent *event);
|
||||
Bool
|
||||
IsGestureEndEvent(InternalEvent *event);
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
IsMaster(DeviceIntPtr dev);
|
||||
extern _X_EXPORT Bool
|
||||
|
|
|
@ -61,4 +61,5 @@ extern _X_EXPORT Bool DeletePassiveGrabFromList(GrabPtr /* pMinuendGrab */ );
|
|||
|
||||
extern Bool GrabIsPointerGrab(GrabPtr grab);
|
||||
extern Bool GrabIsKeyboardGrab(GrabPtr grab);
|
||||
extern Bool GrabIsGestureGrab(GrabPtr grab);
|
||||
#endif /* DIXGRABS_H */
|
||||
|
|
|
@ -36,4 +36,7 @@ _X_INTERNAL int GetCoreType(enum EventType type);
|
|||
_X_INTERNAL int GetXIType(enum EventType type);
|
||||
_X_INTERNAL int GetXI2Type(enum EventType type);
|
||||
|
||||
_X_INTERNAL enum EventType GestureTypeToBegin(enum EventType type);
|
||||
_X_INTERNAL enum EventType GestureTypeToEnd(enum EventType type);
|
||||
|
||||
#endif /* _EVENTCONVERT_H_ */
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct _DeviceEvent DeviceEvent;
|
|||
typedef struct _DeviceChangedEvent DeviceChangedEvent;
|
||||
typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
|
||||
typedef struct _BarrierEvent BarrierEvent;
|
||||
typedef struct _GestureEvent GestureEvent;
|
||||
|
||||
#ifdef XFreeXDGA
|
||||
typedef struct _DGAEvent DGAEvent;
|
||||
|
|
|
@ -75,6 +75,12 @@ enum EventType {
|
|||
ET_XQuartz,
|
||||
ET_BarrierHit,
|
||||
ET_BarrierLeave,
|
||||
ET_GesturePinchBegin,
|
||||
ET_GesturePinchUpdate,
|
||||
ET_GesturePinchEnd,
|
||||
ET_GestureSwipeBegin,
|
||||
ET_GestureSwipeUpdate,
|
||||
ET_GestureSwipeEnd,
|
||||
ET_Internal = 0xFF /* First byte */
|
||||
};
|
||||
|
||||
|
@ -260,6 +266,38 @@ struct _BarrierEvent {
|
|||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct _GestureEvent {
|
||||
unsigned char header; /**< Always ET_Internal */
|
||||
enum EventType type; /**< One of ET_Gesture{Pinch,Swipe}{Begin,Update,End} */
|
||||
int length; /**< Length in bytes */
|
||||
Time time; /**< Time in ms */
|
||||
int deviceid; /**< Device to post this event for */
|
||||
int sourceid; /**< The physical source device */
|
||||
uint32_t num_touches; /**< The number of touches in this gesture */
|
||||
double root_x; /**< Pos relative to root window */
|
||||
double root_y; /**< Pos relative to root window */
|
||||
double delta_x;
|
||||
double delta_y;
|
||||
double delta_unaccel_x;
|
||||
double delta_unaccel_y;
|
||||
double scale; /**< Only on ET_GesturePinch{Begin,Update} */
|
||||
double delta_angle; /**< Only on ET_GesturePinch{Begin,Update} */
|
||||
struct {
|
||||
uint32_t base; /**< XKB base modifiers */
|
||||
uint32_t latched; /**< XKB latched modifiers */
|
||||
uint32_t locked; /**< XKB locked modifiers */
|
||||
uint32_t effective;/**< XKB effective modifiers */
|
||||
} mods;
|
||||
struct {
|
||||
uint8_t base; /**< XKB base group */
|
||||
uint8_t latched; /**< XKB latched group */
|
||||
uint8_t locked; /**< XKB locked group */
|
||||
uint8_t effective;/**< XKB effective group */
|
||||
} group;
|
||||
Window root; /**< Root window of the event */
|
||||
uint32_t flags; /**< Flags to be copied into the generated event */
|
||||
};
|
||||
|
||||
#ifdef XQUARTZ
|
||||
#define XQUARTZ_EVENT_MAXARGS 5
|
||||
struct _XQuartzEvent {
|
||||
|
@ -294,6 +332,7 @@ union _InternalEvent {
|
|||
#ifdef XQUARTZ
|
||||
XQuartzEvent xquartz_event;
|
||||
#endif
|
||||
GestureEvent gesture_event;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -192,11 +192,12 @@ extern int
|
|||
GrabMask * /* eventMask */ );
|
||||
|
||||
extern int
|
||||
GrabTouch(ClientPtr /* client */ ,
|
||||
DeviceIntPtr /* dev */ ,
|
||||
DeviceIntPtr /* mod_dev */ ,
|
||||
GrabParameters * /* param */ ,
|
||||
GrabMask * /* eventMask */ );
|
||||
GrabTouchOrGesture(ClientPtr /* client */ ,
|
||||
DeviceIntPtr /* dev */ ,
|
||||
DeviceIntPtr /* mod_dev */ ,
|
||||
int /* type */ ,
|
||||
GrabParameters * /* param */ ,
|
||||
GrabMask * /* eventMask */ );
|
||||
|
||||
extern int
|
||||
SelectForWindow(DeviceIntPtr /* dev */ ,
|
||||
|
|
|
@ -105,6 +105,9 @@ SOFTWARE.
|
|||
#define TOUCH_POINTER_EMULATED (1 << 5) /* touch event may be pointer emulated */
|
||||
#define TOUCH_END (1 << 6) /* really end this touch now */
|
||||
|
||||
/* GetGestureEvent flags */
|
||||
#define GESTURE_CANCELLED (1 << 0)
|
||||
|
||||
/*int constants for pointer acceleration schemes*/
|
||||
#define PtrAccelNoOp 0
|
||||
#define PtrAccelPredictable 1
|
||||
|
@ -150,7 +153,9 @@ typedef struct _ValuatorClassRec *ValuatorClassPtr;
|
|||
typedef struct _ClassesRec *ClassesPtr;
|
||||
typedef struct _SpriteRec *SpritePtr;
|
||||
typedef struct _TouchClassRec *TouchClassPtr;
|
||||
typedef struct _GestureClassRec *GestureClassPtr;
|
||||
typedef struct _TouchPointInfo *TouchPointInfoPtr;
|
||||
typedef struct _GestureInfo *GestureInfoPtr;
|
||||
typedef struct _DDXTouchPointInfo *DDXTouchPointInfoPtr;
|
||||
typedef union _GrabMask GrabMask;
|
||||
|
||||
|
@ -337,6 +342,9 @@ extern _X_EXPORT Bool InitTouchClassDeviceStruct(DeviceIntPtr /*device */ ,
|
|||
unsigned int /*mode */ ,
|
||||
unsigned int /*numAxes */ );
|
||||
|
||||
extern _X_EXPORT Bool InitGestureClassDeviceStruct(DeviceIntPtr device,
|
||||
unsigned int max_touches);
|
||||
|
||||
typedef void (*BellProcPtr) (int percent,
|
||||
DeviceIntPtr device,
|
||||
void *ctrl,
|
||||
|
@ -488,6 +496,33 @@ void QueueTouchEvents(DeviceIntPtr device,
|
|||
uint32_t ddx_touchid,
|
||||
int flags, const ValuatorMask *mask);
|
||||
|
||||
void InitGestureEvent(InternalEvent *ievent, DeviceIntPtr dev, CARD32 ms,
|
||||
int type, uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x, double delta_unaccel_y,
|
||||
double scale, double delta_angle);
|
||||
|
||||
int GetGestureEvents(InternalEvent *events, DeviceIntPtr dev,
|
||||
uint16_t type, uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x,
|
||||
double delta_unaccel_y,
|
||||
double scale, double delta_angle);
|
||||
|
||||
|
||||
void QueueGesturePinchEvents(DeviceIntPtr dev, uint16_t type,
|
||||
uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x,
|
||||
double delta_unaccel_y,
|
||||
double scale, double delta_angle);
|
||||
|
||||
void QueueGestureSwipeEvents(DeviceIntPtr dev, uint16_t type,
|
||||
uint16_t num_touches, uint32_t flags,
|
||||
double delta_x, double delta_y,
|
||||
double delta_unaccel_x,
|
||||
double delta_unaccel_y);
|
||||
|
||||
extern int GetTouchOwnershipEvents(InternalEvent *events,
|
||||
DeviceIntPtr pDev,
|
||||
TouchPointInfoPtr ti,
|
||||
|
@ -573,6 +608,12 @@ enum TouchListenerType {
|
|||
TOUCH_LISTENER_POINTER_REGULAR,
|
||||
};
|
||||
|
||||
enum GestureListenerType {
|
||||
GESTURE_LISTENER_GRAB,
|
||||
GESTURE_LISTENER_NONGESTURE_GRAB,
|
||||
GESTURE_LISTENER_REGULAR
|
||||
};
|
||||
|
||||
extern void TouchInitDDXTouchPoint(DeviceIntPtr dev,
|
||||
DDXTouchPointInfoPtr ddxtouch);
|
||||
extern DDXTouchPointInfoPtr TouchBeginDDXTouch(DeviceIntPtr dev,
|
||||
|
@ -618,7 +659,24 @@ extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev);
|
|||
extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource);
|
||||
extern void TouchAcceptAndEnd(DeviceIntPtr dev, int touchid);
|
||||
|
||||
extern Bool GestureInitGestureInfo(GestureInfoPtr gesture);
|
||||
extern GestureInfoPtr GestureBeginGesture(DeviceIntPtr dev, InternalEvent *ev);
|
||||
extern GestureInfoPtr GestureFindActiveByEventType(DeviceIntPtr dev, int type);
|
||||
extern void GestureEndGesture(GestureInfoPtr gi);
|
||||
extern Bool GestureResourceIsOwner(GestureInfoPtr gi, XID resource);
|
||||
extern void GestureAddListener(GestureInfoPtr gi, XID resource, int resource_type,
|
||||
enum GestureListenerType type,
|
||||
WindowPtr window, GrabPtr grab);
|
||||
extern void GestureSetupListener(DeviceIntPtr dev, GestureInfoPtr gi,
|
||||
InternalEvent *ev);
|
||||
extern Bool GestureBuildSprite(DeviceIntPtr sourcedev, GestureInfoPtr gi);
|
||||
extern void GestureListenerGone(XID resource);
|
||||
extern void GestureEndActiveGestures(DeviceIntPtr dev);
|
||||
extern void GestureEmitGestureEndToOwner(DeviceIntPtr dev, GestureInfoPtr gi);
|
||||
extern void ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev);
|
||||
|
||||
/* misc event helpers */
|
||||
extern void CopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event);
|
||||
extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients);
|
||||
extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event);
|
||||
extern Bool WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev);
|
||||
|
|
|
@ -75,7 +75,7 @@ extern _X_EXPORT int CountBits(const uint8_t * mask, int len);
|
|||
* events to the protocol, the server will not support these events until
|
||||
* this number here is bumped.
|
||||
*/
|
||||
#define XI2LASTEVENT XI_BarrierLeave
|
||||
#define XI2LASTEVENT XI_GestureSwipeEnd
|
||||
#define XI2MASKSIZE ((XI2LASTEVENT >> 3) + 1) /* no of bytes for masks */
|
||||
|
||||
/**
|
||||
|
@ -352,6 +352,32 @@ typedef struct _TouchClassRec {
|
|||
Mask motionMask;
|
||||
} TouchClassRec;
|
||||
|
||||
typedef struct _GestureListener {
|
||||
XID listener; /* grabs/event selection IDs receiving
|
||||
* events for this gesture */
|
||||
int resource_type; /* listener's resource type */
|
||||
enum GestureListenerType type;
|
||||
WindowPtr window;
|
||||
GrabPtr grab;
|
||||
} GestureListener;
|
||||
|
||||
typedef struct _GestureInfo {
|
||||
int sourceid; /* Source device's ID for this gesture */
|
||||
Bool active; /* whether or not the gesture is active */
|
||||
uint8_t type; /* Gesture type: either ET_GesturePinchBegin or
|
||||
ET_GestureSwipeBegin. Valid if active == TRUE */
|
||||
int num_touches; /* The number of touches in the gesture */
|
||||
SpriteRec sprite; /* window trace for delivery */
|
||||
GestureListener listener; /* the listener that will receive events */
|
||||
Bool has_listener; /* true if listener has been setup already */
|
||||
} GestureInfoRec;
|
||||
|
||||
typedef struct _GestureClassRec {
|
||||
int sourceid;
|
||||
GestureInfoRec gesture;
|
||||
unsigned short max_touches; /* maximum number of touches, may be 0 */
|
||||
} GestureClassRec;
|
||||
|
||||
typedef struct _ButtonClassRec {
|
||||
int sourceid;
|
||||
CARD8 numButtons;
|
||||
|
@ -435,6 +461,7 @@ typedef struct _ClassesRec {
|
|||
KeyClassPtr key;
|
||||
ValuatorClassPtr valuator;
|
||||
TouchClassPtr touch;
|
||||
GestureClassPtr gesture;
|
||||
ButtonClassPtr button;
|
||||
FocusClassPtr focus;
|
||||
ProximityClassPtr proximity;
|
||||
|
@ -550,6 +577,7 @@ typedef struct _DeviceIntRec {
|
|||
KeyClassPtr key;
|
||||
ValuatorClassPtr valuator;
|
||||
TouchClassPtr touch;
|
||||
GestureClassPtr gesture;
|
||||
ButtonClassPtr button;
|
||||
FocusClassPtr focus;
|
||||
ProximityClassPtr proximity;
|
||||
|
|
|
@ -46,9 +46,11 @@ struct _ValuatorMask {
|
|||
extern void verify_internal_event(const InternalEvent *ev);
|
||||
extern void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
|
||||
enum DeviceEventSource event_source);
|
||||
extern void init_gesture_event(GestureEvent *event, DeviceIntPtr dev, Time ms);
|
||||
extern int event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd);
|
||||
extern void event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd,
|
||||
DeviceEvent *event);
|
||||
extern void event_set_state_gesture(DeviceIntPtr kbd, GestureEvent *event);
|
||||
extern Mask event_get_filter_from_type(DeviceIntPtr dev, int evtype);
|
||||
extern Mask event_get_filter_from_xi2type(int evtype);
|
||||
|
||||
|
|
|
@ -2,12 +2,8 @@ version_split = meson.project_version().split('.')
|
|||
major = version_split[0].to_int()
|
||||
minor = version_split[1].to_int()
|
||||
patch = version_split[2].to_int()
|
||||
if version_split.length() == 4
|
||||
subpatch = version_split[3].to_int()
|
||||
else
|
||||
subpatch = 0
|
||||
endif
|
||||
|
||||
# convert to the old-style 1.x.y version scheme used up to 1.20.x for backwards compatibility
|
||||
release = 1 * 10000000 + major * 100000 + minor * 1000 + patch
|
||||
|
||||
dri_dep = dependency('dri', required: build_glx)
|
||||
|
@ -18,8 +14,17 @@ conf_data.set('_DIX_CONFIG_H_', '1')
|
|||
conf_data.set('HAVE_TYPEOF', cc.compiles('''
|
||||
int foo(int bar) { typeof(bar) baz = 1; return baz; }
|
||||
''',
|
||||
name: 'typeof()'))
|
||||
name: 'typeof()') ? '1' : false)
|
||||
|
||||
# For feature macros we're using either false (boolean) or '1', which correspond to the macro being
|
||||
# not defined at all and defined to 1. This is to match autotools behavior and thus preserve
|
||||
# backwards compatibility with all the existing code that uses #ifdef to check if feature is
|
||||
# enabled. This ifdef would pass if the macro is defined to 0 which would silently break code
|
||||
# in various places.
|
||||
#
|
||||
# As a complication when we read the configuration from conf_data back we get either string or
|
||||
# bool. Meson does not like comparing things of different types so we always convert the returned
|
||||
# value to an integer using to_int().
|
||||
conf_data.set('MONOTONIC_CLOCK', cc.has_function('clock_gettime') and
|
||||
cc.compiles('''
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
@ -29,9 +34,9 @@ cc.compiles('''
|
|||
#error CLOCK_MONOTONIC not defined
|
||||
#endif
|
||||
''',
|
||||
name: 'CLOCK_MONOTONIC'))
|
||||
name: 'CLOCK_MONOTONIC') ? '1' : false)
|
||||
|
||||
conf_data.set('XSERVER_DTRACE', with_dtrace)
|
||||
conf_data.set('XSERVER_DTRACE', with_dtrace ? '1' : false)
|
||||
|
||||
if host_machine.endian() == 'little'
|
||||
conf_data.set('X_BYTE_ORDER', 'X_LITTLE_ENDIAN')
|
||||
|
@ -50,7 +55,7 @@ conf_data.set('_GNU_SOURCE', '1')
|
|||
# autoconf checks for /dev/xf86 here, but the test should be based on
|
||||
# the target, not the build system. Could we get rid of this and just
|
||||
# ifdef for openbsd?
|
||||
conf_data.set('HAS_APERTURE_DRV', host_machine.system() == 'openbsd')
|
||||
conf_data.set('HAS_APERTURE_DRV', host_machine.system() == 'openbsd' ? '1' : false)
|
||||
|
||||
if get_option('input_thread') == 'false'
|
||||
enable_input_thread = false
|
||||
|
@ -64,13 +69,14 @@ else
|
|||
enable_input_thread = false
|
||||
endif
|
||||
endif
|
||||
conf_data.set('HAVE_INPUTTHREAD', enable_input_thread)
|
||||
conf_data.set('INPUTTHREAD', enable_input_thread ? '1' : false)
|
||||
|
||||
if cc.compiles('''
|
||||
#define _GNU_SOURCE 1
|
||||
#include <pthread.h>
|
||||
void foo(int bar) { pthread_setname_np(pthread_self(), "example"); }
|
||||
''',
|
||||
args: '-Werror-implicit-function-declaration',
|
||||
name: 'pthread_setname_np(tid, name)')
|
||||
conf_data.set('HAVE_PTHREAD_SETNAME_NP_WITH_TID', 1)
|
||||
elif cc.compiles('''
|
||||
|
@ -78,80 +84,83 @@ elif cc.compiles('''
|
|||
#include <pthread.h>
|
||||
void foo(int bar) { pthread_setname_np("example"); }
|
||||
''',
|
||||
args: '-Werror-implicit-function-declaration',
|
||||
name: 'pthread_setname_np(name)')
|
||||
conf_data.set('HAVE_PTHREAD_SETNAME_NP_WITHOUT_TID', 1)
|
||||
endif
|
||||
|
||||
conf_data.set('HAVE_LIBBSD', libbsd_dep.found())
|
||||
conf_data.set('HAVE_XSHMFENCE', xshmfence_dep.found())
|
||||
conf_data.set('WITH_LIBDRM', libdrm_required)
|
||||
conf_data.set('HAVE_LIBBSD', libbsd_dep.found() ? '1' : false)
|
||||
conf_data.set('HAVE_XSHMFENCE', xshmfence_dep.found() ? '1' : false)
|
||||
conf_data.set('WITH_LIBDRM', libdrm_required ? '1' : false)
|
||||
conf_data.set('GLAMOR_HAS_EGL_QUERY_DMABUF',
|
||||
epoxy_dep.found() and epoxy_dep.version().version_compare('>= 1.4.4'))
|
||||
epoxy_dep.found() and epoxy_dep.version().version_compare('>= 1.4.4') ? '1' : false)
|
||||
conf_data.set('GLAMOR_HAS_EGL_QUERY_DRIVER',
|
||||
epoxy_dep.found() and epoxy_dep.version().version_compare('>= 1.5.4'))
|
||||
conf_data.set('GLXEXT', build_glx)
|
||||
conf_data.set('GLAMOR', build_glamor)
|
||||
conf_data.set('GLAMOR_HAS_GBM', gbm_dep.found())
|
||||
epoxy_dep.found() and epoxy_dep.version().version_compare('>= 1.5.4') ? '1' : false)
|
||||
conf_data.set('GLXEXT', build_glx ? '1' : false)
|
||||
conf_data.set('GLAMOR', build_glamor ? '1' : false)
|
||||
conf_data.set('GLAMOR_HAS_GBM', gbm_dep.found() ? '1' : false)
|
||||
conf_data.set('GLAMOR_HAS_GBM_LINEAR',
|
||||
build_glamor and gbm_dep.found() and gbm_dep.version().version_compare('>= 10.6'))
|
||||
build_glamor and gbm_dep.found() and gbm_dep.version().version_compare('>= 10.6') ? '1' : false)
|
||||
conf_data.set('GBM_BO_WITH_MODIFIERS',
|
||||
build_glamor and gbm_dep.found() and gbm_dep.version().version_compare('>= 17.1'))
|
||||
build_glamor and gbm_dep.found() and gbm_dep.version().version_compare('>= 17.1') ? '1' : false)
|
||||
conf_data.set('GBM_BO_FD_FOR_PLANE',
|
||||
build_glamor and gbm_dep.found() and gbm_dep.version().version_compare('>= 21.1') ? '1' : false)
|
||||
|
||||
conf_data.set_quoted('SERVER_MISC_CONFIG_PATH', serverconfigdir)
|
||||
conf_data.set_quoted('PROJECTROOT', get_option('prefix'))
|
||||
conf_data.set_quoted('SYSCONFDIR', join_paths(get_option('prefix'), get_option('sysconfdir')))
|
||||
conf_data.set_quoted('COMPILEDDEFAULTFONTPATH', default_font_path)
|
||||
|
||||
conf_data.set('HASXDMAUTH', has_xdm_auth)
|
||||
conf_data.set('SECURE_RPC', get_option('secure-rpc'))
|
||||
conf_data.set('HASXDMAUTH', has_xdm_auth ? '1' : false)
|
||||
conf_data.set('SECURE_RPC', get_option('secure-rpc') ? '1' : false)
|
||||
|
||||
conf_data.set('HAVE_DLFCN_H', cc.has_header('dlfcn.h'))
|
||||
conf_data.set('HAVE_EXECINFO_H', cc.has_header('execinfo.h'))
|
||||
conf_data.set('HAVE_FCNTL_H', cc.has_header('fcntl.h'))
|
||||
conf_data.set('HAVE_FNMATCH_H', cc.has_header('fnmatch.h'))
|
||||
conf_data.set('HAVE_STDLIB_H', cc.has_header('stdlib.h'))
|
||||
conf_data.set('HAVE_STRING_H', cc.has_header('string.h'))
|
||||
conf_data.set('HAVE_STRINGS_H', cc.has_header('strings.h'))
|
||||
conf_data.set('HAVE_SYS_UTSNAME_H', cc.has_header('sys/utsname.h'))
|
||||
conf_data.set('HAVE_SYS_SYSMACROS_H', cc.has_header('sys/sysmacros.h'))
|
||||
conf_data.set('HAVE_UNISTD_H', cc.has_header('unistd.h'))
|
||||
conf_data.set('HAVE_DLFCN_H', cc.has_header('dlfcn.h') ? '1' : false)
|
||||
conf_data.set('HAVE_EXECINFO_H', cc.has_header('execinfo.h') ? '1' : false)
|
||||
conf_data.set('HAVE_FCNTL_H', cc.has_header('fcntl.h') ? '1' : false)
|
||||
conf_data.set('HAVE_FNMATCH_H', cc.has_header('fnmatch.h') ? '1' : false)
|
||||
conf_data.set('HAVE_STDLIB_H', cc.has_header('stdlib.h') ? '1' : false)
|
||||
conf_data.set('HAVE_STRING_H', cc.has_header('string.h') ? '1' : false)
|
||||
conf_data.set('HAVE_STRINGS_H', cc.has_header('strings.h') ? '1' : false)
|
||||
conf_data.set('HAVE_SYS_UTSNAME_H', cc.has_header('sys/utsname.h') ? '1' : false)
|
||||
conf_data.set('HAVE_SYS_SYSMACROS_H', cc.has_header('sys/sysmacros.h') ? '1' : false)
|
||||
conf_data.set('HAVE_UNISTD_H', cc.has_header('unistd.h') ? '1' : false)
|
||||
|
||||
conf_data.set('HAVE_ARC4RANDOM_BUF', cc.has_function('arc4random_buf', dependencies: libbsd_dep))
|
||||
conf_data.set('HAVE_BACKTRACE', cc.has_function('backtrace'))
|
||||
conf_data.set('HAVE_CBRT', cc.has_function('cbrt'))
|
||||
conf_data.set('HAVE_EPOLL_CREATE1', cc.has_function('epoll_create1'))
|
||||
conf_data.set('HAVE_GETUID', cc.has_function('getuid'))
|
||||
conf_data.set('HAVE_GETEUID', cc.has_function('geteuid'))
|
||||
conf_data.set('HAVE_ISASTREAM', cc.has_function('isastream'))
|
||||
conf_data.set('HAVE_ISSETUGID', cc.has_function('issetugid'))
|
||||
conf_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs'))
|
||||
conf_data.set('HAVE_GETPEEREID', cc.has_function('getpeereid'))
|
||||
conf_data.set('HAVE_GETPEERUCRED', cc.has_function('getpeerucred'))
|
||||
conf_data.set('HAVE_GETPROGNAME', cc.has_function('getprogname'))
|
||||
conf_data.set('HAVE_GETZONEID', cc.has_function('getzoneid'))
|
||||
conf_data.set('HAVE_MEMFD_CREATE', cc.has_function('memfd_create'))
|
||||
conf_data.set('HAVE_MKOSTEMP', cc.has_function('mkostemp'))
|
||||
conf_data.set('HAVE_MMAP', cc.has_function('mmap'))
|
||||
conf_data.set('HAVE_POLL', cc.has_function('poll'))
|
||||
conf_data.set('HAVE_POLLSET_CREATE', cc.has_function('pollset_create'))
|
||||
conf_data.set('HAVE_POSIX_FALLOCATE', cc.has_function('posix_fallocate'))
|
||||
conf_data.set('HAVE_PORT_CREATE', cc.has_function('port_create'))
|
||||
conf_data.set('HAVE_REALLOCARRAY', cc.has_function('reallocarray', dependencies: libbsd_dep))
|
||||
conf_data.set('HAVE_SETEUID', cc.has_function('seteuid'))
|
||||
conf_data.set('HAVE_SETITIMER', cc.has_function('setitimer'))
|
||||
conf_data.set('HAVE_SHMCTL64', cc.has_function('shmctl64'))
|
||||
conf_data.set('HAVE_SIGACTION', cc.has_function('sigaction'))
|
||||
conf_data.set('HAVE_SIGPROCMASK', cc.has_function('sigprocmask'))
|
||||
conf_data.set('HAVE_STRCASECMP', cc.has_function('strcasecmp'))
|
||||
conf_data.set('HAVE_STRCASESTR', cc.has_function('strcasestr'))
|
||||
conf_data.set('HAVE_STRLCAT', cc.has_function('strlcat', dependencies: libbsd_dep))
|
||||
conf_data.set('HAVE_STRLCPY', cc.has_function('strlcpy', dependencies: libbsd_dep))
|
||||
conf_data.set('HAVE_STRNCASECMP', cc.has_function('strncasecmp'))
|
||||
conf_data.set('HAVE_STRNDUP', cc.has_function('strndup') and cc.has_header_symbol('string.h', 'strndup'))
|
||||
conf_data.set('HAVE_TIMINGSAFE_MEMCMP', cc.has_function('timingsafe_memcmp'))
|
||||
conf_data.set('HAVE_VASPRINTF', cc.has_function('vasprintf'))
|
||||
conf_data.set('HAVE_VSNPRINTF', cc.has_function('vsnprintf'))
|
||||
conf_data.set('HAVE_WALKCONTEXT', cc.has_function('walkcontext'))
|
||||
conf_data.set('HAVE_ARC4RANDOM_BUF', cc.has_function('arc4random_buf', dependencies: libbsd_dep) ? '1' : false)
|
||||
conf_data.set('HAVE_BACKTRACE', cc.has_function('backtrace') ? '1' : false)
|
||||
conf_data.set('HAVE_CBRT', cc.has_function('cbrt') ? '1' : false)
|
||||
conf_data.set('HAVE_EPOLL_CREATE1', cc.has_function('epoll_create1') ? '1' : false)
|
||||
conf_data.set('HAVE_GETUID', cc.has_function('getuid') ? '1' : false)
|
||||
conf_data.set('HAVE_GETEUID', cc.has_function('geteuid') ? '1' : false)
|
||||
conf_data.set('HAVE_ISASTREAM', cc.has_function('isastream') ? '1' : false)
|
||||
conf_data.set('HAVE_ISSETUGID', cc.has_function('issetugid') ? '1' : false)
|
||||
conf_data.set('HAVE_GETIFADDRS', cc.has_function('getifaddrs') ? '1' : false)
|
||||
conf_data.set('HAVE_GETPEEREID', cc.has_function('getpeereid') ? '1' : false)
|
||||
conf_data.set('HAVE_GETPEERUCRED', cc.has_function('getpeerucred') ? '1' : false)
|
||||
conf_data.set('HAVE_GETPROGNAME', cc.has_function('getprogname') ? '1' : false)
|
||||
conf_data.set('HAVE_GETZONEID', cc.has_function('getzoneid') ? '1' : false)
|
||||
conf_data.set('HAVE_MEMFD_CREATE', cc.has_function('memfd_create') ? '1' : false)
|
||||
conf_data.set('HAVE_MKOSTEMP', cc.has_function('mkostemp') ? '1' : false)
|
||||
conf_data.set('HAVE_MMAP', cc.has_function('mmap') ? '1' : false)
|
||||
conf_data.set('HAVE_POLL', cc.has_function('poll') ? '1' : false)
|
||||
conf_data.set('HAVE_POLLSET_CREATE', cc.has_function('pollset_create') ? '1' : false)
|
||||
conf_data.set('HAVE_POSIX_FALLOCATE', cc.has_function('posix_fallocate') ? '1' : false)
|
||||
conf_data.set('HAVE_PORT_CREATE', cc.has_function('port_create') ? '1' : false)
|
||||
conf_data.set('HAVE_REALLOCARRAY', cc.has_function('reallocarray', dependencies: libbsd_dep) ? '1' : false)
|
||||
conf_data.set('HAVE_SETEUID', cc.has_function('seteuid') ? '1' : false)
|
||||
conf_data.set('HAVE_SETITIMER', cc.has_function('setitimer') ? '1' : false)
|
||||
conf_data.set('HAVE_SHMCTL64', cc.has_function('shmctl64') ? '1' : false)
|
||||
conf_data.set('HAVE_SIGACTION', cc.has_function('sigaction') ? '1' : false)
|
||||
conf_data.set('HAVE_SIGPROCMASK', cc.has_function('sigprocmask') ? '1' : false)
|
||||
conf_data.set('HAVE_STRCASECMP', cc.has_function('strcasecmp') ? '1' : false)
|
||||
conf_data.set('HAVE_STRCASESTR', cc.has_function('strcasestr') ? '1' : false)
|
||||
conf_data.set('HAVE_STRLCAT', cc.has_function('strlcat', dependencies: libbsd_dep) ? '1' : false)
|
||||
conf_data.set('HAVE_STRLCPY', cc.has_function('strlcpy', dependencies: libbsd_dep) ? '1' : false)
|
||||
conf_data.set('HAVE_STRNCASECMP', cc.has_function('strncasecmp') ? '1' : false)
|
||||
conf_data.set('HAVE_STRNDUP', cc.has_function('strndup') and cc.has_header_symbol('string.h', 'strndup') ? '1' : false)
|
||||
conf_data.set('HAVE_TIMINGSAFE_MEMCMP', cc.has_function('timingsafe_memcmp') ? '1' : false)
|
||||
conf_data.set('HAVE_VASPRINTF', cc.has_function('vasprintf') ? '1' : false)
|
||||
conf_data.set('HAVE_VSNPRINTF', cc.has_function('vsnprintf') ? '1' : false)
|
||||
conf_data.set('HAVE_WALKCONTEXT', cc.has_function('walkcontext') ? '1' : false)
|
||||
|
||||
conf_data.set('BUSFAULT', conf_data.get('HAVE_SIGACTION'))
|
||||
|
||||
|
@ -167,55 +176,55 @@ if cc.has_header_symbol('sys/socket.h', 'SCM_RIGHTS')
|
|||
conf_data.set('XTRANS_SEND_FDS', '1')
|
||||
endif
|
||||
|
||||
if not conf_data.get('HAVE_GETPEEREID') and not conf_data.get('HAVE_GETPEERUCRED')
|
||||
if conf_data.get('HAVE_GETPEEREID').to_int() == 0 and conf_data.get('HAVE_GETPEERUCRED').to_int() == 0
|
||||
if not cc.has_header_symbol('sys/socket.h', 'SO_PEERCRED')
|
||||
conf_data.set('NO_LOCAL_CLIENT_CRED', 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
conf_data.set('TCPCONN', '1')
|
||||
conf_data.set('UNIXCONN', host_machine.system() != 'windows')
|
||||
conf_data.set('IPv6', build_ipv6)
|
||||
conf_data.set('UNIXCONN', host_machine.system() != 'windows' ? '1' : false)
|
||||
conf_data.set('IPv6', build_ipv6 ? '1' : false)
|
||||
|
||||
conf_data.set('BIGREQS', '1')
|
||||
conf_data.set('COMPOSITE', '1')
|
||||
conf_data.set('DAMAGE', '1')
|
||||
conf_data.set('DBE', '1')
|
||||
conf_data.set('DPMSExtension', build_dpms)
|
||||
conf_data.set('DRI3', build_dri3)
|
||||
conf_data.set('DPMSExtension', build_dpms ? '1' : false)
|
||||
conf_data.set('DRI3', build_dri3 ? '1' : false)
|
||||
if build_glx
|
||||
conf_data.set_quoted('DRI_DRIVER_PATH', dri_dep.get_pkgconfig_variable('dridriverdir'))
|
||||
endif
|
||||
conf_data.set('HAS_SHM', build_mitshm)
|
||||
conf_data.set('MITSHM', build_mitshm)
|
||||
conf_data.set('PANORAMIX', build_xinerama)
|
||||
conf_data.set('HAS_SHM', build_mitshm ? '1' : false)
|
||||
conf_data.set('MITSHM', build_mitshm ? '1' : false)
|
||||
conf_data.set('PANORAMIX', build_xinerama ? '1' : false)
|
||||
conf_data.set('PRESENT', '1')
|
||||
conf_data.set('RANDR', '1')
|
||||
conf_data.set('RES', build_res)
|
||||
conf_data.set('RES', build_res ? '1' : false)
|
||||
conf_data.set('RENDER', '1')
|
||||
conf_data.set('SCREENSAVER', build_screensaver)
|
||||
conf_data.set('SCREENSAVER', build_screensaver ? '1' : false)
|
||||
conf_data.set('SHAPE', '1')
|
||||
conf_data.set('XACE', build_xace)
|
||||
conf_data.set('XACE', build_xace ? '1' : false)
|
||||
conf_data.set('XCMISC', '1')
|
||||
conf_data.set('XCSECURITY', build_xsecurity)
|
||||
conf_data.set('XDMCP', xdmcp_dep.found())
|
||||
conf_data.set('XF86BIGFONT', build_xf86bigfont)
|
||||
conf_data.set('XCSECURITY', build_xsecurity ? '1' : false)
|
||||
conf_data.set('XDMCP', xdmcp_dep.found() ? '1' : false)
|
||||
conf_data.set('XF86BIGFONT', build_xf86bigfont ? '1' : false)
|
||||
conf_data.set('XF86VIDMODE', 1)
|
||||
conf_data.set('XFIXES', '1')
|
||||
conf_data.set('XINERAMA', build_xinerama)
|
||||
conf_data.set('XINERAMA', build_xinerama ? '1' : false)
|
||||
conf_data.set('XINPUT', '1')
|
||||
conf_data.set('XRECORD', '1')
|
||||
conf_data.set('XSELINUX', build_xselinux)
|
||||
conf_data.set('XSELINUX', build_xselinux ? '1' : false)
|
||||
conf_data.set('XSYNC', '1')
|
||||
conf_data.set('XTEST', '1')
|
||||
conf_data.set('XV', build_xv)
|
||||
conf_data.set('XvExtension', build_xv)
|
||||
conf_data.set('XV', build_xv ? '1' : false)
|
||||
conf_data.set('XvExtension', build_xv ? '1' : false)
|
||||
|
||||
conf_data.set('HAVE_SHA1_IN_' + sha1.to_upper(), '1', description: 'Use @0@ SHA1 functions'.format(sha1))
|
||||
conf_data.set('HAVE_LIBUNWIND', get_option('libunwind'))
|
||||
|
||||
enable_debugging = get_option('buildtype') == 'debug'
|
||||
conf_data.set('DEBUG', enable_debugging)
|
||||
conf_data.set('DEBUG', enable_debugging ? '1' : false)
|
||||
|
||||
conf_data.set_quoted('XVENDORNAME', get_option('vendor_name'))
|
||||
conf_data.set_quoted('XVENDORNAMESHORT', get_option('vendor_name_short'))
|
||||
|
@ -230,7 +239,7 @@ supports_syscons = false
|
|||
supports_wscons = false
|
||||
csrg_based = false
|
||||
|
||||
if host_machine.system() == 'freebsd' or host_machine.system() == 'dragonflybsd'
|
||||
if host_machine.system() == 'freebsd' or host_machine.system() == 'dragonfly'
|
||||
supports_pccons = true
|
||||
supports_pcvt = true
|
||||
supports_syscons = true
|
||||
|
@ -262,7 +271,7 @@ endif
|
|||
|
||||
conf_data.set_quoted('XKB_DFLT_RULES', get_option('xkb_default_rules'))
|
||||
conf_data.set_quoted('__XSERVERNAME__', 'Xorg')
|
||||
conf_data.set('CSRG_BASED', csrg_based)
|
||||
conf_data.set('CSRG_BASED', csrg_based ? '1' : false)
|
||||
|
||||
configure_file(output : 'dix-config.h',
|
||||
configuration : conf_data)
|
||||
|
@ -291,8 +300,8 @@ configure_file(output : 'xkb-config.h',
|
|||
configuration : xkb_data)
|
||||
|
||||
xwayland_data = configuration_data()
|
||||
xwayland_data.set('XWL_HAS_GLAMOR', build_glamor and (gbm_dep.found() or build_eglstream))
|
||||
xwayland_data.set('XWL_HAS_EGLSTREAM', build_eglstream)
|
||||
xwayland_data.set('XWL_HAS_GLAMOR', build_glamor and (gbm_dep.found() or build_eglstream) ? '1' : false)
|
||||
xwayland_data.set('XWL_HAS_EGLSTREAM', build_eglstream ? '1' : false)
|
||||
|
||||
configure_file(output : 'xwayland-config.h',
|
||||
input : 'xwayland-config.h.meson.in',
|
||||
|
|
|
@ -15,6 +15,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
#include <X11/Xdefs.h>
|
||||
#include <X11/Xosdefs.h>
|
||||
#include <X11/Xfuncproto.h>
|
||||
#include <assert.h>
|
||||
#include "misc.h"
|
||||
|
||||
/*****************************************************************
|
||||
|
|
|
@ -72,7 +72,7 @@ extern _X_EXPORT int dixChangeWindowProperty(ClientPtr pClient,
|
|||
int format,
|
||||
int mode,
|
||||
unsigned long len,
|
||||
void *value,
|
||||
const void *value,
|
||||
Bool sendevent);
|
||||
|
||||
extern _X_EXPORT int DeleteProperty(ClientPtr /*client */ ,
|
||||
|
|
|
@ -139,12 +139,12 @@
|
|||
#define SERVER_XF86VIDMODE_MINOR_VERSION 2
|
||||
|
||||
/* Fixes */
|
||||
#define SERVER_XFIXES_MAJOR_VERSION 5
|
||||
#define SERVER_XFIXES_MAJOR_VERSION 6
|
||||
#define SERVER_XFIXES_MINOR_VERSION 0
|
||||
|
||||
/* X Input */
|
||||
#define SERVER_XI_MAJOR_VERSION 2
|
||||
#define SERVER_XI_MINOR_VERSION 3
|
||||
#define SERVER_XI_MINOR_VERSION 4
|
||||
|
||||
/* XKB */
|
||||
#define SERVER_XKB_MAJOR_VERSION 1
|
||||
|
|
|
@ -33,6 +33,7 @@ int systemd_logind_take_fd(int major, int minor, const char *path, Bool *paus);
|
|||
void systemd_logind_release_fd(int major, int minor, int fd);
|
||||
int systemd_logind_controls_session(void);
|
||||
void systemd_logind_vtenter(void);
|
||||
void systemd_logind_drop_master(void);
|
||||
#else
|
||||
#define systemd_logind_init()
|
||||
#define systemd_logind_fini()
|
||||
|
@ -40,6 +41,7 @@ void systemd_logind_vtenter(void);
|
|||
#define systemd_logind_release_fd(major, minor, fd) close(fd)
|
||||
#define systemd_logind_controls_session() 0
|
||||
#define systemd_logind_vtenter()
|
||||
#define systemd_logind_drop_master()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
/* version-config.h.in: not generated */
|
||||
|
||||
#ifndef VERSION_CONFIG_H
|
||||
#define VERSION_CONFIG_H
|
||||
|
||||
/* Vendor man version */
|
||||
#undef VENDOR_MAN_VERSION
|
||||
|
||||
/* Vendor name */
|
||||
#undef VENDOR_NAME
|
||||
|
||||
/* Vendor release */
|
||||
#undef VENDOR_RELEASE
|
||||
|
||||
#endif /* VERSION_CONFIG_H */
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
/* xwayland-config.h.in: not at all generated. */
|
||||
#ifndef _XWAYLAND_CONFIG_H_
|
||||
#define _XWAYLAND_CONFIG_H_
|
||||
|
||||
#include <dix-config.h>
|
||||
|
||||
/* Build glamor support for Xwayland */
|
||||
#undef XWL_HAS_GLAMOR
|
||||
|
||||
/* Build eglstream support for Xwayland */
|
||||
#undef XWL_HAS_EGLSTREAM
|
||||
|
||||
#endif /* _XWAYLAND_CONFIG_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue