Compare commits
65 Commits
scaling-mr
...
xwayland-2
Author | SHA1 | Date |
---|---|---|
Michel Dänzer | 1dbb96ae48 | |
Michel Dänzer | b42c33b6ef | |
Michel Dänzer | 96829a7b19 | |
Michel Dänzer | bfd7e302fc | |
Olivier Fourdan | d9005a02e9 | |
Olivier Fourdan | 8c74023712 | |
Olivier Fourdan | 763f4fb278 | |
Erik Kurzinger | e754b473d1 | |
Olivier Fourdan | 831426afd1 | |
Olivier Fourdan | 2e1bb50644 | |
Olivier Fourdan | 8744ab1b41 | |
Erik Kurzinger | f4720f1c42 | |
Erik Kurzinger | b2963fccc1 | |
Olivier Fourdan | bdb4712da3 | |
Olivier Fourdan | 96febe8ba4 | |
Olivier Fourdan | 7d839b3ed3 | |
Olivier Fourdan | 8b8a9bf6c7 | |
Olivier Fourdan | 15e550cc9a | |
Olivier Fourdan | 01319a9006 | |
Olivier Fourdan | 77617490fc | |
Olivier Fourdan | b05b19df01 | |
Olivier Fourdan | 1cce4bfd68 | |
Olivier Fourdan | 526cb24826 | |
Olivier Fourdan | 72790f7446 | |
Olivier Fourdan | 46dc7e8ee3 | |
Olivier Fourdan | 673676e759 | |
Olivier Fourdan | 740f00d44f | |
Olivier Fourdan | 8499fc0671 | |
Erik Kurzinger | d60acf6f0b | |
Erik Kurzinger | 3d10978cb6 | |
Erik Kurzinger | f44b22b0c6 | |
Erik Kurzinger | 15d3756814 | |
Olivier Fourdan | 1f65893873 | |
Michel Dänzer | d4cc2e2db9 | |
Matthieu Herrb | 1e4bf85df1 | |
Michel Dänzer | 2a327e5860 | |
Michel Dänzer | aa06f8bdec | |
Olivier Fourdan | a8581795ed | |
Michel Dänzer | f20dc97947 | |
Olivier Fourdan | 15f8b78904 | |
Adam Jackson | efd546cd1e | |
Michel Dänzer | 280aac5a0e | |
Michel Dänzer | fdc61c5a3c | |
Olivier Fourdan | 22a3dedac3 | |
Olivier Fourdan | b16dbd878d | |
Olivier Fourdan | 4d2128fd1d | |
Olivier Fourdan | 49c479a7c3 | |
Olivier Fourdan | c3f86d2868 | |
Olivier Fourdan | 2e212551d6 | |
Olivier Fourdan | 7531d71663 | |
Olivier Fourdan | 0663a245ad | |
Michel Dänzer | 1e72c3ce84 | |
Michel Dänzer | 001f0c8938 | |
Michel Dänzer | 0408fcb329 | |
Michel Dänzer | 274d54d1c3 | |
Michel Dänzer | be7257c5d1 | |
Michel Dänzer | aa49cd5ab7 | |
Michel Dänzer | 23296633bb | |
Michel Dänzer | 9335ee7994 | |
Michel Dänzer | 4f4b8e00fc | |
Michel Dänzer | 8f480147f6 | |
Michel Dänzer | 69cc6a6caa | |
Michel Dänzer | 6cae4b397d | |
Michel Dänzer | f8a6a7b265 | |
Michel Dänzer | 9de9c31273 |
|
@ -29,7 +29,6 @@ pkg-config,\
|
|||
python3,\
|
||||
windowsdriproto,\
|
||||
xorgproto,\
|
||||
libdmx-devel,\
|
||||
libepoxy-devel,\
|
||||
libfontenc-devel,\
|
||||
libfreetype-devel,\
|
||||
|
@ -73,7 +72,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 -Ddmx=true -Dxephyr=true -Dxnest=true -Dxvfb=true -Dxwin=true -Dxorg=true -Dhal=false -Dudev=false -Dpciaccess=false -Dint10=false build"'
|
||||
- '%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 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"'
|
||||
|
|
|
@ -59,21 +59,10 @@ debian-buster:
|
|||
after_script:
|
||||
- ccache --show-stats
|
||||
|
||||
autotools:
|
||||
extends: .common-build-and-test
|
||||
script:
|
||||
- mkdir build/
|
||||
- cd build/
|
||||
- ../autogen.sh --prefix=/usr CFLAGS="-fno-common"
|
||||
- make -j${FDO_CI_CONCURRENT:-4} distcheck
|
||||
- PIGLIT_DIR=/root/piglit XTEST_DIR=/root/xts make -j${FDO_CI_CONCURRENT:-4} check
|
||||
- cd ..
|
||||
- .gitlab-ci/manpages-check
|
||||
|
||||
meson:
|
||||
extends: .common-build-and-test
|
||||
script:
|
||||
- meson -Dc_args="-fno-common" -Dprefix=/usr -Dxephyr=true -Dwerror=true $MESON_EXTRA_OPTIONS build/
|
||||
- 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
|
||||
|
|
27
.travis.yml
27
.travis.yml
|
@ -1,27 +0,0 @@
|
|||
language: c
|
||||
cache:
|
||||
ccache: true
|
||||
directories:
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
branches:
|
||||
except:
|
||||
- /appveyor.*/
|
||||
|
||||
os: osx
|
||||
osx_image: xcode9.2
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- env: TOOL=meson
|
||||
- env: TOOL=autotools
|
||||
|
||||
install:
|
||||
- brew update
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache meson
|
||||
|
||||
script:
|
||||
- ./test/scripts/build-travis-osx.sh $TOOL
|
||||
- ccache -s
|
||||
|
||||
before_cache:
|
||||
- brew cleanup
|
215
Makefile.am
215
Makefile.am
|
@ -1,215 +0,0 @@
|
|||
AUTOMAKE_OPTIONS=nostdinc
|
||||
|
||||
# Required for automake < 1.14
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
if COMPOSITE
|
||||
COMPOSITE_DIR=composite
|
||||
endif
|
||||
|
||||
if GLX
|
||||
GLX_DIR=glx
|
||||
endif
|
||||
|
||||
if DBE
|
||||
DBE_DIR=dbe
|
||||
endif
|
||||
|
||||
if RECORD
|
||||
RECORD_DIR=record
|
||||
endif
|
||||
|
||||
if DRI3
|
||||
DRI3_DIR=dri3
|
||||
endif
|
||||
|
||||
if PRESENT
|
||||
PRESENT_DIR=present
|
||||
endif
|
||||
|
||||
if PSEUDORAMIX
|
||||
PSEUDORAMIX_DIR=pseudoramiX
|
||||
endif
|
||||
|
||||
if GLAMOR
|
||||
GLAMOR_DIR=glamor
|
||||
endif
|
||||
|
||||
SUBDIRS = \
|
||||
doc \
|
||||
man \
|
||||
include \
|
||||
dix \
|
||||
fb \
|
||||
mi \
|
||||
Xext \
|
||||
miext \
|
||||
os \
|
||||
randr \
|
||||
render \
|
||||
Xi \
|
||||
xkb \
|
||||
$(PSEUDORAMIX_DIR) \
|
||||
$(DBE_DIR) \
|
||||
$(RECORD_DIR) \
|
||||
xfixes \
|
||||
damageext \
|
||||
$(COMPOSITE_DIR) \
|
||||
$(GLX_DIR) \
|
||||
$(PRESENT_DIR) \
|
||||
$(DRI3_DIR) \
|
||||
exa \
|
||||
$(GLAMOR_DIR) \
|
||||
config \
|
||||
hw \
|
||||
test
|
||||
|
||||
if XORG
|
||||
aclocaldir = $(datadir)/aclocal
|
||||
aclocal_DATA = xorg-server.m4
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = xorg-server.pc
|
||||
endif
|
||||
|
||||
EXTRA_DIST = xorg-server.pc.in xorg-server.m4 autogen.sh README.md
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS=\
|
||||
--with-xkb-path=$(XKB_BASE_DIRECTORY) \
|
||||
--with-xkb-bin-directory=$(XKB_BIN_DIRECTORY) \
|
||||
--with-xkb-output='$${datadir}/X11/xkb/compiled'
|
||||
|
||||
.PHONY: ChangeLog INSTALL
|
||||
|
||||
INSTALL:
|
||||
$(INSTALL_CMD)
|
||||
|
||||
ChangeLog:
|
||||
$(CHANGELOG_CMD)
|
||||
|
||||
dist-hook: ChangeLog INSTALL
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
doc \
|
||||
man \
|
||||
include \
|
||||
dix \
|
||||
fb \
|
||||
mi \
|
||||
Xext \
|
||||
miext \
|
||||
os \
|
||||
pseudoramiX \
|
||||
randr \
|
||||
render \
|
||||
Xi \
|
||||
xkb \
|
||||
dbe \
|
||||
record \
|
||||
xfixes \
|
||||
damageext \
|
||||
composite \
|
||||
glx \
|
||||
exa \
|
||||
glamor \
|
||||
config \
|
||||
dri3 \
|
||||
present \
|
||||
hw \
|
||||
test
|
||||
|
||||
# gross hack
|
||||
relink: all
|
||||
$(AM_V_at)$(MAKE) -C hw relink
|
||||
|
||||
install-headers: Makefile
|
||||
+find . -name Makefile | while read m; do \
|
||||
if grep -q install-sdkHEADERS $$m; then \
|
||||
(cd `dirname "$$m"` && make install-sdkHEADERS) \
|
||||
fi \
|
||||
done
|
||||
|
||||
distcheck-hook:
|
||||
cd $(srcdir) && \
|
||||
meson setup _distcheck_build && \
|
||||
meson configure _distcheck_build && \
|
||||
ninja -C _distcheck_build && \
|
||||
rm -rf _distcheck_build && \
|
||||
cd -
|
||||
|
||||
EXTRA_DIST += \
|
||||
meson_options.txt \
|
||||
include/xorg-config.h.meson.in \
|
||||
include/xwin-config.h.meson.in \
|
||||
hw/xfree86/loader/symbol-test.c \
|
||||
composite/meson.build \
|
||||
config/meson.build \
|
||||
damageext/meson.build \
|
||||
dbe/meson.build \
|
||||
dix/meson.build \
|
||||
dri3/meson.build \
|
||||
exa/meson.build \
|
||||
fb/meson.build \
|
||||
glamor/meson.build \
|
||||
glx/meson.build \
|
||||
hw/dmx/config/meson.build \
|
||||
hw/dmx/examples/meson.build \
|
||||
hw/dmx/glxProxy/meson.build \
|
||||
hw/dmx/input/meson.build \
|
||||
hw/dmx/meson.build \
|
||||
hw/kdrive/ephyr/meson.build \
|
||||
hw/kdrive/meson.build \
|
||||
hw/kdrive/src/meson.build \
|
||||
hw/meson.build \
|
||||
hw/vfb/meson.build \
|
||||
hw/xfree86/common/meson.build \
|
||||
hw/xfree86/ddc/meson.build \
|
||||
hw/xfree86/dixmods/meson.build \
|
||||
hw/xfree86/dri2/meson.build \
|
||||
hw/xfree86/dri/meson.build \
|
||||
hw/xfree86/drivers/modesetting/meson.build \
|
||||
hw/xfree86/exa/meson.build \
|
||||
hw/xfree86/fbdevhw/meson.build \
|
||||
hw/xfree86/glamor_egl/meson.build \
|
||||
hw/xfree86/i2c/meson.build \
|
||||
hw/xfree86/int10/meson.build \
|
||||
hw/xfree86/loader/meson.build \
|
||||
hw/xfree86/meson.build \
|
||||
hw/xfree86/modes/meson.build \
|
||||
hw/xfree86/os-support/meson.build \
|
||||
hw/xfree86/parser/meson.build \
|
||||
hw/xfree86/ramdac/meson.build \
|
||||
hw/xfree86/shadowfb/meson.build \
|
||||
hw/xfree86/vgahw/meson.build \
|
||||
hw/xfree86/x86emu/meson.build \
|
||||
hw/xfree86/xkb/meson.build \
|
||||
hw/xnest/meson.build \
|
||||
hw/xquartz/meson.build \
|
||||
hw/xwayland/meson.build \
|
||||
hw/xwin/dri/meson.build \
|
||||
hw/xwin/glx/meson.build \
|
||||
hw/xwin/meson.build \
|
||||
hw/xwin/winclipboard/meson.build \
|
||||
include/meson.build \
|
||||
meson.build \
|
||||
miext/damage/meson.build \
|
||||
miext/shadow/meson.build \
|
||||
miext/sync/meson.build \
|
||||
mi/meson.build \
|
||||
os/meson.build \
|
||||
present/meson.build \
|
||||
pseudoramiX/meson.build \
|
||||
randr/meson.build \
|
||||
record/meson.build \
|
||||
render/meson.build \
|
||||
test/bigreq/meson.build \
|
||||
test/bigreq/request-length.c \
|
||||
test/meson.build \
|
||||
test/sync/meson.build \
|
||||
test/sync/sync.c \
|
||||
Xext/meson.build \
|
||||
xfixes/meson.build \
|
||||
Xi/meson.build \
|
||||
xkb/meson.build
|
||||
|
||||
DISTCLEANFILES = buildDateTime.h
|
120
Xext/Makefile.am
120
Xext/Makefile.am
|
@ -1,120 +0,0 @@
|
|||
noinst_LTLIBRARIES = libXext.la libXvidmode.la libhashtable.la
|
||||
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
if XORG
|
||||
sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h shmint.h syncsdk.h
|
||||
endif
|
||||
|
||||
# Sources always included in libXextbuiltin.la, libXext.la
|
||||
BUILTIN_SRCS = \
|
||||
bigreq.c \
|
||||
geext.c \
|
||||
shape.c \
|
||||
sleepuntil.c \
|
||||
sleepuntil.h \
|
||||
sync.c \
|
||||
syncsdk.h \
|
||||
syncsrv.h \
|
||||
xcmisc.c \
|
||||
xtest.c
|
||||
BUILTIN_LIBS =
|
||||
|
||||
# Optional sources included if extension enabled by configure.ac rules
|
||||
|
||||
# MIT Shared Memory extension
|
||||
MITSHM_SRCS = shm.c shmint.h
|
||||
if MITSHM
|
||||
BUILTIN_SRCS += $(MITSHM_SRCS)
|
||||
endif
|
||||
|
||||
# XVideo extension
|
||||
XV_SRCS = xvmain.c xvdisp.c xvmc.c xvdix.h xvmcext.h xvdisp.h
|
||||
if XV
|
||||
BUILTIN_SRCS += $(XV_SRCS)
|
||||
endif
|
||||
|
||||
# XResource extension: lets clients get data about per-client resource usage
|
||||
RES_SRCS = xres.c
|
||||
if RES
|
||||
BUILTIN_SRCS += $(RES_SRCS)
|
||||
endif
|
||||
|
||||
# MIT ScreenSaver extension
|
||||
SCREENSAVER_SRCS = saver.c
|
||||
if SCREENSAVER
|
||||
BUILTIN_SRCS += $(SCREENSAVER_SRCS)
|
||||
endif
|
||||
|
||||
# Xinerama extension: making multiple video devices act as one virtual screen
|
||||
XINERAMA_SRCS = panoramiX.c panoramiX.h panoramiXh.h panoramiXsrv.h panoramiXprocs.c panoramiXSwap.c
|
||||
if XINERAMA
|
||||
BUILTIN_SRCS += $(XINERAMA_SRCS)
|
||||
if XORG
|
||||
sdk_HEADERS += panoramiXsrv.h panoramiX.h
|
||||
endif
|
||||
endif
|
||||
|
||||
# X-ACE extension: provides hooks for building security policy extensions
|
||||
# like XC-Security, X-SELinux & XTSol
|
||||
XACE_SRCS = xace.c xace.h xacestr.h
|
||||
if XACE
|
||||
BUILTIN_SRCS += $(XACE_SRCS)
|
||||
if XORG
|
||||
sdk_HEADERS += xace.h xacestr.h
|
||||
endif
|
||||
endif
|
||||
|
||||
# SELinux extension: provides SELinux policy support for X objects
|
||||
# requires X-ACE extension
|
||||
XSELINUX_SRCS = xselinux_ext.c xselinux_hooks.c xselinux_label.c xselinux.h xselinuxint.h
|
||||
if XSELINUX
|
||||
BUILTIN_SRCS += $(XSELINUX_SRCS)
|
||||
BUILTIN_LIBS += $(SELINUX_LIBS)
|
||||
endif
|
||||
|
||||
# Security extension: multi-level security to protect clients from each other
|
||||
XCSECURITY_SRCS = security.c securitysrv.h
|
||||
if XCSECURITY
|
||||
BUILTIN_SRCS += $(XCSECURITY_SRCS)
|
||||
endif
|
||||
|
||||
# XF86 Big Font extension
|
||||
BIGFONT_SRCS = xf86bigfont.c xf86bigfontsrv.h
|
||||
if XF86BIGFONT
|
||||
BUILTIN_SRCS += $(BIGFONT_SRCS)
|
||||
endif
|
||||
|
||||
# DPMS extension
|
||||
DPMS_SRCS = dpms.c dpmsproc.h
|
||||
if DPMSExtension
|
||||
BUILTIN_SRCS += $(DPMS_SRCS)
|
||||
endif
|
||||
|
||||
# Now take all of the above, mix well, bake for 10 minutes and get libXext*.la
|
||||
|
||||
libXext_la_SOURCES = $(BUILTIN_SRCS)
|
||||
libXext_la_LIBADD = $(BUILTIN_LIBS)
|
||||
if RES
|
||||
libXext_la_LIBADD += libhashtable.la
|
||||
endif
|
||||
|
||||
# XVidMode extension
|
||||
libXvidmode_la_SOURCES = vidmode.c
|
||||
|
||||
#Hashtable
|
||||
libhashtable_la_SOURCES = hashtable.c hashtable.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(MITSHM_SRCS) \
|
||||
$(XV_SRCS) \
|
||||
$(RES_SRCS) \
|
||||
$(SCREENSAVER_SRCS) \
|
||||
$(XACE_SRCS) \
|
||||
$(XCSECURITY_SRCS) \
|
||||
$(XSELINUX_SRCS) \
|
||||
$(XINERAMA_SRCS) \
|
||||
$(BIGFONT_SRCS) \
|
||||
$(DPMS_SRCS) \
|
||||
$(GE_SRCS)
|
||||
|
|
@ -73,5 +73,3 @@ libxserver_xext_vidmode = static_library('libxserver_xext_vidmode',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
install_data(hdrs_xext, install_dir: xorgsdkdir)
|
||||
|
|
111
Xi/Makefile.am
111
Xi/Makefile.am
|
@ -1,111 +0,0 @@
|
|||
noinst_LTLIBRARIES = libXi.la libXistubs.la
|
||||
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
libXi_la_SOURCES = \
|
||||
allowev.c \
|
||||
allowev.h \
|
||||
chgdctl.c \
|
||||
chgdctl.h \
|
||||
chgfctl.c \
|
||||
chgfctl.h \
|
||||
chgkbd.c \
|
||||
chgkbd.h \
|
||||
chgkmap.c \
|
||||
chgkmap.h \
|
||||
chgprop.c \
|
||||
chgprop.h \
|
||||
chgptr.c \
|
||||
chgptr.h \
|
||||
closedev.c \
|
||||
closedev.h \
|
||||
devbell.c \
|
||||
devbell.h \
|
||||
exevents.c \
|
||||
exglobals.h \
|
||||
extinit.c \
|
||||
getbmap.c \
|
||||
getbmap.h \
|
||||
getdctl.c \
|
||||
getdctl.h \
|
||||
getfctl.c \
|
||||
getfctl.h \
|
||||
getfocus.c \
|
||||
getfocus.h \
|
||||
getkmap.c \
|
||||
getkmap.h \
|
||||
getmmap.c \
|
||||
getmmap.h \
|
||||
getprop.c \
|
||||
getprop.h \
|
||||
getselev.c \
|
||||
getselev.h \
|
||||
getvers.c \
|
||||
getvers.h \
|
||||
grabdev.c \
|
||||
grabdev.h \
|
||||
grabdevb.c \
|
||||
grabdevb.h \
|
||||
grabdevk.c \
|
||||
grabdevk.h \
|
||||
gtmotion.c \
|
||||
gtmotion.h \
|
||||
listdev.c \
|
||||
listdev.h \
|
||||
opendev.c \
|
||||
opendev.h \
|
||||
queryst.c \
|
||||
queryst.h \
|
||||
selectev.c \
|
||||
selectev.h \
|
||||
sendexev.c \
|
||||
sendexev.h \
|
||||
setbmap.c \
|
||||
setbmap.h \
|
||||
setdval.c \
|
||||
setdval.h \
|
||||
setfocus.c \
|
||||
setfocus.h \
|
||||
setmmap.c \
|
||||
setmmap.h \
|
||||
setmode.c \
|
||||
setmode.h \
|
||||
ungrdev.c \
|
||||
ungrdev.h \
|
||||
ungrdevb.c \
|
||||
ungrdevb.h \
|
||||
ungrdevk.c \
|
||||
ungrdevk.h \
|
||||
xiallowev.c \
|
||||
xiallowev.h \
|
||||
xibarriers.c \
|
||||
xibarriers.h \
|
||||
xichangecursor.c \
|
||||
xichangecursor.h \
|
||||
xichangehierarchy.c \
|
||||
xichangehierarchy.h \
|
||||
xigetclientpointer.c \
|
||||
xigetclientpointer.h \
|
||||
xigrabdev.c \
|
||||
xigrabdev.h \
|
||||
xipassivegrab.h \
|
||||
xipassivegrab.c \
|
||||
xiproperty.c \
|
||||
xiproperty.h \
|
||||
xiquerydevice.c \
|
||||
xiquerydevice.h \
|
||||
xiquerypointer.c \
|
||||
xiquerypointer.h \
|
||||
xiqueryversion.c \
|
||||
xiqueryversion.h \
|
||||
xiselectev.c \
|
||||
xiselectev.h \
|
||||
xisetclientpointer.c \
|
||||
xisetclientpointer.h \
|
||||
xisetdevfocus.c \
|
||||
xisetdevfocus.h \
|
||||
xiwarppointer.c \
|
||||
xiwarppointer.h
|
||||
|
||||
libXistubs_la_SOURCES = \
|
||||
stubs.c
|
|
@ -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;
|
||||
|
|
17
autogen.sh
17
autogen.sh
|
@ -1,17 +0,0 @@
|
|||
#! /bin/sh
|
||||
|
||||
srcdir=`dirname "$0"`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
ORIGDIR=`pwd`
|
||||
cd "$srcdir"
|
||||
|
||||
autoreconf --force -v --install || exit 1
|
||||
cd "$ORIGDIR" || exit $?
|
||||
|
||||
git config --local --get format.subjectPrefix ||
|
||||
git config --local format.subjectPrefix "PATCH xserver"
|
||||
|
||||
if test -z "$NOCONFIGURE"; then
|
||||
exec "$srcdir"/configure "$@"
|
||||
fi
|
|
@ -1,15 +0,0 @@
|
|||
noinst_LTLIBRARIES = libcomposite.la
|
||||
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
if XORG
|
||||
sdk_HEADERS = compositeext.h
|
||||
endif
|
||||
|
||||
libcomposite_la_SOURCES = \
|
||||
compalloc.c \
|
||||
compext.c \
|
||||
compint.h \
|
||||
compinit.c \
|
||||
compoverlay.c \
|
||||
compwindow.c
|
|
@ -15,5 +15,3 @@ libxserver_composite = static_library('libxserver_composite',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
install_data(hdrs_composite, install_dir: xorgsdkdir)
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
# Collection of quirks and blacklist/whitelists for specific devices.
|
||||
|
||||
|
||||
# Accelerometer device, posts data through ABS_X/ABS_Y, making X unusable
|
||||
# http://bugs.freedesktop.org/show_bug.cgi?id=22442
|
||||
Section "InputClass"
|
||||
Identifier "ThinkPad HDAPS accelerometer blacklist"
|
||||
MatchProduct "ThinkPad HDAPS accelerometer data"
|
||||
Option "Ignore" "on"
|
||||
EndSection
|
||||
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=523914
|
||||
# Mouse does not move in PV Xen guest
|
||||
# Explicitly tell evdev to not ignore the absolute axes.
|
||||
Section "InputClass"
|
||||
Identifier "Xen Virtual Pointer axis blacklist"
|
||||
MatchProduct "Xen Virtual Pointer"
|
||||
Option "IgnoreAbsoluteAxes" "off"
|
||||
Option "IgnoreRelativeAxes" "off"
|
||||
EndSection
|
||||
|
||||
# https://bugs.freedesktop.org/show_bug.cgi?id=55867
|
||||
# Bug 55867 - Doesn't know how to tag XI_TRACKBALL
|
||||
Section "InputClass"
|
||||
Identifier "Tag trackballs as XI_TRACKBALL"
|
||||
MatchProduct "trackball"
|
||||
MatchDriver "evdev"
|
||||
Option "TypeName" "TRACKBALL"
|
||||
EndSection
|
||||
|
||||
# https://bugs.freedesktop.org/show_bug.cgi?id=62831
|
||||
# Bug 62831 - Mionix Naos 5000 mouse detected incorrectly
|
||||
Section "InputClass"
|
||||
Identifier "Tag Mionix Naos 5000 mouse XI_MOUSE"
|
||||
MatchProduct "La-VIEW Technology Naos 5000 Mouse"
|
||||
MatchDriver "evdev"
|
||||
Option "TypeName" "MOUSE"
|
||||
EndSection
|
|
@ -1,41 +0,0 @@
|
|||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
noinst_LTLIBRARIES = libconfig.la
|
||||
libconfig_la_SOURCES = config.c config-backends.h
|
||||
libconfig_la_LIBADD =
|
||||
|
||||
if NEED_DBUS
|
||||
AM_CFLAGS += $(DBUS_CFLAGS)
|
||||
libconfig_la_SOURCES += dbus-core.c
|
||||
libconfig_la_LIBADD += $(DBUS_LIBS)
|
||||
endif
|
||||
|
||||
if CONFIG_UDEV
|
||||
|
||||
AM_CFLAGS += $(UDEV_CFLAGS)
|
||||
libconfig_la_SOURCES += udev.c
|
||||
libconfig_la_LIBADD += $(UDEV_LIBS)
|
||||
|
||||
if XORG
|
||||
xorgconfddir = $(datadir)/X11/$(XF86CONFIGDIR)
|
||||
xorgconfd_DATA = 10-quirks.conf
|
||||
endif
|
||||
|
||||
else
|
||||
|
||||
if CONFIG_HAL
|
||||
AM_CFLAGS += $(HAL_CFLAGS)
|
||||
libconfig_la_SOURCES += hal.c
|
||||
libconfig_la_LIBADD += $(HAL_LIBS)
|
||||
|
||||
else
|
||||
|
||||
if CONFIG_WSCONS
|
||||
libconfig_la_SOURCES += wscons.c
|
||||
endif # CONFIG_WSCONS
|
||||
|
||||
endif # !CONFIG_HAL
|
||||
|
||||
endif # !CONFIG_UDEV
|
||||
|
||||
EXTRA_DIST = x11-input.fdi fdi2iclass.py 10-quirks.conf
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
#include "input.h"
|
||||
#include "list.h"
|
||||
|
||||
void remove_devices(const char *backend, const char *config_info);
|
||||
BOOL device_is_duplicate(const char *config_info);
|
||||
|
||||
#ifdef CONFIG_UDEV
|
||||
int config_udev_pre_init(void);
|
||||
int config_udev_init(void);
|
||||
void config_udev_fini(void);
|
||||
void config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback);
|
||||
#elif defined(CONFIG_HAL)
|
||||
int config_hal_init(void);
|
||||
void config_hal_fini(void);
|
||||
#elif defined(CONFIG_WSCONS)
|
||||
int config_wscons_init(void);
|
||||
void config_wscons_fini(void);
|
||||
#endif
|
151
config/config.c
151
config/config.c
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <unistd.h>
|
||||
#include "os.h"
|
||||
#include "inputstr.h"
|
||||
#include "hotplug.h"
|
||||
#include "config-backends.h"
|
||||
#include "systemd-logind.h"
|
||||
|
||||
void
|
||||
config_pre_init(void)
|
||||
{
|
||||
#ifdef CONFIG_UDEV
|
||||
if (!config_udev_pre_init())
|
||||
ErrorF("[config] failed to pre-init udev\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
config_init(void)
|
||||
{
|
||||
#ifdef CONFIG_UDEV
|
||||
if (!config_udev_init())
|
||||
ErrorF("[config] failed to initialise udev\n");
|
||||
#elif defined(CONFIG_HAL)
|
||||
if (!config_hal_init())
|
||||
ErrorF("[config] failed to initialise HAL\n");
|
||||
#elif defined(CONFIG_WSCONS)
|
||||
if (!config_wscons_init())
|
||||
ErrorF("[config] failed to initialise wscons\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
config_fini(void)
|
||||
{
|
||||
#if defined(CONFIG_UDEV)
|
||||
config_udev_fini();
|
||||
#elif defined(CONFIG_HAL)
|
||||
config_hal_fini();
|
||||
#elif defined(CONFIG_WSCONS)
|
||||
config_wscons_fini();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
config_odev_probe(config_odev_probe_proc_ptr probe_callback)
|
||||
{
|
||||
#if defined(CONFIG_UDEV_KMS)
|
||||
config_udev_odev_probe(probe_callback);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
remove_device(const char *backend, DeviceIntPtr dev)
|
||||
{
|
||||
/* this only gets called for devices that have already been added */
|
||||
LogMessage(X_INFO, "config/%s: removing device %s\n", backend, dev->name);
|
||||
|
||||
/* Call PIE here so we don't try to dereference a device that's
|
||||
* already been removed. */
|
||||
input_lock();
|
||||
ProcessInputEvents();
|
||||
DeleteInputDeviceRequest(dev);
|
||||
input_unlock();
|
||||
}
|
||||
|
||||
void
|
||||
remove_devices(const char *backend, const char *config_info)
|
||||
{
|
||||
DeviceIntPtr dev, next;
|
||||
|
||||
for (dev = inputInfo.devices; dev; dev = next) {
|
||||
next = dev->next;
|
||||
if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
|
||||
remove_device(backend, dev);
|
||||
}
|
||||
for (dev = inputInfo.off_devices; dev; dev = next) {
|
||||
next = dev->next;
|
||||
if (dev->config_info && strcmp(dev->config_info, config_info) == 0)
|
||||
remove_device(backend, dev);
|
||||
}
|
||||
|
||||
RemoveInputDeviceTraces(config_info);
|
||||
}
|
||||
|
||||
BOOL
|
||||
device_is_duplicate(const char *config_info)
|
||||
{
|
||||
DeviceIntPtr dev;
|
||||
|
||||
for (dev = inputInfo.devices; dev; dev = dev->next) {
|
||||
if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (dev = inputInfo.off_devices; dev; dev = dev->next) {
|
||||
if (dev->config_info && (strcmp(dev->config_info, config_info) == 0))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
struct OdevAttributes *
|
||||
config_odev_allocate_attributes(void)
|
||||
{
|
||||
struct OdevAttributes *attribs =
|
||||
xnfcalloc(1, sizeof (struct OdevAttributes));
|
||||
attribs->fd = -1;
|
||||
return attribs;
|
||||
}
|
||||
|
||||
void
|
||||
config_odev_free_attributes(struct OdevAttributes *attribs)
|
||||
{
|
||||
if (attribs->fd != -1)
|
||||
systemd_logind_release_fd(attribs->major, attribs->minor, attribs->fd);
|
||||
free(attribs->path);
|
||||
free(attribs->syspath);
|
||||
free(attribs->busid);
|
||||
free(attribs->driver);
|
||||
free(attribs);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
D-BUS Configuration API v2
|
||||
----------------------------
|
||||
|
||||
The X server will register the bus name org.x.config.displayN, and the
|
||||
object /org/x/config/N, where N is the display number.
|
||||
|
||||
Currently only hotplugging of input devices is supported.
|
||||
|
||||
org.x.config.input:
|
||||
org.x.config.input.version:
|
||||
Returns one unsigned int32, which is the API version.
|
||||
|
||||
org.x.config.input.add:
|
||||
Takes an argument of key/value option pairs in arrays, e.g.:
|
||||
[ss][ss][ss][ss]
|
||||
is the signature for four options. These options will be passed
|
||||
to the input driver as with any others.
|
||||
Option names beginning with _ are not allowed; they are reserved
|
||||
for internal use.
|
||||
|
||||
Returns a number of signed int32s. Positive integers are the
|
||||
device IDs of new devices; negative numbers are X error codes,
|
||||
as defined in X.h. BadMatch will be returned if the options
|
||||
given do not match any device. BadValue is returned for a malformed
|
||||
message. (Example: 8 is new device ID 8; -8 is BadMatch.)
|
||||
|
||||
Notably, BadAlloc is never returned: the server internally signals
|
||||
to D-BUS that the attempt failed for lack of memory.
|
||||
|
||||
org.x.config.input.remove:
|
||||
Takes one uint32 argument, which is the device ID to remove, i.e.:
|
||||
u
|
||||
is the signature.
|
||||
|
||||
Returns one signed int32 which represents an X status as defined in
|
||||
X.h. See org.x.config.input.add. Error codes are negative numbers.
|
||||
|
||||
org.x.config.input.listDevices:
|
||||
Lists the currently active devices. No argument.
|
||||
Return value is sequence of [<id> <name>] [<id> <name>] ..., i.e. [us].
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006-2007 Daniel Stone
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "dix.h"
|
||||
#include "os.h"
|
||||
#include "dbus-core.h"
|
||||
|
||||
/* How often to attempt reconnecting when we get booted off the bus. */
|
||||
#define RECONNECT_DELAY (10 * 1000) /* in ms */
|
||||
|
||||
struct dbus_core_info {
|
||||
int fd;
|
||||
DBusConnection *connection;
|
||||
OsTimerPtr timer;
|
||||
struct dbus_core_hook *hooks;
|
||||
};
|
||||
static struct dbus_core_info bus_info = { .fd = -1 };
|
||||
|
||||
static CARD32 reconnect_timer(OsTimerPtr timer, CARD32 time, void *arg);
|
||||
|
||||
static void
|
||||
socket_handler(int fd, int ready, void *data)
|
||||
{
|
||||
struct dbus_core_info *info = data;
|
||||
|
||||
if (info->connection) {
|
||||
do {
|
||||
dbus_connection_read_write_dispatch(info->connection, 0);
|
||||
} while (info->connection &&
|
||||
dbus_connection_get_is_connected(info->connection) &&
|
||||
dbus_connection_get_dispatch_status(info->connection) ==
|
||||
DBUS_DISPATCH_DATA_REMAINS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect (if we haven't already been forcefully disconnected), clean up
|
||||
* after ourselves, and call all registered disconnect hooks.
|
||||
*/
|
||||
static void
|
||||
teardown(void)
|
||||
{
|
||||
struct dbus_core_hook *hook;
|
||||
|
||||
if (bus_info.timer) {
|
||||
TimerFree(bus_info.timer);
|
||||
bus_info.timer = NULL;
|
||||
}
|
||||
|
||||
/* We should really have pre-disconnect hooks and run them here, for
|
||||
* completeness. But then it gets awkward, given that you can't
|
||||
* guarantee that they'll be called ... */
|
||||
if (bus_info.connection)
|
||||
dbus_connection_unref(bus_info.connection);
|
||||
|
||||
if (bus_info.fd != -1)
|
||||
RemoveNotifyFd(bus_info.fd);
|
||||
bus_info.fd = -1;
|
||||
bus_info.connection = NULL;
|
||||
|
||||
for (hook = bus_info.hooks; hook; hook = hook->next) {
|
||||
if (hook->disconnect)
|
||||
hook->disconnect(hook->data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a filter, which only handles the disconnected signal, which
|
||||
* doesn't go to the normal message handling function. This takes
|
||||
* precedence over the message handling function, so have have to be
|
||||
* careful to ignore anything we don't want to deal with here.
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
message_filter(DBusConnection * connection, DBusMessage * message, void *data)
|
||||
{
|
||||
/* If we get disconnected, then take everything down, and attempt to
|
||||
* reconnect immediately (assuming it's just a restart). The
|
||||
* connection isn't valid at this point, so throw it out immediately. */
|
||||
if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
|
||||
DebugF("[dbus-core] disconnected from bus\n");
|
||||
bus_info.connection = NULL;
|
||||
teardown();
|
||||
|
||||
if (bus_info.timer)
|
||||
TimerFree(bus_info.timer);
|
||||
bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to connect to the system bus, and set a filter to deal with
|
||||
* disconnection (see message_filter above).
|
||||
*
|
||||
* @return 1 on success, 0 on failure.
|
||||
*/
|
||||
static int
|
||||
connect_to_bus(void)
|
||||
{
|
||||
DBusError error;
|
||||
struct dbus_core_hook *hook;
|
||||
|
||||
dbus_error_init(&error);
|
||||
bus_info.connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
|
||||
if (!bus_info.connection || dbus_error_is_set(&error)) {
|
||||
LogMessage(X_ERROR, "dbus-core: error connecting to system bus: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
goto err_begin;
|
||||
}
|
||||
|
||||
/* Thankyou. Really, thankyou. */
|
||||
dbus_connection_set_exit_on_disconnect(bus_info.connection, FALSE);
|
||||
|
||||
if (!dbus_connection_get_unix_fd(bus_info.connection, &bus_info.fd)) {
|
||||
ErrorF("[dbus-core] couldn't get fd for system bus\n");
|
||||
goto err_unref;
|
||||
}
|
||||
|
||||
if (!dbus_connection_add_filter(bus_info.connection, message_filter,
|
||||
&bus_info, NULL)) {
|
||||
ErrorF("[dbus-core] couldn't add filter: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
goto err_fd;
|
||||
}
|
||||
|
||||
dbus_error_free(&error);
|
||||
SetNotifyFd(bus_info.fd, socket_handler, X_NOTIFY_READ, &bus_info);
|
||||
|
||||
for (hook = bus_info.hooks; hook; hook = hook->next) {
|
||||
if (hook->connect)
|
||||
hook->connect(bus_info.connection, hook->data);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
err_fd:
|
||||
bus_info.fd = -1;
|
||||
err_unref:
|
||||
dbus_connection_unref(bus_info.connection);
|
||||
bus_info.connection = NULL;
|
||||
err_begin:
|
||||
dbus_error_free(&error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CARD32
|
||||
reconnect_timer(OsTimerPtr timer, CARD32 time, void *arg)
|
||||
{
|
||||
if (connect_to_bus()) {
|
||||
TimerFree(bus_info.timer);
|
||||
bus_info.timer = NULL;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return RECONNECT_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dbus_core_add_hook(struct dbus_core_hook *hook)
|
||||
{
|
||||
struct dbus_core_hook **prev;
|
||||
|
||||
for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next);
|
||||
|
||||
hook->next = NULL;
|
||||
*prev = hook;
|
||||
|
||||
/* If we're already connected, call the connect hook. */
|
||||
if (bus_info.connection)
|
||||
hook->connect(bus_info.connection, hook->data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dbus_core_remove_hook(struct dbus_core_hook *hook)
|
||||
{
|
||||
struct dbus_core_hook **prev;
|
||||
|
||||
for (prev = &bus_info.hooks; *prev; prev = &(*prev)->next) {
|
||||
if (*prev == hook) {
|
||||
*prev = hook->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
dbus_core_init(void)
|
||||
{
|
||||
memset(&bus_info, 0, sizeof(bus_info));
|
||||
bus_info.fd = -1;
|
||||
bus_info.hooks = NULL;
|
||||
if (!connect_to_bus())
|
||||
bus_info.timer = TimerSet(NULL, 0, 1, reconnect_timer, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
dbus_core_fini(void)
|
||||
{
|
||||
teardown();
|
||||
}
|
|
@ -1,202 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
#
|
||||
# Convert xorg keys from hal FDIs files to xorg.conf InputClass sections.
|
||||
# Modified from Martin Pitt's original fdi2mpi.py script:
|
||||
# http://cgit.freedesktop.org/media-player-info/tree/tools/fdi2mpi.py
|
||||
#
|
||||
# (C) 2010 Dan Nicholson
|
||||
# (C) 2009 Canonical Ltd.
|
||||
# Author: Dan Nicholson <dbn.lists@gmail.com>
|
||||
# Author: Martin Pitt <martin.pitt@ubuntu.com>
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# fur- nished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FIT- NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
|
||||
# NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import sys, xml.dom.minidom
|
||||
|
||||
# dict converting <match> tags to Match* entries
|
||||
match_table = {
|
||||
'info.product': 'MatchProduct',
|
||||
'input.product': 'MatchProduct',
|
||||
'info.vendor': 'MatchVendor',
|
||||
'input.vendor': 'MatchVendor',
|
||||
'info.device': 'MatchDevicePath',
|
||||
'linux.device_file': 'MatchDevicePath',
|
||||
'/org/freedesktop/Hal/devices/computer:system.kernel.name': 'MatchOS',
|
||||
'@info.parent:pnp.id': 'MatchPnPID',
|
||||
}
|
||||
|
||||
# dict converting info.capabilities list to Match* entries
|
||||
cap_match_table = {
|
||||
'input.keys': 'MatchIsKeyboard',
|
||||
'input.keyboard': 'MatchIsKeyboard',
|
||||
'input.keypad': 'MatchIsKeyboard',
|
||||
'input.mouse': 'MatchIsPointer',
|
||||
'input.joystick': 'MatchIsJoystick',
|
||||
'input.tablet': 'MatchIsTablet',
|
||||
'input.touchpad': 'MatchIsTouchpad',
|
||||
'input.touchscreen': 'MatchIsTouchscreen',
|
||||
}
|
||||
|
||||
def device_glob(path):
|
||||
'''Convert a contains device path to a glob entry'''
|
||||
if path[0] != '/':
|
||||
path = '*' + path
|
||||
return path + '*'
|
||||
|
||||
def parse_match(node):
|
||||
'''Parse a <match> tag to a tuple with InputClass values'''
|
||||
match = None
|
||||
value = None
|
||||
booltype = False
|
||||
|
||||
# see what type of key we have
|
||||
if node.attributes.has_key('key'):
|
||||
key = node.attributes['key'].nodeValue
|
||||
if key in match_table:
|
||||
match = match_table[key]
|
||||
elif key == 'info.capabilities':
|
||||
booltype = True
|
||||
|
||||
# bail out now if it's unrecognized
|
||||
if not match and not booltype:
|
||||
return (match, value)
|
||||
|
||||
if node.attributes.has_key('string'):
|
||||
value = node.attributes['string'].nodeValue
|
||||
elif node.attributes.has_key('contains'):
|
||||
value = node.attributes['contains'].nodeValue
|
||||
if match == 'MatchDevicePath':
|
||||
value = device_glob(value)
|
||||
elif booltype and value in cap_match_table:
|
||||
match = cap_match_table[value]
|
||||
value = 'yes'
|
||||
elif node.attributes.has_key('string_outof'):
|
||||
value = node.attributes['string_outof'].nodeValue.replace(';','|')
|
||||
elif node.attributes.has_key('contains_outof'):
|
||||
all_values = node.attributes['contains_outof'].nodeValue.split(';')
|
||||
for v in all_values:
|
||||
if match == 'MatchDevicePath':
|
||||
v = device_glob(v)
|
||||
elif match == 'MatchPnPID' and len(v) < 7:
|
||||
v += '*'
|
||||
if value:
|
||||
value += '|' + v
|
||||
else:
|
||||
value = v
|
||||
|
||||
return (match, value)
|
||||
|
||||
def parse_options(node):
|
||||
'''Parse the x11_* options and return InputClass entries'''
|
||||
driver = ''
|
||||
ignore = False
|
||||
options = []
|
||||
for n in node.childNodes:
|
||||
if n.nodeType != xml.dom.minidom.Node.ELEMENT_NODE:
|
||||
continue
|
||||
|
||||
tag = n.tagName
|
||||
key = n.attributes['key'].nodeValue
|
||||
value = ''
|
||||
|
||||
if n.hasChildNodes():
|
||||
content_node = n.childNodes[0]
|
||||
assert content_node.nodeType == xml.dom.Node.TEXT_NODE
|
||||
value = content_node.nodeValue
|
||||
|
||||
if tag == 'match':
|
||||
continue
|
||||
assert tag in ('addset', 'merge', 'append', 'remove')
|
||||
|
||||
if tag == 'remove' and key == 'input.x11_driver':
|
||||
ignore = True
|
||||
elif key == 'input.x11_driver':
|
||||
driver = value
|
||||
elif key.startswith('input.x11_options.'):
|
||||
option = key.split('.', 2)[2]
|
||||
options.append((option, value))
|
||||
|
||||
return (driver, ignore, options)
|
||||
|
||||
def is_match_node(node):
|
||||
'''Check if a node is a <match> element'''
|
||||
return node.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and \
|
||||
node.tagName == 'match'
|
||||
|
||||
def parse_all_matches(node):
|
||||
'''Parse a x11 match tag and any parents that don't supply their
|
||||
own options'''
|
||||
matches = []
|
||||
|
||||
while True:
|
||||
(key, value) = parse_match(node)
|
||||
if key and value:
|
||||
matches.append((key, value))
|
||||
|
||||
# walk up to a parent match node
|
||||
node = node.parentNode
|
||||
if node == None or not is_match_node(node):
|
||||
break
|
||||
|
||||
# leave if there other options at this level
|
||||
children = set([n.tagName for n in node.childNodes
|
||||
if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE])
|
||||
if children & set(['addset', 'merge', 'append']):
|
||||
break
|
||||
|
||||
return matches
|
||||
|
||||
# stupid counter to give "unique" rule names
|
||||
num_sections = 1
|
||||
def print_section(matches, driver, ignore, options):
|
||||
'''Print a valid InputClass section to stdout'''
|
||||
global num_sections
|
||||
print 'Section "InputClass"'
|
||||
print '\tIdentifier "Converted Class %d"' % num_sections
|
||||
num_sections += 1
|
||||
for m, v in matches:
|
||||
print '\t%s "%s"' % (m, v)
|
||||
if driver:
|
||||
print '\tDriver "%s"' % driver
|
||||
if ignore:
|
||||
print '\tOption "Ignore" "yes"'
|
||||
for o, v in options:
|
||||
print '\tOption "%s" "%s"' % (o, v)
|
||||
print 'EndSection'
|
||||
|
||||
def parse_fdi(fdi):
|
||||
'''Parse x11 matches from fdi'''
|
||||
# find all <match> leaf nodes
|
||||
num = 0
|
||||
for match_node in fdi.getElementsByTagName('match'):
|
||||
children = set([n.tagName for n in match_node.childNodes
|
||||
if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE])
|
||||
|
||||
# see if there are any options at this level
|
||||
(driver, ignore, options) = parse_options(match_node)
|
||||
if not driver and not ignore and not options:
|
||||
continue
|
||||
|
||||
matches = parse_all_matches(match_node)
|
||||
if num > 0:
|
||||
print
|
||||
print_section(matches, driver, ignore, options)
|
||||
num += 1
|
||||
|
||||
for f in sys.argv[1:]:
|
||||
parse_fdi(xml.dom.minidom.parse(f))
|
675
config/hal.c
675
config/hal.c
|
@ -1,675 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2007 Daniel Stone
|
||||
* Copyright © 2007 Red Hat, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Daniel Stone <daniel@fooishbar.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <hal/libhal.h>
|
||||
#include <string.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "dbus-core.h"
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
#include "hotplug.h"
|
||||
#include "config-backends.h"
|
||||
#include "os.h"
|
||||
|
||||
#define LIBHAL_PROP_KEY "input.x11_options."
|
||||
#define LIBHAL_XKB_PROP_KEY "input.xkb."
|
||||
|
||||
struct config_hal_info {
|
||||
DBusConnection *system_bus;
|
||||
LibHalContext *hal_ctx;
|
||||
};
|
||||
|
||||
/* Used for special handling of xkb options. */
|
||||
struct xkb_options {
|
||||
char *layout;
|
||||
char *model;
|
||||
char *rules;
|
||||
char *variant;
|
||||
char *options;
|
||||
};
|
||||
|
||||
static void
|
||||
device_removed(LibHalContext * ctx, const char *udi)
|
||||
{
|
||||
char *value;
|
||||
|
||||
if (asprintf(&value, "hal:%s", udi) == -1)
|
||||
return;
|
||||
|
||||
remove_devices("hal", value);
|
||||
|
||||
free(value);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_prop_string(LibHalContext * hal_ctx, const char *udi, const char *name)
|
||||
{
|
||||
char *prop, *ret;
|
||||
|
||||
prop = libhal_device_get_property_string(hal_ctx, udi, name, NULL);
|
||||
LogMessageVerb(X_INFO, 10, "config/hal: getting %s on %s returned %s\n",
|
||||
name, udi, prop ? prop : "(null)");
|
||||
if (prop) {
|
||||
ret = strdup(prop);
|
||||
libhal_free_string(prop);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_prop_string_array(LibHalContext * hal_ctx, const char *udi,
|
||||
const char *prop)
|
||||
{
|
||||
char **props, *ret, *str;
|
||||
int i, len = 0;
|
||||
|
||||
props = libhal_device_get_property_strlist(hal_ctx, udi, prop, NULL);
|
||||
if (props) {
|
||||
for (i = 0; props[i]; i++)
|
||||
len += strlen(props[i]);
|
||||
|
||||
ret = calloc(sizeof(char), len + i); /* i - 1 commas, 1 NULL */
|
||||
if (!ret) {
|
||||
libhal_free_string_array(props);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = ret;
|
||||
for (i = 0; props[i]; i++) {
|
||||
strcpy(str, props[i]);
|
||||
str += strlen(props[i]);
|
||||
*str++ = ',';
|
||||
}
|
||||
*(str - 1) = '\0';
|
||||
|
||||
libhal_free_string_array(props);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
device_added(LibHalContext * hal_ctx, const char *udi)
|
||||
{
|
||||
char *path = NULL, *driver = NULL, *name = NULL, *config_info = NULL;
|
||||
char *hal_tags, *parent;
|
||||
InputOption *input_options = NULL;
|
||||
InputAttributes attrs = { 0 };
|
||||
DeviceIntPtr dev = NULL;
|
||||
DBusError error;
|
||||
struct xkb_options xkb_opts = { 0 };
|
||||
int rc;
|
||||
|
||||
LibHalPropertySet *set = NULL;
|
||||
LibHalPropertySetIterator set_iter;
|
||||
char *psi_key = NULL, *tmp_val;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
driver = get_prop_string(hal_ctx, udi, "input.x11_driver");
|
||||
if (!driver) {
|
||||
/* verbose, don't tell the user unless they _want_ to see it */
|
||||
LogMessageVerb(X_INFO, 7,
|
||||
"config/hal: no driver specified for device %s\n", udi);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
path = get_prop_string(hal_ctx, udi, "input.device");
|
||||
if (!path) {
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: no driver or path specified for %s\n", udi);
|
||||
goto unwind;
|
||||
}
|
||||
attrs.device = strdup(path);
|
||||
|
||||
name = get_prop_string(hal_ctx, udi, "info.product");
|
||||
if (!name)
|
||||
name = strdup("(unnamed)");
|
||||
else
|
||||
attrs.product = strdup(name);
|
||||
|
||||
attrs.vendor = get_prop_string(hal_ctx, udi, "info.vendor");
|
||||
hal_tags = get_prop_string(hal_ctx, udi, "input.tags");
|
||||
attrs.tags = xstrtokenize(hal_tags, ",");
|
||||
free(hal_tags);
|
||||
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.keys", NULL))
|
||||
attrs.flags |= ATTR_KEY | ATTR_KEYBOARD;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.mouse", NULL))
|
||||
attrs.flags |= ATTR_POINTER;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.joystick", NULL))
|
||||
attrs.flags |= ATTR_JOYSTICK;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.tablet", NULL))
|
||||
attrs.flags |= ATTR_TABLET;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.tablet_pad", NULL))
|
||||
attrs.flags |= ATTR_TABLET_PAD;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.touchpad", NULL))
|
||||
attrs.flags |= ATTR_TOUCHPAD;
|
||||
if (libhal_device_query_capability(hal_ctx, udi, "input.touchscreen", NULL))
|
||||
attrs.flags |= ATTR_TOUCHSCREEN;
|
||||
|
||||
parent = get_prop_string(hal_ctx, udi, "info.parent");
|
||||
if (parent) {
|
||||
int usb_vendor, usb_product;
|
||||
char *old_parent;
|
||||
|
||||
/* construct USB ID in lowercase - "0000:ffff" */
|
||||
usb_vendor = libhal_device_get_property_int(hal_ctx, parent,
|
||||
"usb.vendor_id", NULL);
|
||||
LogMessageVerb(X_INFO, 10,
|
||||
"config/hal: getting usb.vendor_id on %s "
|
||||
"returned %04x\n", parent, usb_vendor);
|
||||
usb_product = libhal_device_get_property_int(hal_ctx, parent,
|
||||
"usb.product_id", NULL);
|
||||
LogMessageVerb(X_INFO, 10,
|
||||
"config/hal: getting usb.product_id on %s "
|
||||
"returned %04x\n", parent, usb_product);
|
||||
if (usb_vendor && usb_product)
|
||||
if (asprintf(&attrs.usb_id, "%04x:%04x", usb_vendor, usb_product)
|
||||
== -1)
|
||||
attrs.usb_id = NULL;
|
||||
|
||||
attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
|
||||
old_parent = parent;
|
||||
|
||||
while (!attrs.pnp_id &&
|
||||
(parent = get_prop_string(hal_ctx, parent, "info.parent"))) {
|
||||
attrs.pnp_id = get_prop_string(hal_ctx, parent, "pnp.id");
|
||||
|
||||
free(old_parent);
|
||||
old_parent = parent;
|
||||
}
|
||||
|
||||
free(old_parent);
|
||||
}
|
||||
|
||||
input_options = input_option_new(NULL, "_source", "server/hal");
|
||||
if (!input_options) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't allocate first key/value pair\n");
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* most drivers use device.. not path. evdev uses both however, but the
|
||||
* path version isn't documented apparently. support both for now. */
|
||||
input_options = input_option_new(input_options, "path", path);
|
||||
input_options = input_option_new(input_options, "device", path);
|
||||
|
||||
input_options = input_option_new(input_options, "driver", driver);
|
||||
input_options = input_option_new(input_options, "name", name);
|
||||
|
||||
if (asprintf(&config_info, "hal:%s", udi) == -1) {
|
||||
config_info = NULL;
|
||||
LogMessage(X_ERROR, "config/hal: couldn't allocate name\n");
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* Check for duplicate devices */
|
||||
if (device_is_duplicate(config_info)) {
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: device %s already added. Ignoring.\n", name);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
/* ok, grab options from hal.. iterate through all properties
|
||||
* and lets see if any of them are options that we can add */
|
||||
set = libhal_device_get_all_properties(hal_ctx, udi, &error);
|
||||
|
||||
if (!set) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't get property list for %s: %s (%s)\n",
|
||||
udi, error.name, error.message);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
libhal_psi_init(&set_iter, set);
|
||||
while (libhal_psi_has_more(&set_iter)) {
|
||||
/* we are looking for supported keys.. extract and add to options */
|
||||
psi_key = libhal_psi_get_key(&set_iter);
|
||||
|
||||
if (psi_key) {
|
||||
|
||||
/* normal options first (input.x11_options.<propname>) */
|
||||
if (!strncasecmp
|
||||
(psi_key, LIBHAL_PROP_KEY, sizeof(LIBHAL_PROP_KEY) - 1)) {
|
||||
char *tmp;
|
||||
|
||||
/* only support strings for all values */
|
||||
tmp_val = get_prop_string(hal_ctx, udi, psi_key);
|
||||
|
||||
if (tmp_val) {
|
||||
|
||||
/* xkb needs special handling. HAL specs include
|
||||
* input.xkb.xyz options, but the x11-input.fdi specifies
|
||||
* input.x11_options.Xkbxyz options. By default, we use
|
||||
* the former, unless the specific X11 ones are specified.
|
||||
* Since we can't predict the order in which the keys
|
||||
* arrive, we need to store them.
|
||||
*/
|
||||
if ((tmp = strcasestr(psi_key, "xkb")) && strlen(tmp) >= 4) {
|
||||
if (!strcasecmp(&tmp[3], "layout")) {
|
||||
free(xkb_opts.layout);
|
||||
xkb_opts.layout = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "model")) {
|
||||
free(xkb_opts.model);
|
||||
xkb_opts.model = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "rules")) {
|
||||
free(xkb_opts.rules);
|
||||
xkb_opts.rules = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "variant")) {
|
||||
free(xkb_opts.variant);
|
||||
xkb_opts.variant = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(&tmp[3], "options")) {
|
||||
free(xkb_opts.options);
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* all others */
|
||||
input_options =
|
||||
input_option_new(input_options,
|
||||
psi_key + sizeof(LIBHAL_PROP_KEY) -
|
||||
1, tmp_val);
|
||||
free(tmp_val);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* server 1.4 had xkb_options as strlist. */
|
||||
if ((tmp = strcasestr(psi_key, "xkb")) &&
|
||||
(strlen(tmp) >= 4) &&
|
||||
(!strcasecmp(&tmp[3], "options")) &&
|
||||
(tmp_val =
|
||||
get_prop_string_array(hal_ctx, udi, psi_key))) {
|
||||
free(xkb_opts.options);
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncasecmp
|
||||
(psi_key, LIBHAL_XKB_PROP_KEY,
|
||||
sizeof(LIBHAL_XKB_PROP_KEY) - 1)) {
|
||||
char *tmp;
|
||||
|
||||
/* only support strings for all values */
|
||||
tmp_val = get_prop_string(hal_ctx, udi, psi_key);
|
||||
|
||||
if (tmp_val && strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) {
|
||||
|
||||
tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1];
|
||||
|
||||
if (!strcasecmp(tmp, "layout")) {
|
||||
if (!xkb_opts.layout)
|
||||
xkb_opts.layout = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "rules")) {
|
||||
if (!xkb_opts.rules)
|
||||
xkb_opts.rules = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "variant")) {
|
||||
if (!xkb_opts.variant)
|
||||
xkb_opts.variant = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "model")) {
|
||||
if (!xkb_opts.model)
|
||||
xkb_opts.model = strdup(tmp_val);
|
||||
}
|
||||
else if (!strcasecmp(tmp, "options")) {
|
||||
if (!xkb_opts.options)
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
free(tmp_val);
|
||||
}
|
||||
else {
|
||||
/* server 1.4 had xkb options as strlist */
|
||||
tmp_val = get_prop_string_array(hal_ctx, udi, psi_key);
|
||||
if (tmp_val &&
|
||||
strlen(psi_key) >= sizeof(LIBHAL_XKB_PROP_KEY)) {
|
||||
tmp = &psi_key[sizeof(LIBHAL_XKB_PROP_KEY) - 1];
|
||||
if (!strcasecmp(tmp, ".options") && (!xkb_opts.options))
|
||||
xkb_opts.options = strdup(tmp_val);
|
||||
}
|
||||
free(tmp_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* psi_key doesn't need to be freed */
|
||||
libhal_psi_next(&set_iter);
|
||||
}
|
||||
|
||||
/* Now add xkb options */
|
||||
if (xkb_opts.layout)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_layout", xkb_opts.layout);
|
||||
if (xkb_opts.rules)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_rules", xkb_opts.rules);
|
||||
if (xkb_opts.variant)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_variant", xkb_opts.variant);
|
||||
if (xkb_opts.model)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_model", xkb_opts.model);
|
||||
if (xkb_opts.options)
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_options", xkb_opts.options);
|
||||
input_options = input_option_new(input_options, "config_info", config_info);
|
||||
|
||||
/* this isn't an error, but how else do you output something that the user can see? */
|
||||
LogMessage(X_INFO, "config/hal: Adding input device %s\n", name);
|
||||
if ((rc = NewInputDeviceRequest(input_options, &attrs, &dev)) != Success) {
|
||||
LogMessage(X_ERROR, "config/hal: NewInputDeviceRequest failed (%d)\n",
|
||||
rc);
|
||||
dev = NULL;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
unwind:
|
||||
if (set)
|
||||
libhal_free_property_set(set);
|
||||
free(path);
|
||||
free(driver);
|
||||
free(name);
|
||||
free(config_info);
|
||||
input_option_free_list(&input_options);
|
||||
|
||||
free(attrs.product);
|
||||
free(attrs.vendor);
|
||||
free(attrs.device);
|
||||
free(attrs.pnp_id);
|
||||
free(attrs.usb_id);
|
||||
if (attrs.tags) {
|
||||
char **tag = attrs.tags;
|
||||
|
||||
while (*tag) {
|
||||
free(*tag);
|
||||
tag++;
|
||||
}
|
||||
free(attrs.tags);
|
||||
}
|
||||
|
||||
free(xkb_opts.layout);
|
||||
free(xkb_opts.rules);
|
||||
free(xkb_opts.model);
|
||||
free(xkb_opts.variant);
|
||||
free(xkb_opts.options);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
disconnect_hook(void *data)
|
||||
{
|
||||
DBusError error;
|
||||
struct config_hal_info *info = data;
|
||||
|
||||
if (info->hal_ctx) {
|
||||
if (dbus_connection_get_is_connected(info->system_bus)) {
|
||||
dbus_error_init(&error);
|
||||
if (!libhal_ctx_shutdown(info->hal_ctx, &error))
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: disconnect_hook couldn't shut down context: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
libhal_ctx_free(info->hal_ctx);
|
||||
}
|
||||
|
||||
info->hal_ctx = NULL;
|
||||
info->system_bus = NULL;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
connect_and_register(DBusConnection * connection, struct config_hal_info *info)
|
||||
{
|
||||
DBusError error;
|
||||
char **devices;
|
||||
int num_devices, i;
|
||||
|
||||
if (info->hal_ctx)
|
||||
return TRUE; /* already registered, pretend we did something */
|
||||
|
||||
info->system_bus = connection;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
info->hal_ctx = libhal_ctx_new();
|
||||
if (!info->hal_ctx) {
|
||||
LogMessage(X_ERROR, "config/hal: couldn't create HAL context\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
if (!libhal_ctx_set_dbus_connection(info->hal_ctx, info->system_bus)) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't associate HAL context with bus\n");
|
||||
goto out_err;
|
||||
}
|
||||
if (!libhal_ctx_init(info->hal_ctx, &error)) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't initialise context: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
goto out_err;
|
||||
}
|
||||
if (!libhal_device_property_watch_all(info->hal_ctx, &error)) {
|
||||
LogMessage(X_ERROR,
|
||||
"config/hal: couldn't watch all properties: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
goto out_ctx;
|
||||
}
|
||||
libhal_ctx_set_device_added(info->hal_ctx, device_added);
|
||||
libhal_ctx_set_device_removed(info->hal_ctx, device_removed);
|
||||
|
||||
devices = libhal_find_device_by_capability(info->hal_ctx, "input",
|
||||
&num_devices, &error);
|
||||
/* FIXME: Get default devices if error is set. */
|
||||
if (dbus_error_is_set(&error)) {
|
||||
LogMessage(X_ERROR, "config/hal: couldn't find input device: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
goto out_ctx;
|
||||
}
|
||||
for (i = 0; i < num_devices; i++)
|
||||
device_added(info->hal_ctx, devices[i]);
|
||||
libhal_free_string_array(devices);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return TRUE;
|
||||
|
||||
out_ctx:
|
||||
dbus_error_free(&error);
|
||||
|
||||
if (!libhal_ctx_shutdown(info->hal_ctx, &error)) {
|
||||
LogMessage(X_WARNING,
|
||||
"config/hal: couldn't shut down context: %s (%s)\n",
|
||||
error.name ? error.name : "unknown error",
|
||||
error.message ? error.message : "null");
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
|
||||
out_err:
|
||||
dbus_error_free(&error);
|
||||
|
||||
if (info->hal_ctx) {
|
||||
libhal_ctx_free(info->hal_ctx);
|
||||
}
|
||||
|
||||
info->hal_ctx = NULL;
|
||||
info->system_bus = NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle NewOwnerChanged signals to deal with HAL startup at X server runtime.
|
||||
*
|
||||
* NewOwnerChanged is send once when HAL shuts down, and once again when it
|
||||
* comes back up. Message has three arguments, first is the name
|
||||
* (org.freedesktop.Hal), the second one is the old owner, third one is new
|
||||
* owner.
|
||||
*/
|
||||
static DBusHandlerResult
|
||||
ownerchanged_handler(DBusConnection * connection, DBusMessage * message,
|
||||
void *data)
|
||||
{
|
||||
int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
if (dbus_message_is_signal(message,
|
||||
"org.freedesktop.DBus", "NameOwnerChanged")) {
|
||||
DBusError error;
|
||||
char *name, *old_owner, *new_owner;
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_message_get_args(message, &error,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &old_owner,
|
||||
DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID);
|
||||
|
||||
if (dbus_error_is_set(&error)) {
|
||||
ErrorF
|
||||
("[config/hal] failed to get NameOwnerChanged args: %s (%s)\n",
|
||||
error.name, error.message);
|
||||
}
|
||||
else if (name && strcmp(name, "org.freedesktop.Hal") == 0) {
|
||||
|
||||
if (!old_owner || !strlen(old_owner)) {
|
||||
DebugF("[config/hal] HAL startup detected.\n");
|
||||
if (connect_and_register
|
||||
(connection, (struct config_hal_info *) data))
|
||||
dbus_connection_unregister_object_path(connection,
|
||||
"/org/freedesktop/DBus");
|
||||
else
|
||||
ErrorF("[config/hal] Failed to connect to HAL bus.\n");
|
||||
}
|
||||
|
||||
ret = DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
dbus_error_free(&error);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler for the NameOwnerChanged signal.
|
||||
*/
|
||||
static BOOL
|
||||
listen_for_startup(DBusConnection * connection, void *data)
|
||||
{
|
||||
DBusObjectPathVTable vtable = {.message_function = ownerchanged_handler, };
|
||||
DBusError error;
|
||||
const char MATCH_RULE[] = "sender='org.freedesktop.DBus',"
|
||||
"interface='org.freedesktop.DBus',"
|
||||
"type='signal',"
|
||||
"path='/org/freedesktop/DBus'," "member='NameOwnerChanged'";
|
||||
int rc = FALSE;
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_bus_add_match(connection, MATCH_RULE, &error);
|
||||
if (!dbus_error_is_set(&error)) {
|
||||
if (dbus_connection_register_object_path(connection,
|
||||
"/org/freedesktop/DBus",
|
||||
&vtable, data))
|
||||
rc = TRUE;
|
||||
else
|
||||
ErrorF("[config/hal] cannot register object path.\n");
|
||||
}
|
||||
else {
|
||||
ErrorF("[config/hal] couldn't add match rule: %s (%s)\n", error.name,
|
||||
error.message);
|
||||
ErrorF("[config/hal] cannot detect a HAL startup.\n");
|
||||
}
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
connect_hook(DBusConnection * connection, void *data)
|
||||
{
|
||||
struct config_hal_info *info = data;
|
||||
|
||||
if (listen_for_startup(connection, data) &&
|
||||
connect_and_register(connection, info))
|
||||
dbus_connection_unregister_object_path(connection,
|
||||
"/org/freedesktop/DBus");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct config_hal_info hal_info;
|
||||
|
||||
static struct dbus_core_hook hook = {
|
||||
.connect = connect_hook,
|
||||
.disconnect = disconnect_hook,
|
||||
.data = &hal_info,
|
||||
};
|
||||
|
||||
int
|
||||
config_hal_init(void)
|
||||
{
|
||||
memset(&hal_info, 0, sizeof(hal_info));
|
||||
hal_info.system_bus = NULL;
|
||||
hal_info.hal_ctx = NULL;
|
||||
|
||||
if (!dbus_core_add_hook(&hook)) {
|
||||
LogMessage(X_ERROR, "config/hal: failed to add D-Bus hook\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* verbose message */
|
||||
LogMessageVerb(X_INFO, 7, "config/hal: initialized\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_hal_fini(void)
|
||||
{
|
||||
dbus_core_remove_hook(&hook);
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
srcs_config = [
|
||||
'config.c',
|
||||
]
|
||||
|
||||
config_dep = [common_dep]
|
||||
|
||||
if build_dbus
|
||||
srcs_config += 'dbus-core.c'
|
||||
config_dep += dbus_dep
|
||||
endif
|
||||
|
||||
if build_hal
|
||||
srcs_config += 'hal.c'
|
||||
config_dep += hal_dep
|
||||
endif
|
||||
|
||||
if build_udev
|
||||
srcs_config += 'udev.c'
|
||||
config_dep += udev_dep
|
||||
endif
|
||||
|
||||
if host_machine.system() == 'openbsd'
|
||||
srcs_config += 'wscons.c'
|
||||
endif
|
||||
|
||||
if build_xorg
|
||||
install_data('10-quirks.conf',
|
||||
install_dir: join_paths(get_option('datadir'), 'X11/xorg.conf.d'))
|
||||
endif
|
||||
|
||||
libxserver_config = static_library('libxserver_config',
|
||||
srcs_config,
|
||||
include_directories: inc,
|
||||
dependencies: config_dep,
|
||||
)
|
579
config/udev.c
579
config/udev.c
|
@ -1,579 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Julien Cristau
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Author: Julien Cristau <jcristau@debian.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <libudev.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
#include "hotplug.h"
|
||||
#include "config-backends.h"
|
||||
#include "os.h"
|
||||
#include "globals.h"
|
||||
#include "systemd-logind.h"
|
||||
|
||||
#ifdef HAVE_SYS_SYSMACROS_H
|
||||
#include <sys/sysmacros.h>
|
||||
#endif
|
||||
|
||||
#define UDEV_XKB_PROP_KEY "xkb"
|
||||
|
||||
#define LOG_PROPERTY(path, prop, val) \
|
||||
LogMessageVerb(X_INFO, 10, \
|
||||
"config/udev: getting property %s on %s " \
|
||||
"returned \"%s\"\n", \
|
||||
(prop), (path), (val) ? (val) : "(null)")
|
||||
#define LOG_SYSATTR(path, attr, val) \
|
||||
LogMessageVerb(X_INFO, 10, \
|
||||
"config/udev: getting attribute %s on %s " \
|
||||
"returned \"%s\"\n", \
|
||||
(attr), (path), (val) ? (val) : "(null)")
|
||||
|
||||
static struct udev_monitor *udev_monitor;
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
static void
|
||||
config_udev_odev_setup_attribs(struct udev_device *udev_device, const char *path, const char *syspath,
|
||||
int major, int minor,
|
||||
config_odev_probe_proc_ptr probe_callback);
|
||||
#endif
|
||||
|
||||
static char itoa_buf[16];
|
||||
|
||||
static const char *itoa(int i)
|
||||
{
|
||||
snprintf(itoa_buf, sizeof(itoa_buf), "%d", i);
|
||||
return itoa_buf;
|
||||
}
|
||||
|
||||
static Bool
|
||||
check_seat(struct udev_device *udev_device)
|
||||
{
|
||||
const char *dev_seat;
|
||||
|
||||
dev_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
|
||||
if (!dev_seat)
|
||||
dev_seat = "seat0";
|
||||
|
||||
if (SeatId && strcmp(dev_seat, SeatId))
|
||||
return FALSE;
|
||||
|
||||
if (!SeatId && strcmp(dev_seat, "seat0"))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
device_added(struct udev_device *udev_device)
|
||||
{
|
||||
const char *path, *name = NULL;
|
||||
char *config_info = NULL;
|
||||
const char *syspath;
|
||||
const char *tags_prop;
|
||||
const char *key, *value, *tmp;
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
const char *subsys = NULL;
|
||||
#endif
|
||||
InputOption *input_options;
|
||||
InputAttributes attrs = { };
|
||||
DeviceIntPtr dev = NULL;
|
||||
struct udev_list_entry *set, *entry;
|
||||
struct udev_device *parent;
|
||||
int rc;
|
||||
dev_t devnum;
|
||||
|
||||
path = udev_device_get_devnode(udev_device);
|
||||
|
||||
syspath = udev_device_get_syspath(udev_device);
|
||||
|
||||
if (!path || !syspath)
|
||||
return;
|
||||
|
||||
if (!check_seat(udev_device))
|
||||
return;
|
||||
|
||||
devnum = udev_device_get_devnum(udev_device);
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
subsys = udev_device_get_subsystem(udev_device);
|
||||
|
||||
if (subsys && !strcmp(subsys, "drm")) {
|
||||
const char *sysname = udev_device_get_sysname(udev_device);
|
||||
|
||||
if (strncmp(sysname, "card", 4) != 0)
|
||||
return;
|
||||
|
||||
/* Check for devices already added through xf86platformProbe() */
|
||||
if (xf86_find_platform_device_by_devnum(major(devnum), minor(devnum)))
|
||||
return;
|
||||
|
||||
LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
|
||||
|
||||
config_udev_odev_setup_attribs(udev_device, path, syspath, major(devnum),
|
||||
minor(devnum), NewGPUDeviceRequest);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
value = udev_device_get_property_value(udev_device, "ID_INPUT");
|
||||
if (!value || !strcmp(value, "0")) {
|
||||
LogMessageVerb(X_INFO, 10,
|
||||
"config/udev: ignoring device %s without "
|
||||
"property ID_INPUT set\n", path);
|
||||
return;
|
||||
}
|
||||
|
||||
input_options = input_option_new(NULL, "_source", "server/udev");
|
||||
if (!input_options)
|
||||
return;
|
||||
|
||||
parent = udev_device_get_parent(udev_device);
|
||||
if (parent) {
|
||||
const char *ppath = udev_device_get_devnode(parent);
|
||||
const char *product = udev_device_get_property_value(parent, "PRODUCT");
|
||||
const char *pnp_id = udev_device_get_sysattr_value(parent, "id");
|
||||
unsigned int usb_vendor, usb_model;
|
||||
|
||||
name = udev_device_get_sysattr_value(parent, "name");
|
||||
LOG_SYSATTR(ppath, "name", name);
|
||||
if (!name) {
|
||||
name = udev_device_get_property_value(parent, "NAME");
|
||||
LOG_PROPERTY(ppath, "NAME", name);
|
||||
}
|
||||
|
||||
/* construct USB ID in lowercase hex - "0000:ffff" */
|
||||
if (product &&
|
||||
sscanf(product, "%*x/%4x/%4x/%*x", &usb_vendor, &usb_model) == 2) {
|
||||
char *usb_id;
|
||||
if (asprintf(&usb_id, "%04x:%04x", usb_vendor, usb_model)
|
||||
== -1)
|
||||
usb_id = NULL;
|
||||
else
|
||||
LOG_PROPERTY(ppath, "PRODUCT", product);
|
||||
attrs.usb_id = usb_id;
|
||||
}
|
||||
|
||||
while (!pnp_id && (parent = udev_device_get_parent(parent))) {
|
||||
pnp_id = udev_device_get_sysattr_value(parent, "id");
|
||||
if (!pnp_id)
|
||||
continue;
|
||||
|
||||
attrs.pnp_id = strdup(pnp_id);
|
||||
ppath = udev_device_get_devnode(parent);
|
||||
LOG_SYSATTR(ppath, "id", pnp_id);
|
||||
}
|
||||
|
||||
}
|
||||
if (!name)
|
||||
name = "(unnamed)";
|
||||
else
|
||||
attrs.product = strdup(name);
|
||||
input_options = input_option_new(input_options, "name", name);
|
||||
input_options = input_option_new(input_options, "path", path);
|
||||
input_options = input_option_new(input_options, "device", path);
|
||||
input_options = input_option_new(input_options, "major", itoa(major(devnum)));
|
||||
input_options = input_option_new(input_options, "minor", itoa(minor(devnum)));
|
||||
if (path)
|
||||
attrs.device = strdup(path);
|
||||
|
||||
tags_prop = udev_device_get_property_value(udev_device, "ID_INPUT.tags");
|
||||
LOG_PROPERTY(path, "ID_INPUT.tags", tags_prop);
|
||||
attrs.tags = xstrtokenize(tags_prop, ",");
|
||||
|
||||
if (asprintf(&config_info, "udev:%s", syspath) == -1) {
|
||||
config_info = NULL;
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
if (device_is_duplicate(config_info)) {
|
||||
LogMessage(X_WARNING, "config/udev: device %s already added. "
|
||||
"Ignoring.\n", name);
|
||||
goto unwind;
|
||||
}
|
||||
|
||||
set = udev_device_get_properties_list_entry(udev_device);
|
||||
udev_list_entry_foreach(entry, set) {
|
||||
key = udev_list_entry_get_name(entry);
|
||||
if (!key)
|
||||
continue;
|
||||
value = udev_list_entry_get_value(entry);
|
||||
if (!strncasecmp(key, UDEV_XKB_PROP_KEY, sizeof(UDEV_XKB_PROP_KEY) - 1)) {
|
||||
LOG_PROPERTY(path, key, value);
|
||||
tmp = key + sizeof(UDEV_XKB_PROP_KEY) - 1;
|
||||
if (!strcasecmp(tmp, "rules"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_rules", value);
|
||||
else if (!strcasecmp(tmp, "layout"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_layout", value);
|
||||
else if (!strcasecmp(tmp, "variant"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_variant", value);
|
||||
else if (!strcasecmp(tmp, "model"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_model", value);
|
||||
else if (!strcasecmp(tmp, "options"))
|
||||
input_options =
|
||||
input_option_new(input_options, "xkb_options", value);
|
||||
}
|
||||
else if (!strcmp(key, "ID_VENDOR")) {
|
||||
LOG_PROPERTY(path, key, value);
|
||||
attrs.vendor = strdup(value);
|
||||
} else if (!strncmp(key, "ID_INPUT_", 9)) {
|
||||
const struct pfmap {
|
||||
const char *property;
|
||||
unsigned int flag;
|
||||
} map[] = {
|
||||
{ "ID_INPUT_KEY", ATTR_KEY },
|
||||
{ "ID_INPUT_KEYBOARD", ATTR_KEYBOARD },
|
||||
{ "ID_INPUT_MOUSE", ATTR_POINTER },
|
||||
{ "ID_INPUT_JOYSTICK", ATTR_JOYSTICK },
|
||||
{ "ID_INPUT_TABLET", ATTR_TABLET },
|
||||
{ "ID_INPUT_TABLET_PAD", ATTR_TABLET_PAD },
|
||||
{ "ID_INPUT_TOUCHPAD", ATTR_TOUCHPAD },
|
||||
{ "ID_INPUT_TOUCHSCREEN", ATTR_TOUCHSCREEN },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
/* Anything but the literal string "0" is considered a
|
||||
* boolean true. The empty string isn't a thing with udev
|
||||
* properties anyway */
|
||||
if (value && strcmp(value, "0")) {
|
||||
const struct pfmap *m = map;
|
||||
|
||||
while (m->property != NULL) {
|
||||
if (!strcmp(m->property, key)) {
|
||||
LOG_PROPERTY(path, key, value);
|
||||
attrs.flags |= m->flag;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input_options = input_option_new(input_options, "config_info", config_info);
|
||||
|
||||
/* Default setting needed for non-seat0 seats */
|
||||
if (ServerIsNotSeat0())
|
||||
input_options = input_option_new(input_options, "GrabDevice", "on");
|
||||
|
||||
LogMessage(X_INFO, "config/udev: Adding input device %s (%s)\n",
|
||||
name, path);
|
||||
rc = NewInputDeviceRequest(input_options, &attrs, &dev);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
unwind:
|
||||
free(config_info);
|
||||
input_option_free_list(&input_options);
|
||||
|
||||
free(attrs.usb_id);
|
||||
free(attrs.pnp_id);
|
||||
free(attrs.product);
|
||||
free(attrs.device);
|
||||
free(attrs.vendor);
|
||||
if (attrs.tags) {
|
||||
char **tag = attrs.tags;
|
||||
|
||||
while (*tag) {
|
||||
free(*tag);
|
||||
tag++;
|
||||
}
|
||||
free(attrs.tags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
device_removed(struct udev_device *device)
|
||||
{
|
||||
char *value;
|
||||
const char *syspath = udev_device_get_syspath(device);
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
const char *subsys = udev_device_get_subsystem(device);
|
||||
|
||||
if (subsys && !strcmp(subsys, "drm")) {
|
||||
const char *sysname = udev_device_get_sysname(device);
|
||||
const char *path = udev_device_get_devnode(device);
|
||||
dev_t devnum = udev_device_get_devnum(device);
|
||||
|
||||
if ((strncmp(sysname,"card", 4) != 0) || (path == NULL))
|
||||
return;
|
||||
|
||||
LogMessage(X_INFO, "config/udev: removing GPU device %s %s\n",
|
||||
syspath, path);
|
||||
config_udev_odev_setup_attribs(device, path, syspath, major(devnum),
|
||||
minor(devnum), DeleteGPUDeviceRequest);
|
||||
/* Retry vtenter after a drm node removal */
|
||||
systemd_logind_vtenter();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (asprintf(&value, "udev:%s", syspath) == -1)
|
||||
return;
|
||||
|
||||
remove_devices("udev", value);
|
||||
|
||||
free(value);
|
||||
}
|
||||
|
||||
static void
|
||||
socket_handler(int fd, int ready, void *data)
|
||||
{
|
||||
struct udev_device *udev_device;
|
||||
const char *action;
|
||||
|
||||
input_lock();
|
||||
udev_device = udev_monitor_receive_device(udev_monitor);
|
||||
if (!udev_device) {
|
||||
input_unlock();
|
||||
return;
|
||||
}
|
||||
action = udev_device_get_action(udev_device);
|
||||
if (action) {
|
||||
if (!strcmp(action, "add")) {
|
||||
device_removed(udev_device);
|
||||
device_added(udev_device);
|
||||
} else if (!strcmp(action, "change")) {
|
||||
/* ignore change for the drm devices */
|
||||
const char *subsys = udev_device_get_subsystem(udev_device);
|
||||
|
||||
if (subsys && strcmp(subsys, "drm")) {
|
||||
device_removed(udev_device);
|
||||
device_added(udev_device);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(action, "remove"))
|
||||
device_removed(udev_device);
|
||||
}
|
||||
udev_device_unref(udev_device);
|
||||
input_unlock();
|
||||
}
|
||||
|
||||
int
|
||||
config_udev_pre_init(void)
|
||||
{
|
||||
struct udev *udev;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return 0;
|
||||
|
||||
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||
if (!udev_monitor)
|
||||
return 0;
|
||||
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "input",
|
||||
NULL);
|
||||
/* For Wacom serial devices */
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "tty", NULL);
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
/* For output GPU devices */
|
||||
udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, "drm", NULL);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UDEV_MONITOR_FILTER_ADD_MATCH_TAG
|
||||
if (ServerIsNotSeat0())
|
||||
udev_monitor_filter_add_match_tag(udev_monitor, SeatId);
|
||||
#endif
|
||||
if (udev_monitor_enable_receiving(udev_monitor)) {
|
||||
ErrorF("config/udev: failed to bind the udev monitor\n");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
config_udev_init(void)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_enumerate *enumerate;
|
||||
struct udev_list_entry *devices, *device;
|
||||
|
||||
udev = udev_monitor_get_udev(udev_monitor);
|
||||
enumerate = udev_enumerate_new(udev);
|
||||
if (!enumerate)
|
||||
return 0;
|
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "input");
|
||||
udev_enumerate_add_match_subsystem(enumerate, "tty");
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
udev_enumerate_add_match_subsystem(enumerate, "drm");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UDEV_ENUMERATE_ADD_MATCH_TAG
|
||||
if (ServerIsNotSeat0())
|
||||
udev_enumerate_add_match_tag(enumerate, SeatId);
|
||||
#endif
|
||||
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry_foreach(device, devices) {
|
||||
const char *syspath = udev_list_entry_get_name(device);
|
||||
struct udev_device *udev_device =
|
||||
udev_device_new_from_syspath(udev, syspath);
|
||||
|
||||
/* Device might be gone by the time we try to open it */
|
||||
if (!udev_device)
|
||||
continue;
|
||||
|
||||
device_added(udev_device);
|
||||
udev_device_unref(udev_device);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
|
||||
SetNotifyFd(udev_monitor_get_fd(udev_monitor), socket_handler, X_NOTIFY_READ, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_udev_fini(void)
|
||||
{
|
||||
struct udev *udev;
|
||||
|
||||
if (!udev_monitor)
|
||||
return;
|
||||
|
||||
udev = udev_monitor_get_udev(udev_monitor);
|
||||
|
||||
RemoveNotifyFd(udev_monitor_get_fd(udev_monitor));
|
||||
udev_monitor_unref(udev_monitor);
|
||||
udev_monitor = NULL;
|
||||
udev_unref(udev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UDEV_KMS
|
||||
|
||||
/* Find the last occurrence of the needle in haystack */
|
||||
static char *strrstr(const char *haystack, const char *needle)
|
||||
{
|
||||
char *prev, *last, *tmp;
|
||||
|
||||
prev = strstr(haystack, needle);
|
||||
if (!prev)
|
||||
return NULL;
|
||||
|
||||
last = prev;
|
||||
tmp = prev + 1;
|
||||
|
||||
while (tmp) {
|
||||
last = strstr(tmp, needle);
|
||||
if (!last)
|
||||
return prev;
|
||||
else {
|
||||
prev = last;
|
||||
tmp = prev + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
static void
|
||||
config_udev_odev_setup_attribs(struct udev_device *udev_device, const char *path, const char *syspath,
|
||||
int major, int minor,
|
||||
config_odev_probe_proc_ptr probe_callback)
|
||||
{
|
||||
struct OdevAttributes *attribs = config_odev_allocate_attributes();
|
||||
const char *value, *str;
|
||||
|
||||
attribs->path = XNFstrdup(path);
|
||||
attribs->syspath = XNFstrdup(syspath);
|
||||
attribs->major = major;
|
||||
attribs->minor = minor;
|
||||
|
||||
value = udev_device_get_property_value(udev_device, "ID_PATH");
|
||||
if (value && (str = strrstr(value, "pci-"))) {
|
||||
value = str;
|
||||
|
||||
if ((str = strstr(value, "usb-")))
|
||||
value = str;
|
||||
|
||||
attribs->busid = XNFstrdup(value);
|
||||
attribs->busid[3] = ':';
|
||||
}
|
||||
|
||||
/* ownership of attribs is passed to probe layer */
|
||||
probe_callback(attribs);
|
||||
}
|
||||
|
||||
void
|
||||
config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_enumerate *enumerate;
|
||||
struct udev_list_entry *devices, *device;
|
||||
|
||||
udev = udev_monitor_get_udev(udev_monitor);
|
||||
enumerate = udev_enumerate_new(udev);
|
||||
if (!enumerate)
|
||||
return;
|
||||
|
||||
udev_enumerate_add_match_subsystem(enumerate, "drm");
|
||||
udev_enumerate_add_match_sysname(enumerate, "card[0-9]*");
|
||||
#ifdef HAVE_UDEV_ENUMERATE_ADD_MATCH_TAG
|
||||
if (ServerIsNotSeat0())
|
||||
udev_enumerate_add_match_tag(enumerate, SeatId);
|
||||
#endif
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
udev_list_entry_foreach(device, devices) {
|
||||
const char *syspath = udev_list_entry_get_name(device);
|
||||
struct udev_device *udev_device = udev_device_new_from_syspath(udev, syspath);
|
||||
const char *path = udev_device_get_devnode(udev_device);
|
||||
const char *sysname = udev_device_get_sysname(udev_device);
|
||||
dev_t devnum = udev_device_get_devnum(udev_device);
|
||||
const char *subsys = udev_device_get_subsystem(udev_device);
|
||||
|
||||
if (!path || !syspath || !subsys)
|
||||
goto no_probe;
|
||||
else if (strcmp(subsys, "drm") != 0)
|
||||
goto no_probe;
|
||||
else if (strncmp(sysname, "card", 4) != 0)
|
||||
goto no_probe;
|
||||
else if (!check_seat(udev_device))
|
||||
goto no_probe;
|
||||
|
||||
config_udev_odev_setup_attribs(udev_device, path, syspath, major(devnum),
|
||||
minor(devnum), probe_callback);
|
||||
no_probe:
|
||||
udev_device_unref(udev_device);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
262
config/wscons.c
262
config/wscons.c
|
@ -1,262 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2011 Matthieu Herrb
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <dev/wscons/wsconsio.h>
|
||||
#include <dev/wscons/wsksymdef.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "input.h"
|
||||
#include "inputstr.h"
|
||||
#include "os.h"
|
||||
#include "config-backends.h"
|
||||
|
||||
#define WSCONS_KBD_DEVICE "/dev/wskbd"
|
||||
#define WSCONS_MOUSE_PREFIX "/dev/wsmouse"
|
||||
|
||||
#define KB_OVRENC \
|
||||
{ KB_UK, "gb" }, \
|
||||
{ KB_SV, "se" }, \
|
||||
{ KB_SG, "ch" }, \
|
||||
{ KB_SF, "ch" }, \
|
||||
{ KB_LA, "latam" }, \
|
||||
{ KB_CF, "ca" }
|
||||
|
||||
struct nameint {
|
||||
int val;
|
||||
char *name;
|
||||
} kbdenc[] = {
|
||||
KB_OVRENC,
|
||||
KB_ENCTAB,
|
||||
{0}
|
||||
};
|
||||
|
||||
struct nameint kbdvar[] = {
|
||||
{KB_NODEAD | KB_SG, "de_nodeadkeys"},
|
||||
{KB_NODEAD | KB_SF, "fr_nodeadkeys"},
|
||||
{KB_SF, "fr"},
|
||||
{KB_DVORAK | KB_CF, "fr-dvorak"},
|
||||
{KB_DVORAK | KB_FR, "bepo"},
|
||||
{KB_DVORAK, "dvorak"},
|
||||
{KB_CF, "fr-legacy"},
|
||||
{KB_NODEAD, "nodeadkeys"},
|
||||
{0}
|
||||
};
|
||||
|
||||
struct nameint kbdopt[] = {
|
||||
{KB_SWAPCTRLCAPS, "ctrl:swapcaps"},
|
||||
{0}
|
||||
};
|
||||
|
||||
struct nameint kbdmodel[] = {
|
||||
{WSKBD_TYPE_ZAURUS, "zaurus"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void
|
||||
wscons_add_keyboard(void)
|
||||
{
|
||||
InputAttributes attrs = { };
|
||||
DeviceIntPtr dev = NULL;
|
||||
InputOption *input_options = NULL;
|
||||
char *config_info = NULL;
|
||||
int fd, i, rc;
|
||||
unsigned int type;
|
||||
kbd_t wsenc = 0;
|
||||
|
||||
/* Find keyboard configuration */
|
||||
fd = open(WSCONS_KBD_DEVICE, O_RDWR | O_NONBLOCK | O_EXCL);
|
||||
if (fd == -1) {
|
||||
LogMessage(X_ERROR, "wskbd: open %s: %s\n",
|
||||
WSCONS_KBD_DEVICE, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, WSKBDIO_GETENCODING, &wsenc) == -1) {
|
||||
LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GETENCODING) "
|
||||
"failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
if (ioctl(fd, WSKBDIO_GTYPE, &type) == -1) {
|
||||
LogMessage(X_WARNING, "wskbd: ioctl(WSKBDIO_GTYPE) "
|
||||
"failed: %s\n", strerror(errno));
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
input_options = input_option_new(input_options, "_source", "server/wscons");
|
||||
if (input_options == NULL)
|
||||
return;
|
||||
|
||||
LogMessage(X_INFO, "config/wscons: checking input device %s\n",
|
||||
WSCONS_KBD_DEVICE);
|
||||
input_options = input_option_new(input_options, "name", WSCONS_KBD_DEVICE);
|
||||
input_options = input_option_new(input_options, "driver", "kbd");
|
||||
|
||||
config_info = Xprintf("wscons:%s", WSCONS_KBD_DEVICE);
|
||||
if (!config_info)
|
||||
goto unwind;
|
||||
if (KB_ENCODING(wsenc) == KB_USER) {
|
||||
/* Ignore wscons "user" layout */
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: ignoring \"user\" layout\n");
|
||||
goto kbd_config_done;
|
||||
}
|
||||
for (i = 0; kbdenc[i].val; i++)
|
||||
if (KB_ENCODING(wsenc) == kbdenc[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using layout %s\n",
|
||||
kbdenc[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_layout", kbdenc[i].name);
|
||||
break;
|
||||
}
|
||||
for (i = 0; kbdvar[i].val; i++)
|
||||
if (wsenc == kbdvar[i].val || KB_VARIANT(wsenc) == kbdvar[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using variant %s\n",
|
||||
kbdvar[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_variant", kbdvar[i].name);
|
||||
break;
|
||||
}
|
||||
for (i = 0; kbdopt[i].val; i++)
|
||||
if (KB_VARIANT(wsenc) == kbdopt[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using option %s\n",
|
||||
kbdopt[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_options", kbdopt[i].name);
|
||||
break;
|
||||
}
|
||||
for (i = 0; kbdmodel[i].val; i++)
|
||||
if (type == kbdmodel[i].val) {
|
||||
LogMessageVerb(X_INFO, 3, "wskbd: using model %s\n",
|
||||
kbdmodel[i].name);
|
||||
input_options = input_option_new(input_options,
|
||||
"xkb_model", kbdmodel[i].name);
|
||||
break;
|
||||
}
|
||||
|
||||
kbd_config_done:
|
||||
attrs.flags |= ATTR_KEY | ATTR_KEYBOARD;
|
||||
rc = NewInputDeviceRequest(input_options, &attrs, &dev);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
for (; dev; dev = dev->next) {
|
||||
free(dev->config_info);
|
||||
dev->config_info = strdup(config_info);
|
||||
}
|
||||
unwind:
|
||||
input_option_free_list(&input_options);
|
||||
}
|
||||
|
||||
static void
|
||||
wscons_add_pointer(const char *path, const char *driver, int flags)
|
||||
{
|
||||
InputAttributes attrs = { };
|
||||
DeviceIntPtr dev = NULL;
|
||||
InputOption *input_options = NULL;
|
||||
char *config_info = NULL;
|
||||
int rc;
|
||||
|
||||
config_info = Xprintf("wscons:%s", path);
|
||||
if (!config_info)
|
||||
return;
|
||||
|
||||
input_options = input_option_new(input_options, "_source", "server/wscons");
|
||||
if (input_options == NULL)
|
||||
return;
|
||||
|
||||
input_options = input_option_new(input_options, "name", strdup(path));
|
||||
input_options = input_option_new(input_options, "driver", strdup(driver));
|
||||
input_options = input_option_new(input_options, "device", strdup(path));
|
||||
LogMessage(X_INFO, "config/wscons: checking input device %s\n", path);
|
||||
attrs.flags |= flags;
|
||||
rc = NewInputDeviceRequest(input_options, &attrs, &dev);
|
||||
if (rc != Success)
|
||||
goto unwind;
|
||||
|
||||
for (; dev; dev = dev->next) {
|
||||
free(dev->config_info);
|
||||
dev->config_info = strdup(config_info);
|
||||
}
|
||||
unwind:
|
||||
input_option_free_list(&input_options);
|
||||
}
|
||||
|
||||
static void
|
||||
wscons_add_pointers(void)
|
||||
{
|
||||
char devname[256];
|
||||
int fd, i, wsmouse_type;
|
||||
|
||||
/* Check pointing devices */
|
||||
for (i = 0; i < 4; i++) {
|
||||
snprintf(devname, sizeof(devname), "%s%d", WSCONS_MOUSE_PREFIX, i);
|
||||
LogMessageVerb(X_INFO, 10, "wsmouse: checking %s\n", devname);
|
||||
fd = open_device(devnamem O_RDWR | O_NONBLOCK | O_EXCL);
|
||||
if (fd == -1) {
|
||||
LogMessageVerb(X_WARNING, 10, "%s: %s\n", devname, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
if (ioctl(fd, WSMOUSEIO_GTYPE, &wsmouse_type) != 0) {
|
||||
LogMessageVerb(X_WARNING, 10,
|
||||
"%s: WSMOUSEIO_GTYPE failed\n", devname);
|
||||
close(fd);
|
||||
continue;
|
||||
}
|
||||
close(fd);
|
||||
switch (wsmouse_type) {
|
||||
case WSMOUSE_TYPE_SYNAPTICS:
|
||||
wscons_add_pointer(devname, "synaptics", ATTR_TOUCHPAD);
|
||||
break;
|
||||
case WSMOUSE_TYPE_TPANEL:
|
||||
wscons_add_pointer(devname, "ws", ATTR_TOUCHSCREEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Add a default entry catching all other mux elements as "mouse" */
|
||||
wscons_add_pointer(WSCONS_MOUSE_PREFIX, "mouse", ATTR_POINTER);
|
||||
}
|
||||
|
||||
int
|
||||
config_wscons_init(void)
|
||||
{
|
||||
wscons_add_keyboard();
|
||||
wscons_add_pointers();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
config_wscons_fini(void)
|
||||
{
|
||||
/* Not much to do ? */
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<deviceinfo version="0.2">
|
||||
<device>
|
||||
|
||||
<!-- The way this works:
|
||||
|
||||
Match against some input device (see the HAL specification for more
|
||||
information), and then merge in keys, which you can use to specify
|
||||
the configuration similar to the way you would in xorg.conf. You will
|
||||
need to restart HAL after making changes. If you are having issues,
|
||||
starting X with the -logverbose 7 flag may yield useful information.
|
||||
|
||||
Keys Supported:
|
||||
|
||||
Key "input.x11_driver" (string)
|
||||
This specifies the driver to use. You MUST specify this option,
|
||||
or a driver will not be loaded and the rest will be ignored by
|
||||
Xorg
|
||||
|
||||
Key "input.x11_options.<option name>" (string)
|
||||
This allows you to specify arbitrary options to pass to the driver.
|
||||
Anything you would normally specify in xorg.conf goes here. So, for
|
||||
option "Mode" in xorg.conf, you would specify the key name of
|
||||
"input.x11_options.Mode".
|
||||
|
||||
Do not specify "input.x11_options.Device" since "input.device"
|
||||
will be used automatically.
|
||||
|
||||
You MUST specify all options as strings, otherwise the server will
|
||||
ignore them.
|
||||
|
||||
Legacy Keys
|
||||
"input.xkb.rules"
|
||||
"input.xkb.model"
|
||||
"input.xkb.layout"
|
||||
"input.xkb.variant"
|
||||
"input.xkb.options"
|
||||
|
||||
These keys are deprecated. Use these instead:
|
||||
"input.x11_options.XkbRules"
|
||||
"input.x11_options.XkbModel"
|
||||
"input.x11_options.XkbLayout"
|
||||
"input.x11_options.XkbVariant"
|
||||
"input.x11_options.XkbOptions"
|
||||
|
||||
See the evdev documentation for more information.
|
||||
|
||||
FIXME: Support tablets too.
|
||||
TODO: I think its fixed, can't test
|
||||
|
||||
-->
|
||||
|
||||
<match key="info.capabilities" contains="input.mouse">
|
||||
<merge key="input.x11_driver" type="string">mouse</merge>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="Linux">
|
||||
<merge key="input.x11_driver" type="string">evdev</merge>
|
||||
</match>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="SunOS">
|
||||
<match key="input.device" contains="usb">
|
||||
<merge key="input.x11_options.StreamsModule" type="string">usbms</merge>
|
||||
<merge key="input.x11_options.Protocol" type="string">VUID</merge>
|
||||
</match>
|
||||
</match>
|
||||
</match>
|
||||
|
||||
<match key="info.capabilities" contains="input.keys">
|
||||
<merge key="input.x11_options.XkbRules" type="string">base</merge>
|
||||
|
||||
<!-- If we're using Linux, we use evdev by default (falling back to
|
||||
kbd otherwise). -->
|
||||
<merge key="input.x11_driver" type="string">kbd</merge>
|
||||
<merge key="input.x11_options.XkbModel" type="string">pc105</merge>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="Linux">
|
||||
<merge key="input.x11_driver" type="string">evdev</merge>
|
||||
<merge key="input.x11_options.XkbModel" type="string">evdev</merge>
|
||||
</match>
|
||||
<match key="/org/freedesktop/Hal/devices/computer:system.kernel.name"
|
||||
string="SunOS">
|
||||
<match key="input.device" contains="usb">
|
||||
<merge key="input.x11_options.StreamsModule" type="string">usbkbm</merge>
|
||||
<merge key="input.x11_options.Protocol" type="string">VUID</merge>
|
||||
</match>
|
||||
</match>
|
||||
|
||||
<merge key="input.x11_options.XkbLayout" type="string">us</merge>
|
||||
|
||||
<merge key="input.x11_options.XkbVariant" type="string" />
|
||||
</match>
|
||||
</device>
|
||||
</deviceinfo>
|
2526
configure.ac
2526
configure.ac
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +0,0 @@
|
|||
noinst_LTLIBRARIES = libdamageext.la
|
||||
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
libdamageext_la_SOURCES = \
|
||||
damageext.c \
|
||||
damageextint.h
|
|
@ -1,12 +0,0 @@
|
|||
noinst_LTLIBRARIES = libdbe.la
|
||||
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
if XORG
|
||||
sdk_HEADERS = dbestruct.h
|
||||
endif
|
||||
|
||||
libdbe_la_SOURCES = \
|
||||
dbe.c \
|
||||
midbe.c \
|
||||
midbe.h
|
|
@ -12,5 +12,3 @@ libxserver_dbe = static_library('libxserver_dbe',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
install_data(hdrs_dbe, install_dir: xorgsdkdir)
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
noinst_LTLIBRARIES = libdix.la libmain.la
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
libmain_la_SOURCES = \
|
||||
stubmain.c
|
||||
|
||||
libdix_la_SOURCES = \
|
||||
atom.c \
|
||||
colormap.c \
|
||||
cursor.c \
|
||||
devices.c \
|
||||
dispatch.c \
|
||||
dispatch.h \
|
||||
dixfonts.c \
|
||||
main.c \
|
||||
dixutils.c \
|
||||
enterleave.c \
|
||||
enterleave.h \
|
||||
events.c \
|
||||
eventconvert.c \
|
||||
extension.c \
|
||||
gc.c \
|
||||
getevents.c \
|
||||
globals.c \
|
||||
glyphcurs.c \
|
||||
grabs.c \
|
||||
initatoms.c \
|
||||
inpututils.c \
|
||||
pixmap.c \
|
||||
privates.c \
|
||||
property.c \
|
||||
ptrveloc.c \
|
||||
region.c \
|
||||
registry.c \
|
||||
resource.c \
|
||||
selection.c \
|
||||
swaprep.c \
|
||||
swapreq.c \
|
||||
tables.c \
|
||||
touch.c \
|
||||
window.c
|
||||
|
||||
EXTRA_DIST = buildatoms BuiltInAtoms
|
||||
|
||||
# Install list of protocol names
|
||||
miscconfigdir = $(SERVER_MISC_CONFIG_PATH)
|
||||
dist_miscconfig_DATA = protocol.txt
|
||||
|
||||
if SPECIAL_DTRACE_OBJECTS
|
||||
# Generate dtrace object code for probes in libdix
|
||||
dtrace-dix.o: $(top_srcdir)/include/Xserver.d libdix.la
|
||||
$(AM_V_GEN)$(DTRACE) -G -C -o $@ -s $(top_srcdir)/include/Xserver.d $(am_libdix_la_OBJECTS:%.lo=.libs/%.o)
|
||||
|
||||
noinst_PROGRAMS = dix.O
|
||||
|
||||
dix_O_SOURCES =
|
||||
dix.O: dtrace-dix.o libdix.la
|
||||
$(AM_V_GEN)ld -r -o $@ $(am_libdix_la_OBJECTS:%.lo=.libs/%.o)
|
||||
endif
|
|
@ -2257,6 +2257,9 @@ ProcChangePointerControl(ClientPtr client)
|
|||
REQUEST(xChangePointerControlReq);
|
||||
REQUEST_SIZE_MATCH(xChangePointerControlReq);
|
||||
|
||||
/* If the device has no PtrFeedbackPtr, the xserver has a bug */
|
||||
BUG_RETURN_VAL (!mouse->ptrfeed, BadImplementation);
|
||||
|
||||
ctrl = mouse->ptrfeed->ctrl;
|
||||
if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
|
||||
client->errorValue = stuff->doAccel;
|
||||
|
|
|
@ -1343,7 +1343,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
|||
int buttons, CARD32 ms, int flags,
|
||||
const ValuatorMask *mask_in)
|
||||
{
|
||||
int num_events = 1;
|
||||
int num_events = 0;
|
||||
DeviceEvent *event;
|
||||
RawDeviceEvent *raw = NULL;
|
||||
double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
|
||||
|
@ -1386,6 +1386,10 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
|||
num_events++;
|
||||
|
||||
init_raw(pDev, raw, ms, type, buttons);
|
||||
|
||||
if (flags & POINTER_EMULATED)
|
||||
raw->flags = XIPointerEmulated;
|
||||
|
||||
set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
|
||||
}
|
||||
|
||||
|
@ -1454,36 +1458,37 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
|||
master->last.valuators[1] = screeny;
|
||||
}
|
||||
|
||||
event = &events->device_event;
|
||||
init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
|
||||
if ((flags & POINTER_RAWONLY) == 0) {
|
||||
num_events++;
|
||||
|
||||
if (type == MotionNotify) {
|
||||
event->type = ET_Motion;
|
||||
event->detail.button = 0;
|
||||
}
|
||||
else {
|
||||
if (type == ButtonPress) {
|
||||
event->type = ET_ButtonPress;
|
||||
set_button_down(pDev, buttons, BUTTON_POSTED);
|
||||
event = &events->device_event;
|
||||
init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
|
||||
|
||||
if (type == MotionNotify) {
|
||||
event->type = ET_Motion;
|
||||
event->detail.button = 0;
|
||||
}
|
||||
else if (type == ButtonRelease) {
|
||||
event->type = ET_ButtonRelease;
|
||||
set_button_up(pDev, buttons, BUTTON_POSTED);
|
||||
else {
|
||||
if (type == ButtonPress) {
|
||||
event->type = ET_ButtonPress;
|
||||
set_button_down(pDev, buttons, BUTTON_POSTED);
|
||||
}
|
||||
else if (type == ButtonRelease) {
|
||||
event->type = ET_ButtonRelease;
|
||||
set_button_up(pDev, buttons, BUTTON_POSTED);
|
||||
}
|
||||
event->detail.button = buttons;
|
||||
}
|
||||
event->detail.button = buttons;
|
||||
|
||||
/* root_x and root_y must be in per-screen coordinates */
|
||||
event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
|
||||
|
||||
if (flags & POINTER_EMULATED)
|
||||
event->flags = XIPointerEmulated;
|
||||
|
||||
set_valuators(pDev, event, &mask);
|
||||
}
|
||||
|
||||
/* root_x and root_y must be in per-screen coordinates */
|
||||
event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
|
||||
|
||||
if (flags & POINTER_EMULATED) {
|
||||
if (raw)
|
||||
raw->flags = XIPointerEmulated;
|
||||
event->flags = XIPointerEmulated;
|
||||
}
|
||||
|
||||
set_valuators(pDev, event, &mask);
|
||||
|
||||
return num_events;
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,6 @@ Equipment Corporation.
|
|||
#include <X11/fonts/libxfont2.h>
|
||||
#include "opaque.h"
|
||||
#include "servermd.h"
|
||||
#include "hotplug.h"
|
||||
#include "dixfont.h"
|
||||
#include "extnsionst.h"
|
||||
#include "privates.h"
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
SUBDIRS = dtrace
|
||||
|
||||
if ENABLE_DEVEL_DOCS
|
||||
if HAVE_XMLTO
|
||||
|
||||
# Main DocBook/XML files (DOCTYPE book)
|
||||
docbook = Xserver-spec.xml Xinput.xml
|
||||
|
||||
# Generate DocBook/XML output formats with or without stylesheets
|
||||
include $(top_srcdir)/devbook.am
|
||||
|
||||
endif HAVE_XMLTO
|
||||
endif ENABLE_DEVEL_DOCS
|
||||
|
||||
EXTRA_DIST = smartsched filter-xmlto.sh
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
if ENABLE_DOCS
|
||||
if XSERVER_DTRACE
|
||||
|
||||
# Main DocBook/XML files (DOCTYPE book)
|
||||
docbook = Xserver-DTrace.xml
|
||||
|
||||
# The location where the DocBook/XML files and their generated formats are installed
|
||||
shelfdir = $(docdir)
|
||||
|
||||
# Generate DocBook/XML output formats with or without stylesheets
|
||||
include $(top_srcdir)/docbook.am
|
||||
|
||||
endif XSERVER_DTRACE
|
||||
endif ENABLE_DOCS
|
|
@ -1,13 +0,0 @@
|
|||
noinst_LTLIBRARIES = libdri3.la
|
||||
AM_CFLAGS = \
|
||||
@DIX_CFLAGS@ \
|
||||
@LIBDRM_CFLAGS@
|
||||
|
||||
libdri3_la_SOURCES = \
|
||||
dri3.h \
|
||||
dri3_priv.h \
|
||||
dri3.c \
|
||||
dri3_request.c \
|
||||
dri3_screen.c
|
||||
|
||||
sdk_HEADERS = dri3.h
|
|
@ -16,5 +16,3 @@ if build_dri3
|
|||
dependencies: [ common_dep, libdrm_dep ],
|
||||
)
|
||||
endif
|
||||
|
||||
install_data(hdrs_dri3, install_dir: xorgsdkdir)
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
noinst_LTLIBRARIES = libexa.la
|
||||
|
||||
if XORG
|
||||
sdk_HEADERS = exa.h
|
||||
endif
|
||||
|
||||
AM_CPPFLAGS = $(XORG_INCS)
|
||||
|
||||
AM_CFLAGS = $(XORG_CFLAGS) $(DIX_CFLAGS)
|
||||
|
||||
libexa_la_SOURCES = \
|
||||
exa.c \
|
||||
exa.h \
|
||||
exa_classic.c \
|
||||
exa_migration_classic.c \
|
||||
exa_driver.c \
|
||||
exa_mixed.c \
|
||||
exa_migration_mixed.c \
|
||||
exa_accel.c \
|
||||
exa_glyphs.c \
|
||||
exa_offscreen.c \
|
||||
exa_render.c \
|
||||
exa_priv.h \
|
||||
exa_unaccel.c
|
820
exa/exa.h
820
exa/exa.h
|
@ -1,820 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Keith Packard
|
||||
* 2004 Eric Anholt
|
||||
* 2005 Zack Rusin
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of copyright holders not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Copyright holders make no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This is the header containing the public API of EXA for exa drivers.
|
||||
*/
|
||||
|
||||
#ifndef EXA_H
|
||||
#define EXA_H
|
||||
|
||||
#include "scrnintstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "gcstruct.h"
|
||||
#include "picturestr.h"
|
||||
#include "fb.h"
|
||||
|
||||
#define EXA_VERSION_MAJOR 2
|
||||
#define EXA_VERSION_MINOR 6
|
||||
#define EXA_VERSION_RELEASE 0
|
||||
|
||||
typedef struct _ExaOffscreenArea ExaOffscreenArea;
|
||||
|
||||
typedef void (*ExaOffscreenSaveProc) (ScreenPtr pScreen,
|
||||
ExaOffscreenArea * area);
|
||||
|
||||
typedef enum _ExaOffscreenState {
|
||||
ExaOffscreenAvail,
|
||||
ExaOffscreenRemovable,
|
||||
ExaOffscreenLocked
|
||||
} ExaOffscreenState;
|
||||
|
||||
struct _ExaOffscreenArea {
|
||||
int base_offset; /* allocation base */
|
||||
int offset; /* aligned offset */
|
||||
int size; /* total allocation size */
|
||||
unsigned last_use;
|
||||
void *privData;
|
||||
|
||||
ExaOffscreenSaveProc save;
|
||||
|
||||
ExaOffscreenState state;
|
||||
|
||||
ExaOffscreenArea *next;
|
||||
|
||||
unsigned eviction_cost;
|
||||
|
||||
ExaOffscreenArea *prev; /* Double-linked list for defragmentation */
|
||||
int align; /* required alignment */
|
||||
};
|
||||
|
||||
/**
|
||||
* The ExaDriver structure is allocated through exaDriverAlloc(), and then
|
||||
* fllled in by drivers.
|
||||
*/
|
||||
typedef struct _ExaDriver {
|
||||
/**
|
||||
* exa_major and exa_minor should be set by the driver to the version of
|
||||
* EXA which the driver was compiled for (or configures itself at runtime
|
||||
* to support). This allows EXA to extend the structure for new features
|
||||
* without breaking ABI for drivers compiled against older versions.
|
||||
*/
|
||||
int exa_major, exa_minor;
|
||||
|
||||
/**
|
||||
* memoryBase is the address of the beginning of framebuffer memory.
|
||||
* The visible screen should be within memoryBase to memoryBase +
|
||||
* memorySize.
|
||||
*/
|
||||
CARD8 *memoryBase;
|
||||
|
||||
/**
|
||||
* offScreenBase is the offset from memoryBase of the beginning of the area
|
||||
* to be managed by EXA's linear offscreen memory manager.
|
||||
*
|
||||
* In XFree86 DDX drivers, this is probably:
|
||||
* (pScrn->displayWidth * cpp * pScrn->virtualY)
|
||||
*/
|
||||
unsigned long offScreenBase;
|
||||
|
||||
/**
|
||||
* memorySize is the length (in bytes) of framebuffer memory beginning
|
||||
* from memoryBase.
|
||||
*
|
||||
* The offscreen memory manager will manage the area beginning at
|
||||
* (memoryBase + offScreenBase), with a length of (memorySize -
|
||||
* offScreenBase)
|
||||
*
|
||||
* In XFree86 DDX drivers, this is probably (pScrn->videoRam * 1024)
|
||||
*/
|
||||
unsigned long memorySize;
|
||||
|
||||
/**
|
||||
* pixmapOffsetAlign is the byte alignment necessary for pixmap offsets
|
||||
* within framebuffer.
|
||||
*
|
||||
* Hardware typically has a required alignment of offsets, which may or may
|
||||
* not be a power of two. EXA will ensure that pixmaps managed by the
|
||||
* offscreen memory manager meet this alignment requirement.
|
||||
*/
|
||||
int pixmapOffsetAlign;
|
||||
|
||||
/**
|
||||
* pixmapPitchAlign is the byte alignment necessary for pixmap pitches
|
||||
* within the framebuffer.
|
||||
*
|
||||
* Hardware typically has a required alignment of pitches for acceleration.
|
||||
* For 3D hardware, Composite acceleration often requires that source and
|
||||
* mask pixmaps (textures) have a power-of-two pitch, which can be demanded
|
||||
* using EXA_OFFSCREEN_ALIGN_POT. These pitch requirements only apply to
|
||||
* pixmaps managed by the offscreen memory manager. Thus, it is up to the
|
||||
* driver to ensure that the visible screen has an appropriate pitch for
|
||||
* acceleration.
|
||||
*/
|
||||
int pixmapPitchAlign;
|
||||
|
||||
/**
|
||||
* The flags field is bitfield of boolean values controlling EXA's behavior.
|
||||
*
|
||||
* The flags include EXA_OFFSCREEN_PIXMAPS, EXA_OFFSCREEN_ALIGN_POT, and
|
||||
* EXA_TWO_BITBLT_DIRECTIONS.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
/** @{ */
|
||||
/**
|
||||
* maxX controls the X coordinate limitation for rendering from the card.
|
||||
* The driver should never receive a request for rendering beyond maxX
|
||||
* in the X direction from the origin of a pixmap.
|
||||
*/
|
||||
int maxX;
|
||||
|
||||
/**
|
||||
* maxY controls the Y coordinate limitation for rendering from the card.
|
||||
* The driver should never receive a request for rendering beyond maxY
|
||||
* in the Y direction from the origin of a pixmap.
|
||||
*/
|
||||
int maxY;
|
||||
/** @} */
|
||||
|
||||
/* private */
|
||||
ExaOffscreenArea *offScreenAreas;
|
||||
Bool needsSync;
|
||||
int lastMarker;
|
||||
|
||||
/** @name Solid
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* PrepareSolid() sets up the driver for doing a solid fill.
|
||||
* @param pPixmap Destination pixmap
|
||||
* @param alu raster operation
|
||||
* @param planemask write mask for the fill
|
||||
* @param fg "foreground" color for the fill
|
||||
*
|
||||
* This call should set up the driver for doing a series of solid fills
|
||||
* through the Solid() call. The alu raster op is one of the GX*
|
||||
* graphics functions listed in X.h, and typically maps to a similar
|
||||
* single-byte "ROP" setting in all hardware. The planemask controls
|
||||
* which bits of the destination should be affected, and will only represent
|
||||
* the bits up to the depth of pPixmap. The fg is the pixel value of the
|
||||
* foreground color referred to in ROP descriptions.
|
||||
*
|
||||
* Note that many drivers will need to store some of the data in the driver
|
||||
* private record, for sending to the hardware with each drawing command.
|
||||
*
|
||||
* The PrepareSolid() call is required of all drivers, but it may fail for any
|
||||
* reason. Failure results in a fallback to software rendering.
|
||||
*/
|
||||
Bool (*PrepareSolid) (PixmapPtr pPixmap,
|
||||
int alu, Pixel planemask, Pixel fg);
|
||||
|
||||
/**
|
||||
* Solid() performs a solid fill set up in the last PrepareSolid() call.
|
||||
*
|
||||
* @param pPixmap destination pixmap
|
||||
* @param x1 left coordinate
|
||||
* @param y1 top coordinate
|
||||
* @param x2 right coordinate
|
||||
* @param y2 bottom coordinate
|
||||
*
|
||||
* Performs the fill set up by the last PrepareSolid() call, covering the
|
||||
* area from (x1,y1) to (x2,y2) in pPixmap. Note that the coordinates are
|
||||
* in the coordinate space of the destination pixmap, so the driver will
|
||||
* need to set up the hardware's offset and pitch for the destination
|
||||
* coordinates according to the pixmap's offset and pitch within
|
||||
* framebuffer. This likely means using exaGetPixmapOffset() and
|
||||
* exaGetPixmapPitch().
|
||||
*
|
||||
* This call is required if PrepareSolid() ever succeeds.
|
||||
*/
|
||||
void (*Solid) (PixmapPtr pPixmap, int x1, int y1, int x2, int y2);
|
||||
|
||||
/**
|
||||
* DoneSolid() finishes a set of solid fills.
|
||||
*
|
||||
* @param pPixmap destination pixmap.
|
||||
*
|
||||
* The DoneSolid() call is called at the end of a series of consecutive
|
||||
* Solid() calls following a successful PrepareSolid(). This allows drivers
|
||||
* to finish up emitting drawing commands that were buffered, or clean up
|
||||
* state from PrepareSolid().
|
||||
*
|
||||
* This call is required if PrepareSolid() ever succeeds.
|
||||
*/
|
||||
void (*DoneSolid) (PixmapPtr pPixmap);
|
||||
/** @} */
|
||||
|
||||
/** @name Copy
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* PrepareCopy() sets up the driver for doing a copy within video
|
||||
* memory.
|
||||
*
|
||||
* @param pSrcPixmap source pixmap
|
||||
* @param pDstPixmap destination pixmap
|
||||
* @param dx X copy direction
|
||||
* @param dy Y copy direction
|
||||
* @param alu raster operation
|
||||
* @param planemask write mask for the fill
|
||||
*
|
||||
* This call should set up the driver for doing a series of copies from the
|
||||
* the pSrcPixmap to the pDstPixmap. The dx flag will be positive if the
|
||||
* hardware should do the copy from the left to the right, and dy will be
|
||||
* positive if the copy should be done from the top to the bottom. This
|
||||
* is to deal with self-overlapping copies when pSrcPixmap == pDstPixmap.
|
||||
* If your hardware can only support blits that are (left to right, top to
|
||||
* bottom) or (right to left, bottom to top), then you should set
|
||||
* #EXA_TWO_BITBLT_DIRECTIONS, and EXA will break down Copy operations to
|
||||
* ones that meet those requirements. The alu raster op is one of the GX*
|
||||
* graphics functions listed in X.h, and typically maps to a similar
|
||||
* single-byte "ROP" setting in all hardware. The planemask controls which
|
||||
* bits of the destination should be affected, and will only represent the
|
||||
* bits up to the depth of pPixmap.
|
||||
*
|
||||
* Note that many drivers will need to store some of the data in the driver
|
||||
* private record, for sending to the hardware with each drawing command.
|
||||
*
|
||||
* The PrepareCopy() call is required of all drivers, but it may fail for any
|
||||
* reason. Failure results in a fallback to software rendering.
|
||||
*/
|
||||
Bool (*PrepareCopy) (PixmapPtr pSrcPixmap,
|
||||
PixmapPtr pDstPixmap,
|
||||
int dx, int dy, int alu, Pixel planemask);
|
||||
|
||||
/**
|
||||
* Copy() performs a copy set up in the last PrepareCopy call.
|
||||
*
|
||||
* @param pDstPixmap destination pixmap
|
||||
* @param srcX source X coordinate
|
||||
* @param srcY source Y coordinate
|
||||
* @param dstX destination X coordinate
|
||||
* @param dstY destination Y coordinate
|
||||
* @param width width of the rectangle to be copied
|
||||
* @param height height of the rectangle to be copied.
|
||||
*
|
||||
* Performs the copy set up by the last PrepareCopy() call, copying the
|
||||
* rectangle from (srcX, srcY) to (srcX + width, srcY + width) in the source
|
||||
* pixmap to the same-sized rectangle at (dstX, dstY) in the destination
|
||||
* pixmap. Those rectangles may overlap in memory, if
|
||||
* pSrcPixmap == pDstPixmap. Note that this call does not receive the
|
||||
* pSrcPixmap as an argument -- if it's needed in this function, it should
|
||||
* be stored in the driver private during PrepareCopy(). As with Solid(),
|
||||
* the coordinates are in the coordinate space of each pixmap, so the driver
|
||||
* will need to set up source and destination pitches and offsets from those
|
||||
* pixmaps, probably using exaGetPixmapOffset() and exaGetPixmapPitch().
|
||||
*
|
||||
* This call is required if PrepareCopy ever succeeds.
|
||||
*/
|
||||
void (*Copy) (PixmapPtr pDstPixmap,
|
||||
int srcX,
|
||||
int srcY, int dstX, int dstY, int width, int height);
|
||||
|
||||
/**
|
||||
* DoneCopy() finishes a set of copies.
|
||||
*
|
||||
* @param pPixmap destination pixmap.
|
||||
*
|
||||
* The DoneCopy() call is called at the end of a series of consecutive
|
||||
* Copy() calls following a successful PrepareCopy(). This allows drivers
|
||||
* to finish up emitting drawing commands that were buffered, or clean up
|
||||
* state from PrepareCopy().
|
||||
*
|
||||
* This call is required if PrepareCopy() ever succeeds.
|
||||
*/
|
||||
void (*DoneCopy) (PixmapPtr pDstPixmap);
|
||||
/** @} */
|
||||
|
||||
/** @name Composite
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* CheckComposite() checks to see if a composite operation could be
|
||||
* accelerated.
|
||||
*
|
||||
* @param op Render operation
|
||||
* @param pSrcPicture source Picture
|
||||
* @param pMaskPicture mask picture
|
||||
* @param pDstPicture destination Picture
|
||||
*
|
||||
* The CheckComposite() call checks if the driver could handle acceleration
|
||||
* of op with the given source, mask, and destination pictures. This allows
|
||||
* drivers to check source and destination formats, supported operations,
|
||||
* transformations, and component alpha state, and send operations it can't
|
||||
* support to software rendering early on. This avoids costly pixmap
|
||||
* migration to the wrong places when the driver can't accelerate
|
||||
* operations. Note that because migration hasn't happened, the driver
|
||||
* can't know during CheckComposite() what the offsets and pitches of the
|
||||
* pixmaps are going to be.
|
||||
*
|
||||
* See PrepareComposite() for more details on likely issues that drivers
|
||||
* will have in accelerating Composite operations.
|
||||
*
|
||||
* The CheckComposite() call is recommended if PrepareComposite() is
|
||||
* implemented, but is not required.
|
||||
*/
|
||||
Bool (*CheckComposite) (int op,
|
||||
PicturePtr pSrcPicture,
|
||||
PicturePtr pMaskPicture, PicturePtr pDstPicture);
|
||||
|
||||
/**
|
||||
* PrepareComposite() sets up the driver for doing a Composite operation
|
||||
* described in the Render extension protocol spec.
|
||||
*
|
||||
* @param op Render operation
|
||||
* @param pSrcPicture source Picture
|
||||
* @param pMaskPicture mask picture
|
||||
* @param pDstPicture destination Picture
|
||||
* @param pSrc source pixmap
|
||||
* @param pMask mask pixmap
|
||||
* @param pDst destination pixmap
|
||||
*
|
||||
* This call should set up the driver for doing a series of Composite
|
||||
* operations, as described in the Render protocol spec, with the given
|
||||
* pSrcPicture, pMaskPicture, and pDstPicture. The pSrc, pMask, and
|
||||
* pDst are the pixmaps containing the pixel data, and should be used for
|
||||
* setting the offset and pitch used for the coordinate spaces for each of
|
||||
* the Pictures.
|
||||
*
|
||||
* Notes on interpreting Picture structures:
|
||||
* - The Picture structures will always have a valid pDrawable.
|
||||
* - The Picture structures will never have alphaMap set.
|
||||
* - The mask Picture (and therefore pMask) may be NULL, in which case the
|
||||
* operation is simply src OP dst instead of src IN mask OP dst, and
|
||||
* mask coordinates should be ignored.
|
||||
* - pMarkPicture may have componentAlpha set, which greatly changes
|
||||
* the behavior of the Composite operation. componentAlpha has no effect
|
||||
* when set on pSrcPicture or pDstPicture.
|
||||
* - The source and mask Pictures may have a transformation set
|
||||
* (Picture->transform != NULL), which means that the source coordinates
|
||||
* should be transformed by that transformation, resulting in scaling,
|
||||
* rotation, etc. The PictureTransformPoint() call can transform
|
||||
* coordinates for you. Transforms have no effect on Pictures when used
|
||||
* as a destination.
|
||||
* - The source and mask pictures may have a filter set. PictFilterNearest
|
||||
* and PictFilterBilinear are defined in the Render protocol, but others
|
||||
* may be encountered, and must be handled correctly (usually by
|
||||
* PrepareComposite failing, and falling back to software). Filters have
|
||||
* no effect on Pictures when used as a destination.
|
||||
* - The source and mask Pictures may have repeating set, which must be
|
||||
* respected. Many chipsets will be unable to support repeating on
|
||||
* pixmaps that have a width or height that is not a power of two.
|
||||
*
|
||||
* If your hardware can't support source pictures (textures) with
|
||||
* non-power-of-two pitches, you should set #EXA_OFFSCREEN_ALIGN_POT.
|
||||
*
|
||||
* Note that many drivers will need to store some of the data in the driver
|
||||
* private record, for sending to the hardware with each drawing command.
|
||||
*
|
||||
* The PrepareComposite() call is not required. However, it is highly
|
||||
* recommended for performance of antialiased font rendering and performance
|
||||
* of cairo applications. Failure results in a fallback to software
|
||||
* rendering.
|
||||
*/
|
||||
Bool (*PrepareComposite) (int op,
|
||||
PicturePtr pSrcPicture,
|
||||
PicturePtr pMaskPicture,
|
||||
PicturePtr pDstPicture,
|
||||
PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst);
|
||||
|
||||
/**
|
||||
* Composite() performs a Composite operation set up in the last
|
||||
* PrepareComposite() call.
|
||||
*
|
||||
* @param pDstPixmap destination pixmap
|
||||
* @param srcX source X coordinate
|
||||
* @param srcY source Y coordinate
|
||||
* @param maskX source X coordinate
|
||||
* @param maskY source Y coordinate
|
||||
* @param dstX destination X coordinate
|
||||
* @param dstY destination Y coordinate
|
||||
* @param width destination rectangle width
|
||||
* @param height destination rectangle height
|
||||
*
|
||||
* Performs the Composite operation set up by the last PrepareComposite()
|
||||
* call, to the rectangle from (dstX, dstY) to (dstX + width, dstY + height)
|
||||
* in the destination Pixmap. Note that if a transformation was set on
|
||||
* the source or mask Pictures, the source rectangles may not be the same
|
||||
* size as the destination rectangles and filtering. Getting the coordinate
|
||||
* transformation right at the subpixel level can be tricky, and rendercheck
|
||||
* can test this for you.
|
||||
*
|
||||
* This call is required if PrepareComposite() ever succeeds.
|
||||
*/
|
||||
void (*Composite) (PixmapPtr pDst,
|
||||
int srcX,
|
||||
int srcY,
|
||||
int maskX,
|
||||
int maskY, int dstX, int dstY, int width, int height);
|
||||
|
||||
/**
|
||||
* DoneComposite() finishes a set of Composite operations.
|
||||
*
|
||||
* @param pPixmap destination pixmap.
|
||||
*
|
||||
* The DoneComposite() call is called at the end of a series of consecutive
|
||||
* Composite() calls following a successful PrepareComposite(). This allows
|
||||
* drivers to finish up emitting drawing commands that were buffered, or
|
||||
* clean up state from PrepareComposite().
|
||||
*
|
||||
* This call is required if PrepareComposite() ever succeeds.
|
||||
*/
|
||||
void (*DoneComposite) (PixmapPtr pDst);
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* UploadToScreen() loads a rectangle of data from src into pDst.
|
||||
*
|
||||
* @param pDst destination pixmap
|
||||
* @param x destination X coordinate.
|
||||
* @param y destination Y coordinate
|
||||
* @param width width of the rectangle to be copied
|
||||
* @param height height of the rectangle to be copied
|
||||
* @param src pointer to the beginning of the source data
|
||||
* @param src_pitch pitch (in bytes) of the lines of source data.
|
||||
*
|
||||
* UploadToScreen() copies data in system memory beginning at src (with
|
||||
* pitch src_pitch) into the destination pixmap from (x, y) to
|
||||
* (x + width, y + height). This is typically done with hostdata uploads,
|
||||
* where the CPU sets up a blit command on the hardware with instructions
|
||||
* that the blit data will be fed through some sort of aperture on the card.
|
||||
*
|
||||
* If UploadToScreen() is performed asynchronously, it is up to the driver
|
||||
* to call exaMarkSync(). This is in contrast to most other acceleration
|
||||
* calls in EXA.
|
||||
*
|
||||
* UploadToScreen() can aid in pixmap migration, but is most important for
|
||||
* the performance of exaGlyphs() (antialiased font drawing) by allowing
|
||||
* pipelining of data uploads, avoiding a sync of the card after each glyph.
|
||||
*
|
||||
* @return TRUE if the driver successfully uploaded the data. FALSE
|
||||
* indicates that EXA should fall back to doing the upload in software.
|
||||
*
|
||||
* UploadToScreen() is not required, but is recommended if Composite
|
||||
* acceleration is supported.
|
||||
*/
|
||||
Bool (*UploadToScreen) (PixmapPtr pDst,
|
||||
int x,
|
||||
int y, int w, int h, char *src, int src_pitch);
|
||||
|
||||
/**
|
||||
* UploadToScratch() is no longer used and will be removed next time the EXA
|
||||
* major version needs to be bumped.
|
||||
*/
|
||||
Bool (*UploadToScratch) (PixmapPtr pSrc, PixmapPtr pDst);
|
||||
|
||||
/**
|
||||
* DownloadFromScreen() loads a rectangle of data from pSrc into dst
|
||||
*
|
||||
* @param pSrc source pixmap
|
||||
* @param x source X coordinate.
|
||||
* @param y source Y coordinate
|
||||
* @param width width of the rectangle to be copied
|
||||
* @param height height of the rectangle to be copied
|
||||
* @param dst pointer to the beginning of the destination data
|
||||
* @param dst_pitch pitch (in bytes) of the lines of destination data.
|
||||
*
|
||||
* DownloadFromScreen() copies data from offscreen memory in pSrc from
|
||||
* (x, y) to (x + width, y + height), to system memory starting at
|
||||
* dst (with pitch dst_pitch). This would usually be done
|
||||
* using scatter-gather DMA, supported by a DRM call, or by blitting to AGP
|
||||
* and then synchronously reading from AGP. Because the implementation
|
||||
* might be synchronous, EXA leaves it up to the driver to call
|
||||
* exaMarkSync() if DownloadFromScreen() was asynchronous. This is in
|
||||
* contrast to most other acceleration calls in EXA.
|
||||
*
|
||||
* DownloadFromScreen() can aid in the largest bottleneck in pixmap
|
||||
* migration, which is the read from framebuffer when evicting pixmaps from
|
||||
* framebuffer memory. Thus, it is highly recommended, even though
|
||||
* implementations are typically complicated.
|
||||
*
|
||||
* @return TRUE if the driver successfully downloaded the data. FALSE
|
||||
* indicates that EXA should fall back to doing the download in software.
|
||||
*
|
||||
* DownloadFromScreen() is not required, but is highly recommended.
|
||||
*/
|
||||
Bool (*DownloadFromScreen) (PixmapPtr pSrc,
|
||||
int x, int y,
|
||||
int w, int h, char *dst, int dst_pitch);
|
||||
|
||||
/**
|
||||
* MarkSync() requests that the driver mark a synchronization point,
|
||||
* returning an driver-defined integer marker which could be requested for
|
||||
* synchronization to later in WaitMarker(). This might be used in the
|
||||
* future to avoid waiting for full hardware stalls before accessing pixmap
|
||||
* data with the CPU, but is not important in the current incarnation of
|
||||
* EXA.
|
||||
*
|
||||
* Note that drivers should call exaMarkSync() when they have done some
|
||||
* acceleration, rather than their own MarkSync() handler, as otherwise EXA
|
||||
* will be unaware of the driver's acceleration and not sync to it during
|
||||
* fallbacks.
|
||||
*
|
||||
* MarkSync() is optional.
|
||||
*/
|
||||
int (*MarkSync) (ScreenPtr pScreen);
|
||||
|
||||
/**
|
||||
* WaitMarker() waits for all rendering before the given marker to have
|
||||
* completed. If the driver does not implement MarkSync(), marker is
|
||||
* meaningless, and all rendering by the hardware should be completed before
|
||||
* WaitMarker() returns.
|
||||
*
|
||||
* Note that drivers should call exaWaitSync() to wait for all acceleration
|
||||
* to finish, as otherwise EXA will be unaware of the driver having
|
||||
* synchronized, resulting in excessive WaitMarker() calls.
|
||||
*
|
||||
* WaitMarker() is required of all drivers.
|
||||
*/
|
||||
void (*WaitMarker) (ScreenPtr pScreen, int marker);
|
||||
|
||||
/** @{ */
|
||||
/**
|
||||
* PrepareAccess() is called before CPU access to an offscreen pixmap.
|
||||
*
|
||||
* @param pPix the pixmap being accessed
|
||||
* @param index the index of the pixmap being accessed.
|
||||
*
|
||||
* PrepareAccess() will be called before CPU access to an offscreen pixmap.
|
||||
* This can be used to set up hardware surfaces for byteswapping or
|
||||
* untiling, or to adjust the pixmap's devPrivate.ptr for the purpose of
|
||||
* making CPU access use a different aperture.
|
||||
*
|
||||
* The index is one of #EXA_PREPARE_DEST, #EXA_PREPARE_SRC,
|
||||
* #EXA_PREPARE_MASK, #EXA_PREPARE_AUX_DEST, #EXA_PREPARE_AUX_SRC, or
|
||||
* #EXA_PREPARE_AUX_MASK. Since only up to #EXA_NUM_PREPARE_INDICES pixmaps
|
||||
* will have PrepareAccess() called on them per operation, drivers can have
|
||||
* a small, statically-allocated space to maintain state for PrepareAccess()
|
||||
* and FinishAccess() in. Note that PrepareAccess() is only called once per
|
||||
* pixmap and operation, regardless of whether the pixmap is used as a
|
||||
* destination and/or source, and the index may not reflect the usage.
|
||||
*
|
||||
* PrepareAccess() may fail. An example might be the case of hardware that
|
||||
* can set up 1 or 2 surfaces for CPU access, but not 3. If PrepareAccess()
|
||||
* fails, EXA will migrate the pixmap to system memory.
|
||||
* DownloadFromScreen() must be implemented and must not fail if a driver
|
||||
* wishes to fail in PrepareAccess(). PrepareAccess() must not fail when
|
||||
* pPix is the visible screen, because the visible screen can not be
|
||||
* migrated.
|
||||
*
|
||||
* @return TRUE if PrepareAccess() successfully prepared the pixmap for CPU
|
||||
* drawing.
|
||||
* @return FALSE if PrepareAccess() is unsuccessful and EXA should use
|
||||
* DownloadFromScreen() to migate the pixmap out.
|
||||
*/
|
||||
Bool (*PrepareAccess) (PixmapPtr pPix, int index);
|
||||
|
||||
/**
|
||||
* FinishAccess() is called after CPU access to an offscreen pixmap.
|
||||
*
|
||||
* @param pPix the pixmap being accessed
|
||||
* @param index the index of the pixmap being accessed.
|
||||
*
|
||||
* FinishAccess() will be called after finishing CPU access of an offscreen
|
||||
* pixmap set up by PrepareAccess(). Note that the FinishAccess() will not be
|
||||
* called if PrepareAccess() failed and the pixmap was migrated out.
|
||||
*/
|
||||
void (*FinishAccess) (PixmapPtr pPix, int index);
|
||||
|
||||
/**
|
||||
* PixmapIsOffscreen() is an optional driver replacement to
|
||||
* exaPixmapHasGpuCopy(). Set to NULL if you want the standard behaviour
|
||||
* of exaPixmapHasGpuCopy().
|
||||
*
|
||||
* @param pPix the pixmap
|
||||
* @return TRUE if the given drawable is in framebuffer memory.
|
||||
*
|
||||
* exaPixmapHasGpuCopy() is used to determine if a pixmap is in offscreen
|
||||
* memory, meaning that acceleration could probably be done to it, and that it
|
||||
* will need to be wrapped by PrepareAccess()/FinishAccess() when accessing it
|
||||
* with the CPU.
|
||||
*
|
||||
*
|
||||
*/
|
||||
Bool (*PixmapIsOffscreen) (PixmapPtr pPix);
|
||||
|
||||
/** @name PrepareAccess() and FinishAccess() indices
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* EXA_PREPARE_DEST is the index for a pixmap that may be drawn to or
|
||||
* read from.
|
||||
*/
|
||||
#define EXA_PREPARE_DEST 0
|
||||
/**
|
||||
* EXA_PREPARE_SRC is the index for a pixmap that may be read from
|
||||
*/
|
||||
#define EXA_PREPARE_SRC 1
|
||||
/**
|
||||
* EXA_PREPARE_SRC is the index for a second pixmap that may be read
|
||||
* from.
|
||||
*/
|
||||
#define EXA_PREPARE_MASK 2
|
||||
/**
|
||||
* EXA_PREPARE_AUX* are additional indices for other purposes, e.g.
|
||||
* separate alpha maps with Composite operations.
|
||||
*/
|
||||
#define EXA_PREPARE_AUX_DEST 3
|
||||
#define EXA_PREPARE_AUX_SRC 4
|
||||
#define EXA_PREPARE_AUX_MASK 5
|
||||
#define EXA_NUM_PREPARE_INDICES 6
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* maxPitchPixels controls the pitch limitation for rendering from
|
||||
* the card.
|
||||
* The driver should never receive a request for rendering a pixmap
|
||||
* that has a pitch (in pixels) beyond maxPitchPixels.
|
||||
*
|
||||
* Setting this field is optional -- if your hardware doesn't have
|
||||
* a pitch limitation in pixels, don't set this. If neither this value
|
||||
* nor maxPitchBytes is set, then maxPitchPixels is set to maxX.
|
||||
* If set, it must not be smaller than maxX.
|
||||
*
|
||||
* @sa maxPitchBytes
|
||||
*/
|
||||
int maxPitchPixels;
|
||||
|
||||
/**
|
||||
* maxPitchBytes controls the pitch limitation for rendering from
|
||||
* the card.
|
||||
* The driver should never receive a request for rendering a pixmap
|
||||
* that has a pitch (in bytes) beyond maxPitchBytes.
|
||||
*
|
||||
* Setting this field is optional -- if your hardware doesn't have
|
||||
* a pitch limitation in bytes, don't set this.
|
||||
* If set, it must not be smaller than maxX * 4.
|
||||
* There's no default value for maxPitchBytes.
|
||||
*
|
||||
* @sa maxPitchPixels
|
||||
*/
|
||||
int maxPitchBytes;
|
||||
|
||||
/* Hooks to allow driver to its own pixmap memory management */
|
||||
void *(*CreatePixmap) (ScreenPtr pScreen, int size, int align);
|
||||
void (*DestroyPixmap) (ScreenPtr pScreen, void *driverPriv);
|
||||
/**
|
||||
* Returning a pixmap with non-NULL devPrivate.ptr implies a pixmap which is
|
||||
* not offscreen, which will never be accelerated and Prepare/FinishAccess won't
|
||||
* be called.
|
||||
*/
|
||||
Bool (*ModifyPixmapHeader) (PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData);
|
||||
|
||||
/* hooks for drivers with tiling support:
|
||||
* driver MUST fill out new_fb_pitch with valid pitch of pixmap
|
||||
*/
|
||||
void *(*CreatePixmap2) (ScreenPtr pScreen, int width, int height,
|
||||
int depth, int usage_hint, int bitsPerPixel,
|
||||
int *new_fb_pitch);
|
||||
/** @} */
|
||||
Bool (*SharePixmapBacking)(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p);
|
||||
|
||||
Bool (*SetSharedPixmapBacking)(PixmapPtr pPixmap, void *handle);
|
||||
|
||||
} ExaDriverRec, *ExaDriverPtr;
|
||||
|
||||
/** @name EXA driver flags
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* EXA_OFFSCREEN_PIXMAPS indicates to EXA that the driver can support
|
||||
* offscreen pixmaps.
|
||||
*/
|
||||
#define EXA_OFFSCREEN_PIXMAPS (1 << 0)
|
||||
|
||||
/**
|
||||
* EXA_OFFSCREEN_ALIGN_POT indicates to EXA that the driver needs pixmaps
|
||||
* to have a power-of-two pitch.
|
||||
*/
|
||||
#define EXA_OFFSCREEN_ALIGN_POT (1 << 1)
|
||||
|
||||
/**
|
||||
* EXA_TWO_BITBLT_DIRECTIONS indicates to EXA that the driver can only
|
||||
* support copies that are (left-to-right, top-to-bottom) or
|
||||
* (right-to-left, bottom-to-top).
|
||||
*/
|
||||
#define EXA_TWO_BITBLT_DIRECTIONS (1 << 2)
|
||||
|
||||
/**
|
||||
* EXA_HANDLES_PIXMAPS indicates to EXA that the driver can handle
|
||||
* all pixmap addressing and migration.
|
||||
*/
|
||||
#define EXA_HANDLES_PIXMAPS (1 << 3)
|
||||
|
||||
/**
|
||||
* EXA_SUPPORTS_PREPARE_AUX indicates to EXA that the driver can handle the
|
||||
* EXA_PREPARE_AUX* indices in the Prepare/FinishAccess hooks. If there are no
|
||||
* such hooks, this flag has no effect.
|
||||
*/
|
||||
#define EXA_SUPPORTS_PREPARE_AUX (1 << 4)
|
||||
|
||||
/**
|
||||
* EXA_SUPPORTS_OFFSCREEN_OVERLAPS indicates to EXA that the driver Copy hooks
|
||||
* can handle the source and destination occupying overlapping offscreen memory
|
||||
* areas. This allows the offscreen memory defragmentation code to defragment
|
||||
* areas where the defragmented position overlaps the fragmented position.
|
||||
*
|
||||
* Typically this is supported by traditional 2D engines but not by 3D engines.
|
||||
*/
|
||||
#define EXA_SUPPORTS_OFFSCREEN_OVERLAPS (1 << 5)
|
||||
|
||||
/**
|
||||
* EXA_MIXED_PIXMAPS will hide unacceleratable pixmaps from drivers and manage the
|
||||
* problem known software fallbacks like trapezoids. This only migrates pixmaps one way
|
||||
* into a driver pixmap and then pins it.
|
||||
*/
|
||||
#define EXA_MIXED_PIXMAPS (1 << 6)
|
||||
|
||||
/** @} */
|
||||
|
||||
/* in exa.c */
|
||||
extern _X_EXPORT ExaDriverPtr exaDriverAlloc(void);
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
exaDriverInit(ScreenPtr pScreen, ExaDriverPtr pScreenInfo);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaDriverFini(ScreenPtr pScreen);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaMarkSync(ScreenPtr pScreen);
|
||||
extern _X_EXPORT void
|
||||
exaWaitSync(ScreenPtr pScreen);
|
||||
|
||||
extern _X_EXPORT unsigned long
|
||||
exaGetPixmapOffset(PixmapPtr pPix);
|
||||
|
||||
extern _X_EXPORT unsigned long
|
||||
exaGetPixmapPitch(PixmapPtr pPix);
|
||||
|
||||
extern _X_EXPORT unsigned long
|
||||
exaGetPixmapSize(PixmapPtr pPix);
|
||||
|
||||
extern _X_EXPORT void *exaGetPixmapDriverPrivate(PixmapPtr p);
|
||||
|
||||
/* in exa_offscreen.c */
|
||||
extern _X_EXPORT ExaOffscreenArea *exaOffscreenAlloc(ScreenPtr pScreen,
|
||||
int size, int align,
|
||||
Bool locked,
|
||||
ExaOffscreenSaveProc save,
|
||||
void *privData);
|
||||
|
||||
extern _X_EXPORT ExaOffscreenArea *exaOffscreenFree(ScreenPtr pScreen,
|
||||
ExaOffscreenArea * area);
|
||||
|
||||
extern _X_EXPORT void
|
||||
ExaOffscreenMarkUsed(PixmapPtr pPixmap);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaEnableDisableFBAccess(ScreenPtr pScreen, Bool enable);
|
||||
|
||||
extern _X_EXPORT Bool
|
||||
exaDrawableIsOffscreen(DrawablePtr pDrawable);
|
||||
|
||||
/* in exa.c */
|
||||
extern _X_EXPORT void
|
||||
exaMoveInPixmap(PixmapPtr pPixmap);
|
||||
|
||||
extern _X_EXPORT void
|
||||
exaMoveOutPixmap(PixmapPtr pPixmap);
|
||||
|
||||
/* in exa_unaccel.c */
|
||||
extern _X_EXPORT CARD32
|
||||
exaGetPixmapFirstPixel(PixmapPtr pPixmap);
|
||||
|
||||
/**
|
||||
* Returns TRUE if the given planemask covers all the significant bits in the
|
||||
* pixel values for pDrawable.
|
||||
*/
|
||||
#define EXA_PM_IS_SOLID(_pDrawable, _pm) \
|
||||
(((_pm) & FbFullMask((_pDrawable)->depth)) == \
|
||||
FbFullMask((_pDrawable)->depth))
|
||||
|
||||
#endif /* EXA_H */
|
1297
exa/exa_accel.c
1297
exa/exa_accel.c
File diff suppressed because it is too large
Load Diff
|
@ -1,265 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
/* This file holds the classic exa specific implementation. */
|
||||
|
||||
static _X_INLINE void *
|
||||
ExaGetPixmapAddress(PixmapPtr p)
|
||||
{
|
||||
ExaPixmapPriv(p);
|
||||
|
||||
if (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr)
|
||||
return pExaPixmap->fb_ptr;
|
||||
else
|
||||
return pExaPixmap->sys_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*
|
||||
* If width and height are 0, this won't be a full-fledged pixmap and it will
|
||||
* get ModifyPixmapHeader() called on it later. So, we mark it as pinned, because
|
||||
* ModifyPixmapHeader() would break migration. These types of pixmaps are used
|
||||
* for scratch pixmaps, or to represent the visible screen.
|
||||
*/
|
||||
PixmapPtr
|
||||
exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint)
|
||||
{
|
||||
PixmapPtr pPixmap;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
BoxRec box;
|
||||
int bpp;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (w > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
pPixmap = pScreen->CreatePixmap(pScreen, w, h, depth, usage_hint);
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
|
||||
if (!pPixmap)
|
||||
return NULL;
|
||||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
/* Scratch pixmaps may have w/h equal to zero, and may not be
|
||||
* migrated.
|
||||
*/
|
||||
if (!w || !h)
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
else
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
|
||||
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
|
||||
pExaPixmap->fb_size = pExaPixmap->fb_pitch * h;
|
||||
|
||||
if (pExaPixmap->fb_pitch > 131071) {
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set up damage tracking */
|
||||
pExaPixmap->pDamage = DamageCreate(NULL, NULL,
|
||||
DamageReportNone, TRUE,
|
||||
pScreen, pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage == NULL) {
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
|
||||
/* This ensures that pending damage reflects the current operation. */
|
||||
/* This is used by exa to optimize migration. */
|
||||
DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
/* We set the initial pixmap as completely valid for a simple reason.
|
||||
* Imagine a 1000x1000 pixmap, it has 1 million pixels, 250000 of which
|
||||
* could form single pixel rects as part of a region. Setting the complete region
|
||||
* as valid is a natural defragmentation of the region.
|
||||
*/
|
||||
box.x1 = 0;
|
||||
box.y1 = 0;
|
||||
box.x2 = w;
|
||||
box.y2 = h;
|
||||
RegionInit(&pExaPixmap->validSys, &box, 0);
|
||||
RegionInit(&pExaPixmap->validFB, &box, 0);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
/* During a fallback we must prepare access. */
|
||||
if (pExaScr->fallback_counter)
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
return pPixmap;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
ExaScreenPrivPtr pExaScr;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
Bool ret;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
pScreen = pPixmap->drawable.pScreen;
|
||||
pExaScr = ExaGetScreenPriv(pScreen);
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
if (pExaPixmap) {
|
||||
if (pPixData)
|
||||
pExaPixmap->sys_ptr = pPixData;
|
||||
|
||||
if (devKind > 0)
|
||||
pExaPixmap->sys_pitch = devKind;
|
||||
|
||||
/* Classic EXA:
|
||||
* - Framebuffer.
|
||||
* - Scratch pixmap with gpu memory.
|
||||
*/
|
||||
if (pExaScr->info->memoryBase && pPixData) {
|
||||
if ((CARD8 *) pPixData >= pExaScr->info->memoryBase &&
|
||||
((CARD8 *) pPixData - pExaScr->info->memoryBase) <
|
||||
pExaScr->info->memorySize) {
|
||||
pExaPixmap->fb_ptr = pPixData;
|
||||
pExaPixmap->fb_pitch = devKind;
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (width > 0 && height > 0 && bitsPerPixel > 0) {
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
}
|
||||
|
||||
/* Pixmaps subject to ModifyPixmapHeader will be pinned to system or
|
||||
* gpu memory, so there's no need to track damage.
|
||||
*/
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind, pPixData);
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
|
||||
/* Always NULL this, we don't want lingering pointers. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
if (pPixmap->refcnt == 1) {
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaDestroyPixmap(pPixmap);
|
||||
|
||||
if (pExaPixmap->area) {
|
||||
DBG_PIXMAP(("-- 0x%p (0x%x) (%dx%d)\n",
|
||||
(void *) pPixmap->drawable.id,
|
||||
ExaGetPixmapPriv(pPixmap)->area->offset,
|
||||
pPixmap->drawable.width, pPixmap->drawable.height));
|
||||
/* Free the offscreen area */
|
||||
exaOffscreenFree(pPixmap->drawable.pScreen, pExaPixmap->area);
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
}
|
||||
RegionUninit(&pExaPixmap->validSys);
|
||||
RegionUninit(&pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
ret = pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
Bool ret;
|
||||
|
||||
if (pExaScr->info->PixmapIsOffscreen) {
|
||||
void *old_ptr = pPixmap->devPrivate.ptr;
|
||||
|
||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
||||
ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
|
||||
pPixmap->devPrivate.ptr = old_ptr;
|
||||
}
|
||||
else
|
||||
ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
|
||||
|
||||
return ret;
|
||||
}
|
230
exa/exa_driver.c
230
exa/exa_driver.c
|
@ -1,230 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
/* This file holds the driver allocated pixmaps specific implementation. */
|
||||
|
||||
static _X_INLINE void *
|
||||
ExaGetPixmapAddress(PixmapPtr p)
|
||||
{
|
||||
ExaPixmapPriv(p);
|
||||
|
||||
return pExaPixmap->sys_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*
|
||||
* Pixmaps are always marked as pinned, because exa has no control over them.
|
||||
*/
|
||||
PixmapPtr
|
||||
exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint)
|
||||
{
|
||||
PixmapPtr pPixmap;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
int bpp;
|
||||
size_t paddedWidth, datasize;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (w > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
|
||||
if (!pPixmap)
|
||||
return NULL;
|
||||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
/* Set this before driver hooks, to allow for driver pixmaps without gpu
|
||||
* memory to back it. These pixmaps have a valid pointer at all times.
|
||||
*/
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
if (pExaScr->info->CreatePixmap2) {
|
||||
int new_pitch = 0;
|
||||
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
|
||||
&new_pitch);
|
||||
paddedWidth = pExaPixmap->fb_pitch = new_pitch;
|
||||
}
|
||||
else {
|
||||
paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
|
||||
if (paddedWidth / 4 > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
if (paddedWidth < pExaPixmap->fb_pitch)
|
||||
paddedWidth = pExaPixmap->fb_pitch;
|
||||
datasize = h * paddedWidth;
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap(pScreen, datasize, 0);
|
||||
}
|
||||
|
||||
if (!pExaPixmap->driverPriv) {
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allow ModifyPixmapHeader to set sys_ptr appropriately. */
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
|
||||
(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
|
||||
/* During a fallback we must prepare access. */
|
||||
if (pExaScr->fallback_counter)
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
return pPixmap;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
ExaScreenPrivPtr pExaScr;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
Bool ret;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
pScreen = pPixmap->drawable.pScreen;
|
||||
pExaScr = ExaGetScreenPriv(pScreen);
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
if (pExaPixmap) {
|
||||
if (pPixData)
|
||||
pExaPixmap->sys_ptr = pPixData;
|
||||
|
||||
if (devKind > 0)
|
||||
pExaPixmap->sys_pitch = devKind;
|
||||
|
||||
if (width > 0 && height > 0 && bitsPerPixel > 0) {
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
}
|
||||
}
|
||||
|
||||
if (pExaScr->info->ModifyPixmapHeader) {
|
||||
ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind,
|
||||
pPixData);
|
||||
/* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
|
||||
* If pPixmap->devPrivate.ptr is non-NULL, then we've got a
|
||||
* !has_gpu_copy pixmap. We need to store the pointer,
|
||||
* because PrepareAccess won't be called.
|
||||
*/
|
||||
if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
}
|
||||
if (ret == TRUE)
|
||||
goto out;
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind, pPixData);
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
|
||||
out:
|
||||
/* Always NULL this, we don't want lingering pointers. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_driver(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
if (pPixmap->refcnt == 1) {
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaDestroyPixmap(pPixmap);
|
||||
|
||||
if (pExaPixmap->driverPriv)
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
ret = pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
void *saved_ptr;
|
||||
Bool ret;
|
||||
|
||||
saved_ptr = pPixmap->devPrivate.ptr;
|
||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
||||
ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
|
||||
pPixmap->devPrivate.ptr = saved_ptr;
|
||||
|
||||
return ret;
|
||||
}
|
839
exa/exa_glyphs.c
839
exa/exa_glyphs.c
|
@ -1,839 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2008 Red Hat, Inc.
|
||||
* Partly based on code Copyright © 2000 SuSE, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Red Hat not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. Red Hat makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* Red Hat DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL Red Hat
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of SuSE not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. SuSE makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*
|
||||
* SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
|
||||
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Owen Taylor <otaylor@fishsoup.net>
|
||||
* Based on code by: Keith Packard
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
|
||||
#include "mipict.h"
|
||||
|
||||
#if DEBUG_GLYPH_CACHE
|
||||
#define DBG_GLYPH_CACHE(a) ErrorF a
|
||||
#else
|
||||
#define DBG_GLYPH_CACHE(a)
|
||||
#endif
|
||||
|
||||
/* Width of the pixmaps we use for the caches; this should be less than
|
||||
* max texture size of the driver; this may need to actually come from
|
||||
* the driver.
|
||||
*/
|
||||
#define CACHE_PICTURE_WIDTH 1024
|
||||
|
||||
/* Maximum number of glyphs we buffer on the stack before flushing
|
||||
* rendering to the mask or destination surface.
|
||||
*/
|
||||
#define GLYPH_BUFFER_SIZE 256
|
||||
|
||||
typedef struct {
|
||||
PicturePtr mask;
|
||||
ExaCompositeRectRec rects[GLYPH_BUFFER_SIZE];
|
||||
int count;
|
||||
} ExaGlyphBuffer, *ExaGlyphBufferPtr;
|
||||
|
||||
typedef enum {
|
||||
ExaGlyphSuccess, /* Glyph added to render buffer */
|
||||
ExaGlyphFail, /* out of memory, etc */
|
||||
ExaGlyphNeedFlush, /* would evict a glyph already in the buffer */
|
||||
} ExaGlyphCacheResult;
|
||||
|
||||
void
|
||||
exaGlyphsInit(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
int i = 0;
|
||||
|
||||
memset(pExaScr->glyphCaches, 0, sizeof(pExaScr->glyphCaches));
|
||||
|
||||
pExaScr->glyphCaches[i].format = PICT_a8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
16;
|
||||
i++;
|
||||
pExaScr->glyphCaches[i].format = PICT_a8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
32;
|
||||
i++;
|
||||
pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
16;
|
||||
i++;
|
||||
pExaScr->glyphCaches[i].format = PICT_a8r8g8b8;
|
||||
pExaScr->glyphCaches[i].glyphWidth = pExaScr->glyphCaches[i].glyphHeight =
|
||||
32;
|
||||
i++;
|
||||
|
||||
assert(i == EXA_NUM_GLYPH_CACHES);
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
pExaScr->glyphCaches[i].columns =
|
||||
CACHE_PICTURE_WIDTH / pExaScr->glyphCaches[i].glyphWidth;
|
||||
pExaScr->glyphCaches[i].size = 256;
|
||||
pExaScr->glyphCaches[i].hashSize = 557;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exaUnrealizeGlyphCaches(ScreenPtr pScreen, unsigned int format)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
|
||||
if (cache->format != format)
|
||||
continue;
|
||||
|
||||
if (cache->picture) {
|
||||
FreePicture((void *) cache->picture, (XID) 0);
|
||||
cache->picture = NULL;
|
||||
}
|
||||
|
||||
free(cache->hashEntries);
|
||||
cache->hashEntries = NULL;
|
||||
|
||||
free(cache->glyphs);
|
||||
cache->glyphs = NULL;
|
||||
cache->glyphCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
|
||||
|
||||
/* All caches for a single format share a single pixmap for glyph storage,
|
||||
* allowing mixing glyphs of different sizes without paying a penalty
|
||||
* for switching between mask pixmaps. (Note that for a size of font
|
||||
* right at the border between two sizes, we might be switching for almost
|
||||
* every glyph.)
|
||||
*
|
||||
* This function allocates the storage pixmap, and then fills in the
|
||||
* rest of the allocated structures for all caches with the given format.
|
||||
*/
|
||||
static Bool
|
||||
exaRealizeGlyphCaches(ScreenPtr pScreen, unsigned int format)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
int depth = PIXMAN_FORMAT_DEPTH(format);
|
||||
PictFormatPtr pPictFormat;
|
||||
PixmapPtr pPixmap;
|
||||
PicturePtr pPicture;
|
||||
CARD32 component_alpha;
|
||||
int height;
|
||||
int i;
|
||||
int error;
|
||||
|
||||
pPictFormat = PictureMatchFormat(pScreen, depth, format);
|
||||
if (!pPictFormat)
|
||||
return FALSE;
|
||||
|
||||
/* Compute the total vertical size needed for the format */
|
||||
|
||||
height = 0;
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
int rows;
|
||||
|
||||
if (cache->format != format)
|
||||
continue;
|
||||
|
||||
cache->yOffset = height;
|
||||
|
||||
rows = (cache->size + cache->columns - 1) / cache->columns;
|
||||
height += rows * cache->glyphHeight;
|
||||
}
|
||||
|
||||
/* Now allocate the pixmap and picture */
|
||||
pPixmap = (*pScreen->CreatePixmap) (pScreen,
|
||||
CACHE_PICTURE_WIDTH, height, depth, 0);
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
component_alpha = NeedsComponent(pPictFormat->format);
|
||||
pPicture = CreatePicture(0, &pPixmap->drawable, pPictFormat,
|
||||
CPComponentAlpha, &component_alpha, serverClient,
|
||||
&error);
|
||||
|
||||
(*pScreen->DestroyPixmap) (pPixmap); /* picture holds a refcount */
|
||||
|
||||
if (!pPicture)
|
||||
return FALSE;
|
||||
|
||||
/* And store the picture in all the caches for the format */
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
int j;
|
||||
|
||||
if (cache->format != format)
|
||||
continue;
|
||||
|
||||
cache->picture = pPicture;
|
||||
cache->picture->refcnt++;
|
||||
cache->hashEntries = xallocarray(cache->hashSize, sizeof(int));
|
||||
cache->glyphs = xallocarray(cache->size, sizeof(ExaCachedGlyphRec));
|
||||
cache->glyphCount = 0;
|
||||
|
||||
if (!cache->hashEntries || !cache->glyphs)
|
||||
goto bail;
|
||||
|
||||
for (j = 0; j < cache->hashSize; j++)
|
||||
cache->hashEntries[j] = -1;
|
||||
|
||||
cache->evictionPosition = rand() % cache->size;
|
||||
}
|
||||
|
||||
/* Each cache references the picture individually */
|
||||
FreePicture((void *) pPicture, (XID) 0);
|
||||
return TRUE;
|
||||
|
||||
bail:
|
||||
exaUnrealizeGlyphCaches(pScreen, format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
exaGlyphsFini(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
|
||||
if (cache->picture)
|
||||
exaUnrealizeGlyphCaches(pScreen, cache->format);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
exaGlyphCacheHashLookup(ExaGlyphCachePtr cache, GlyphPtr pGlyph)
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
|
||||
|
||||
while (TRUE) { /* hash table can never be full */
|
||||
int entryPos = cache->hashEntries[slot];
|
||||
|
||||
if (entryPos == -1)
|
||||
return -1;
|
||||
|
||||
if (memcmp
|
||||
(pGlyph->sha1, cache->glyphs[entryPos].sha1,
|
||||
sizeof(pGlyph->sha1)) == 0) {
|
||||
return entryPos;
|
||||
}
|
||||
|
||||
slot--;
|
||||
if (slot < 0)
|
||||
slot = cache->hashSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphCacheHashInsert(ExaGlyphCachePtr cache, GlyphPtr pGlyph, int pos)
|
||||
{
|
||||
int slot;
|
||||
|
||||
memcpy(cache->glyphs[pos].sha1, pGlyph->sha1, sizeof(pGlyph->sha1));
|
||||
|
||||
slot = (*(CARD32 *) pGlyph->sha1) % cache->hashSize;
|
||||
|
||||
while (TRUE) { /* hash table can never be full */
|
||||
if (cache->hashEntries[slot] == -1) {
|
||||
cache->hashEntries[slot] = pos;
|
||||
return;
|
||||
}
|
||||
|
||||
slot--;
|
||||
if (slot < 0)
|
||||
slot = cache->hashSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphCacheHashRemove(ExaGlyphCachePtr cache, int pos)
|
||||
{
|
||||
int slot;
|
||||
int emptiedSlot = -1;
|
||||
|
||||
slot = (*(CARD32 *) cache->glyphs[pos].sha1) % cache->hashSize;
|
||||
|
||||
while (TRUE) { /* hash table can never be full */
|
||||
int entryPos = cache->hashEntries[slot];
|
||||
|
||||
if (entryPos == -1)
|
||||
return;
|
||||
|
||||
if (entryPos == pos) {
|
||||
cache->hashEntries[slot] = -1;
|
||||
emptiedSlot = slot;
|
||||
}
|
||||
else if (emptiedSlot != -1) {
|
||||
/* See if we can move this entry into the emptied slot, we can't
|
||||
* do that if if entry would have hashed between the current position
|
||||
* and the emptied slot. (taking wrapping into account). Bad positions
|
||||
* are:
|
||||
*
|
||||
* | XXXXXXXXXX |
|
||||
* i j
|
||||
*
|
||||
* |XXX XXXX|
|
||||
* j i
|
||||
*
|
||||
* i - slot, j - emptiedSlot
|
||||
*
|
||||
* (Knuth 6.4R)
|
||||
*/
|
||||
|
||||
int entrySlot =
|
||||
(*(CARD32 *) cache->glyphs[entryPos].sha1) % cache->hashSize;
|
||||
|
||||
if (!((entrySlot >= slot && entrySlot < emptiedSlot) ||
|
||||
(emptiedSlot < slot &&
|
||||
(entrySlot < emptiedSlot || entrySlot >= slot)))) {
|
||||
cache->hashEntries[emptiedSlot] = entryPos;
|
||||
cache->hashEntries[slot] = -1;
|
||||
emptiedSlot = slot;
|
||||
}
|
||||
}
|
||||
|
||||
slot--;
|
||||
if (slot < 0)
|
||||
slot = cache->hashSize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define CACHE_X(pos) (((pos) % cache->columns) * cache->glyphWidth)
|
||||
#define CACHE_Y(pos) (cache->yOffset + ((pos) / cache->columns) * cache->glyphHeight)
|
||||
|
||||
/* The most efficient thing to way to upload the glyph to the screen
|
||||
* is to use the UploadToScreen() driver hook; this allows us to
|
||||
* pipeline glyph uploads and to avoid creating gpu backed pixmaps for
|
||||
* glyphs that we'll never use again.
|
||||
*
|
||||
* If we can't do it with UploadToScreen (because the glyph has a gpu copy,
|
||||
* etc), we fall back to CompositePicture.
|
||||
*
|
||||
* We need to damage the cache pixmap manually in either case because the damage
|
||||
* layer unwrapped the picture screen before calling exaGlyphs.
|
||||
*/
|
||||
static void
|
||||
exaGlyphCacheUploadGlyph(ScreenPtr pScreen,
|
||||
ExaGlyphCachePtr cache, int x, int y, GlyphPtr pGlyph)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
PicturePtr pGlyphPicture = GetGlyphPicture(pGlyph, pScreen);
|
||||
PixmapPtr pGlyphPixmap = (PixmapPtr) pGlyphPicture->pDrawable;
|
||||
|
||||
ExaPixmapPriv(pGlyphPixmap);
|
||||
PixmapPtr pCachePixmap = (PixmapPtr) cache->picture->pDrawable;
|
||||
|
||||
if (!pExaScr->info->UploadToScreen || pExaScr->swappedOut ||
|
||||
pExaPixmap->accel_blocked)
|
||||
goto composite;
|
||||
|
||||
/* If the glyph pixmap is already uploaded, no point in doing
|
||||
* things this way */
|
||||
if (exaPixmapHasGpuCopy(pGlyphPixmap))
|
||||
goto composite;
|
||||
|
||||
/* UploadToScreen only works if bpp match */
|
||||
if (pGlyphPixmap->drawable.bitsPerPixel !=
|
||||
pCachePixmap->drawable.bitsPerPixel)
|
||||
goto composite;
|
||||
|
||||
if (pExaScr->do_migration) {
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
/* cache pixmap must have a gpu copy. */
|
||||
pixmaps[0].as_dst = TRUE;
|
||||
pixmaps[0].as_src = FALSE;
|
||||
pixmaps[0].pPix = pCachePixmap;
|
||||
pixmaps[0].pReg = NULL;
|
||||
exaDoMigration(pixmaps, 1, TRUE);
|
||||
}
|
||||
|
||||
if (!exaPixmapHasGpuCopy(pCachePixmap))
|
||||
goto composite;
|
||||
|
||||
/* x,y are in pixmap coordinates, no need for cache{X,Y}off */
|
||||
if (pExaScr->info->UploadToScreen(pCachePixmap,
|
||||
x,
|
||||
y,
|
||||
pGlyph->info.width,
|
||||
pGlyph->info.height,
|
||||
(char *) pExaPixmap->sys_ptr,
|
||||
pExaPixmap->sys_pitch))
|
||||
goto damage;
|
||||
|
||||
composite:
|
||||
CompositePicture(PictOpSrc,
|
||||
pGlyphPicture,
|
||||
None,
|
||||
cache->picture,
|
||||
0, 0, 0, 0, x, y, pGlyph->info.width, pGlyph->info.height);
|
||||
|
||||
damage:
|
||||
/* The cache pixmap isn't a window, so no need to offset coordinates. */
|
||||
exaPixmapDirty(pCachePixmap,
|
||||
x, y, x + cache->glyphWidth, y + cache->glyphHeight);
|
||||
}
|
||||
|
||||
static ExaGlyphCacheResult
|
||||
exaGlyphCacheBufferGlyph(ScreenPtr pScreen,
|
||||
ExaGlyphCachePtr cache,
|
||||
ExaGlyphBufferPtr buffer,
|
||||
GlyphPtr pGlyph,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst)
|
||||
{
|
||||
ExaCompositeRectPtr rect;
|
||||
int pos;
|
||||
int x, y;
|
||||
|
||||
if (buffer->mask && buffer->mask != cache->picture)
|
||||
return ExaGlyphNeedFlush;
|
||||
|
||||
if (!cache->picture) {
|
||||
if (!exaRealizeGlyphCaches(pScreen, cache->format))
|
||||
return ExaGlyphFail;
|
||||
}
|
||||
|
||||
DBG_GLYPH_CACHE(("(%d,%d,%s): buffering glyph %lx\n",
|
||||
cache->glyphWidth, cache->glyphHeight,
|
||||
cache->format == PICT_a8 ? "A" : "ARGB",
|
||||
(long) *(CARD32 *) pGlyph->sha1));
|
||||
|
||||
pos = exaGlyphCacheHashLookup(cache, pGlyph);
|
||||
if (pos != -1) {
|
||||
DBG_GLYPH_CACHE((" found existing glyph at %d\n", pos));
|
||||
x = CACHE_X(pos);
|
||||
y = CACHE_Y(pos);
|
||||
}
|
||||
else {
|
||||
if (cache->glyphCount < cache->size) {
|
||||
/* Space remaining; we fill from the start */
|
||||
pos = cache->glyphCount;
|
||||
x = CACHE_X(pos);
|
||||
y = CACHE_Y(pos);
|
||||
cache->glyphCount++;
|
||||
DBG_GLYPH_CACHE((" storing glyph in free space at %d\n", pos));
|
||||
|
||||
exaGlyphCacheHashInsert(cache, pGlyph, pos);
|
||||
|
||||
}
|
||||
else {
|
||||
/* Need to evict an entry. We have to see if any glyphs
|
||||
* already in the output buffer were at this position in
|
||||
* the cache
|
||||
*/
|
||||
pos = cache->evictionPosition;
|
||||
x = CACHE_X(pos);
|
||||
y = CACHE_Y(pos);
|
||||
DBG_GLYPH_CACHE((" evicting glyph at %d\n", pos));
|
||||
if (buffer->count) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < buffer->count; i++) {
|
||||
if (pSrc ?
|
||||
(buffer->rects[i].xMask == x &&
|
||||
buffer->rects[i].yMask ==
|
||||
y) : (buffer->rects[i].xSrc == x &&
|
||||
buffer->rects[i].ySrc == y)) {
|
||||
DBG_GLYPH_CACHE((" must flush buffer\n"));
|
||||
return ExaGlyphNeedFlush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* OK, we're all set, swap in the new glyph */
|
||||
exaGlyphCacheHashRemove(cache, pos);
|
||||
exaGlyphCacheHashInsert(cache, pGlyph, pos);
|
||||
|
||||
/* And pick a new eviction position */
|
||||
cache->evictionPosition = rand() % cache->size;
|
||||
}
|
||||
|
||||
exaGlyphCacheUploadGlyph(pScreen, cache, x, y, pGlyph);
|
||||
}
|
||||
|
||||
buffer->mask = cache->picture;
|
||||
|
||||
rect = &buffer->rects[buffer->count];
|
||||
|
||||
if (pSrc) {
|
||||
rect->xSrc = xSrc;
|
||||
rect->ySrc = ySrc;
|
||||
rect->xMask = x;
|
||||
rect->yMask = y;
|
||||
}
|
||||
else {
|
||||
rect->xSrc = x;
|
||||
rect->ySrc = y;
|
||||
rect->xMask = 0;
|
||||
rect->yMask = 0;
|
||||
}
|
||||
|
||||
rect->pDst = pDst;
|
||||
rect->xDst = xDst;
|
||||
rect->yDst = yDst;
|
||||
rect->width = pGlyph->info.width;
|
||||
rect->height = pGlyph->info.height;
|
||||
|
||||
buffer->count++;
|
||||
|
||||
return ExaGlyphSuccess;
|
||||
}
|
||||
|
||||
#undef CACHE_X
|
||||
#undef CACHE_Y
|
||||
|
||||
static ExaGlyphCacheResult
|
||||
exaBufferGlyph(ScreenPtr pScreen,
|
||||
ExaGlyphBufferPtr buffer,
|
||||
GlyphPtr pGlyph,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
unsigned int format = (GetGlyphPicture(pGlyph, pScreen))->format;
|
||||
int width = pGlyph->info.width;
|
||||
int height = pGlyph->info.height;
|
||||
ExaCompositeRectPtr rect;
|
||||
PicturePtr mask;
|
||||
int i;
|
||||
|
||||
if (buffer->count == GLYPH_BUFFER_SIZE)
|
||||
return ExaGlyphNeedFlush;
|
||||
|
||||
if (PICT_FORMAT_BPP(format) == 1)
|
||||
format = PICT_a8;
|
||||
|
||||
for (i = 0; i < EXA_NUM_GLYPH_CACHES; i++) {
|
||||
ExaGlyphCachePtr cache = &pExaScr->glyphCaches[i];
|
||||
|
||||
if (format == cache->format &&
|
||||
width <= cache->glyphWidth && height <= cache->glyphHeight) {
|
||||
ExaGlyphCacheResult result = exaGlyphCacheBufferGlyph(pScreen,
|
||||
&pExaScr->
|
||||
glyphCaches
|
||||
[i],
|
||||
buffer,
|
||||
pGlyph,
|
||||
pSrc,
|
||||
pDst,
|
||||
xSrc, ySrc,
|
||||
xMask, yMask,
|
||||
xDst, yDst);
|
||||
|
||||
switch (result) {
|
||||
case ExaGlyphFail:
|
||||
break;
|
||||
case ExaGlyphSuccess:
|
||||
case ExaGlyphNeedFlush:
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Couldn't find the glyph in the cache, use the glyph picture directly */
|
||||
|
||||
mask = GetGlyphPicture(pGlyph, pScreen);
|
||||
if (buffer->mask && buffer->mask != mask)
|
||||
return ExaGlyphNeedFlush;
|
||||
|
||||
buffer->mask = mask;
|
||||
|
||||
rect = &buffer->rects[buffer->count];
|
||||
rect->xSrc = xSrc;
|
||||
rect->ySrc = ySrc;
|
||||
rect->xMask = xMask;
|
||||
rect->yMask = yMask;
|
||||
rect->xDst = xDst;
|
||||
rect->yDst = yDst;
|
||||
rect->width = width;
|
||||
rect->height = height;
|
||||
|
||||
buffer->count++;
|
||||
|
||||
return ExaGlyphSuccess;
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphsToMask(PicturePtr pMask, ExaGlyphBufferPtr buffer)
|
||||
{
|
||||
exaCompositeRects(PictOpAdd, buffer->mask, NULL, pMask,
|
||||
buffer->count, buffer->rects);
|
||||
|
||||
buffer->count = 0;
|
||||
buffer->mask = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
exaGlyphsToDst(CARD8 op, PicturePtr pSrc, PicturePtr pDst, ExaGlyphBufferPtr buffer)
|
||||
{
|
||||
exaCompositeRects(op, pSrc, buffer->mask, pDst, buffer->count,
|
||||
buffer->rects);
|
||||
|
||||
buffer->count = 0;
|
||||
buffer->mask = NULL;
|
||||
}
|
||||
|
||||
/* Cut and paste from render/glyph.c - probably should export it instead */
|
||||
static void
|
||||
GlyphExtents(int nlist, GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
int n;
|
||||
GlyphPtr glyph;
|
||||
int x, y;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
extents->x1 = MAXSHORT;
|
||||
extents->x2 = MINSHORT;
|
||||
extents->y1 = MAXSHORT;
|
||||
extents->y2 = MINSHORT;
|
||||
while (nlist--) {
|
||||
x += list->xOff;
|
||||
y += list->yOff;
|
||||
n = list->len;
|
||||
list++;
|
||||
while (n--) {
|
||||
glyph = *glyphs++;
|
||||
x1 = x - glyph->info.x;
|
||||
if (x1 < MINSHORT)
|
||||
x1 = MINSHORT;
|
||||
y1 = y - glyph->info.y;
|
||||
if (y1 < MINSHORT)
|
||||
y1 = MINSHORT;
|
||||
x2 = x1 + glyph->info.width;
|
||||
if (x2 > MAXSHORT)
|
||||
x2 = MAXSHORT;
|
||||
y2 = y1 + glyph->info.height;
|
||||
if (y2 > MAXSHORT)
|
||||
y2 = MAXSHORT;
|
||||
if (x1 < extents->x1)
|
||||
extents->x1 = x1;
|
||||
if (x2 > extents->x2)
|
||||
extents->x2 = x2;
|
||||
if (y1 < extents->y1)
|
||||
extents->y1 = y1;
|
||||
if (y2 > extents->y2)
|
||||
extents->y2 = y2;
|
||||
x += glyph->info.xOff;
|
||||
y += glyph->info.yOff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
|
||||
{
|
||||
PixmapPtr pMaskPixmap = 0;
|
||||
PicturePtr pMask = NULL;
|
||||
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
||||
int width = 0, height = 0;
|
||||
int x, y;
|
||||
int first_xOff = list->xOff, first_yOff = list->yOff;
|
||||
int n;
|
||||
GlyphPtr glyph;
|
||||
int error;
|
||||
BoxRec extents = { 0, 0, 0, 0 };
|
||||
CARD32 component_alpha;
|
||||
ExaGlyphBuffer buffer;
|
||||
|
||||
if (maskFormat) {
|
||||
ExaScreenPriv(pScreen);
|
||||
GCPtr pGC;
|
||||
xRectangle rect;
|
||||
|
||||
GlyphExtents(nlist, list, glyphs, &extents);
|
||||
|
||||
if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
|
||||
return;
|
||||
width = extents.x2 - extents.x1;
|
||||
height = extents.y2 - extents.y1;
|
||||
|
||||
if (maskFormat->depth == 1) {
|
||||
PictFormatPtr a8Format = PictureMatchFormat(pScreen, 8, PICT_a8);
|
||||
|
||||
if (a8Format)
|
||||
maskFormat = a8Format;
|
||||
}
|
||||
|
||||
pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
|
||||
maskFormat->depth,
|
||||
CREATE_PIXMAP_USAGE_SCRATCH);
|
||||
if (!pMaskPixmap)
|
||||
return;
|
||||
component_alpha = NeedsComponent(maskFormat->format);
|
||||
pMask = CreatePicture(0, &pMaskPixmap->drawable,
|
||||
maskFormat, CPComponentAlpha, &component_alpha,
|
||||
serverClient, &error);
|
||||
if (!pMask ||
|
||||
(!component_alpha && pExaScr->info->CheckComposite &&
|
||||
!(*pExaScr->info->CheckComposite) (PictOpAdd, pSrc, NULL, pMask)))
|
||||
{
|
||||
PictFormatPtr argbFormat;
|
||||
|
||||
(*pScreen->DestroyPixmap) (pMaskPixmap);
|
||||
|
||||
if (!pMask)
|
||||
return;
|
||||
|
||||
/* The driver can't seem to composite to a8, let's try argb (but
|
||||
* without component-alpha) */
|
||||
FreePicture((void *) pMask, (XID) 0);
|
||||
|
||||
argbFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
|
||||
|
||||
if (argbFormat)
|
||||
maskFormat = argbFormat;
|
||||
|
||||
pMaskPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
|
||||
maskFormat->depth,
|
||||
CREATE_PIXMAP_USAGE_SCRATCH);
|
||||
if (!pMaskPixmap)
|
||||
return;
|
||||
|
||||
pMask = CreatePicture(0, &pMaskPixmap->drawable, maskFormat, 0, 0,
|
||||
serverClient, &error);
|
||||
if (!pMask) {
|
||||
(*pScreen->DestroyPixmap) (pMaskPixmap);
|
||||
return;
|
||||
}
|
||||
}
|
||||
pGC = GetScratchGC(pMaskPixmap->drawable.depth, pScreen);
|
||||
ValidateGC(&pMaskPixmap->drawable, pGC);
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
(*pGC->ops->PolyFillRect) (&pMaskPixmap->drawable, pGC, 1, &rect);
|
||||
FreeScratchGC(pGC);
|
||||
x = -extents.x1;
|
||||
y = -extents.y1;
|
||||
}
|
||||
else {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
buffer.count = 0;
|
||||
buffer.mask = NULL;
|
||||
while (nlist--) {
|
||||
x += list->xOff;
|
||||
y += list->yOff;
|
||||
n = list->len;
|
||||
while (n--) {
|
||||
glyph = *glyphs++;
|
||||
|
||||
if (glyph->info.width > 0 && glyph->info.height > 0) {
|
||||
/* pGlyph->info.{x,y} compensate for empty space in the glyph. */
|
||||
if (maskFormat) {
|
||||
if (exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
|
||||
0, 0, 0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y) ==
|
||||
ExaGlyphNeedFlush) {
|
||||
exaGlyphsToMask(pMask, &buffer);
|
||||
exaBufferGlyph(pScreen, &buffer, glyph, NULL, pMask,
|
||||
0, 0, 0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
|
||||
xSrc + (x - glyph->info.x) - first_xOff,
|
||||
ySrc + (y - glyph->info.y) - first_yOff,
|
||||
0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y)
|
||||
== ExaGlyphNeedFlush) {
|
||||
exaGlyphsToDst(op, pSrc, pDst, &buffer);
|
||||
exaBufferGlyph(pScreen, &buffer, glyph, pSrc, pDst,
|
||||
xSrc + (x - glyph->info.x) - first_xOff,
|
||||
ySrc + (y - glyph->info.y) - first_yOff,
|
||||
0, 0, x - glyph->info.x,
|
||||
y - glyph->info.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x += glyph->info.xOff;
|
||||
y += glyph->info.yOff;
|
||||
}
|
||||
list++;
|
||||
}
|
||||
|
||||
if (buffer.count) {
|
||||
if (maskFormat)
|
||||
exaGlyphsToMask(pMask, &buffer);
|
||||
else
|
||||
exaGlyphsToDst(op, pSrc, pDst, &buffer);
|
||||
}
|
||||
|
||||
if (maskFormat) {
|
||||
x = extents.x1;
|
||||
y = extents.y1;
|
||||
CompositePicture(op,
|
||||
pSrc,
|
||||
pMask,
|
||||
pDst,
|
||||
xSrc + x - first_xOff,
|
||||
ySrc + y - first_yOff, 0, 0, x, y, width, height);
|
||||
FreePicture((void *) pMask, (XID) 0);
|
||||
(*pScreen->DestroyPixmap) (pMaskPixmap);
|
||||
}
|
||||
}
|
|
@ -1,761 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2006 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Authors:
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
* Michel Dänzer <michel@tungstengraphics.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
#if DEBUG_MIGRATE
|
||||
#define DBG_MIGRATE(a) ErrorF a
|
||||
#else
|
||||
#define DBG_MIGRATE(a)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The fallback path for UTS/DFS failing is to just memcpy. exaCopyDirtyToSys
|
||||
* and exaCopyDirtyToFb both needed to do this loop.
|
||||
*/
|
||||
static void
|
||||
exaMemcpyBox(PixmapPtr pPixmap, BoxPtr pbox, CARD8 *src, int src_pitch,
|
||||
CARD8 *dst, int dst_pitch)
|
||||
{
|
||||
int i, cpp = pPixmap->drawable.bitsPerPixel / 8;
|
||||
int bytes = (pbox->x2 - pbox->x1) * cpp;
|
||||
|
||||
src += pbox->y1 * src_pitch + pbox->x1 * cpp;
|
||||
dst += pbox->y1 * dst_pitch + pbox->x1 * cpp;
|
||||
|
||||
for (i = pbox->y2 - pbox->y1; i; i--) {
|
||||
memcpy(dst, src, bytes);
|
||||
src += src_pitch;
|
||||
dst += dst_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the pixmap is dirty (has been modified in its current
|
||||
* location compared to the other), or lacks a private for tracking
|
||||
* dirtiness.
|
||||
*/
|
||||
static Bool
|
||||
exaPixmapIsDirty(PixmapPtr pPix)
|
||||
{
|
||||
ExaPixmapPriv(pPix);
|
||||
|
||||
if (pExaPixmap == NULL)
|
||||
EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
|
||||
|
||||
if (!pExaPixmap->pDamage)
|
||||
return FALSE;
|
||||
|
||||
return RegionNotEmpty(DamageRegion(pExaPixmap->pDamage)) ||
|
||||
!RegionEqual(&pExaPixmap->validSys, &pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the pixmap is either pinned in FB, or has a sufficient score
|
||||
* to be considered "should be in framebuffer". That's just anything that has
|
||||
* had more acceleration than fallbacks, or has no score yet.
|
||||
*
|
||||
* Only valid if using a migration scheme that tracks score.
|
||||
*/
|
||||
static Bool
|
||||
exaPixmapShouldBeInFB(PixmapPtr pPix)
|
||||
{
|
||||
ExaPixmapPriv(pPix);
|
||||
|
||||
if (exaPixmapIsPinned(pPix))
|
||||
return TRUE;
|
||||
|
||||
return pExaPixmap->score >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* FB to system or vice versa. Both areas must be allocated.
|
||||
*/
|
||||
static void
|
||||
exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
|
||||
Bool (*transfer) (PixmapPtr pPix, int x, int y, int w, int h,
|
||||
char *sys, int sys_pitch), int fallback_index,
|
||||
void (*sync) (ScreenPtr pScreen))
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
RegionPtr damage = DamageRegion(pExaPixmap->pDamage);
|
||||
RegionRec CopyReg;
|
||||
Bool save_use_gpu_copy;
|
||||
int save_pitch;
|
||||
BoxPtr pBox;
|
||||
int nbox;
|
||||
Bool access_prepared = FALSE;
|
||||
Bool need_sync = FALSE;
|
||||
|
||||
/* Damaged bits are valid in current copy but invalid in other one */
|
||||
if (pExaPixmap->use_gpu_copy) {
|
||||
RegionUnion(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
|
||||
RegionSubtract(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
|
||||
}
|
||||
else {
|
||||
RegionUnion(&pExaPixmap->validSys, &pExaPixmap->validSys, damage);
|
||||
RegionSubtract(&pExaPixmap->validFB, &pExaPixmap->validFB, damage);
|
||||
}
|
||||
|
||||
RegionEmpty(damage);
|
||||
|
||||
/* Copy bits valid in source but not in destination */
|
||||
RegionNull(&CopyReg);
|
||||
RegionSubtract(&CopyReg, pValidSrc, pValidDst);
|
||||
|
||||
if (migrate->as_dst) {
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
/* XXX: The pending damage region will be marked as damaged after the
|
||||
* operation, so it should serve as an upper bound for the region that
|
||||
* needs to be synchronized for the operation. Unfortunately, this
|
||||
* causes corruption in some cases, e.g. when starting compiz. See
|
||||
* https://bugs.freedesktop.org/show_bug.cgi?id=12916 .
|
||||
*/
|
||||
if (pExaScr->optimize_migration) {
|
||||
RegionPtr pending_damage = DamagePendingRegion(pExaPixmap->pDamage);
|
||||
|
||||
#if DEBUG_MIGRATE
|
||||
if (RegionNil(pending_damage)) {
|
||||
static Bool firsttime = TRUE;
|
||||
|
||||
if (firsttime) {
|
||||
ErrorF("%s: Pending damage region empty!\n", __func__);
|
||||
firsttime = FALSE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Try to prevent destination valid region from growing too many
|
||||
* rects by filling it up to the extents of the union of the
|
||||
* destination valid region and the pending damage region.
|
||||
*/
|
||||
if (RegionNumRects(pValidDst) > 10) {
|
||||
BoxRec box;
|
||||
BoxPtr pValidExt, pDamageExt;
|
||||
RegionRec closure;
|
||||
|
||||
pValidExt = RegionExtents(pValidDst);
|
||||
pDamageExt = RegionExtents(pending_damage);
|
||||
|
||||
box.x1 = min(pValidExt->x1, pDamageExt->x1);
|
||||
box.y1 = min(pValidExt->y1, pDamageExt->y1);
|
||||
box.x2 = max(pValidExt->x2, pDamageExt->x2);
|
||||
box.y2 = max(pValidExt->y2, pDamageExt->y2);
|
||||
|
||||
RegionInit(&closure, &box, 0);
|
||||
RegionIntersect(&CopyReg, &CopyReg, &closure);
|
||||
}
|
||||
else
|
||||
RegionIntersect(&CopyReg, &CopyReg, pending_damage);
|
||||
}
|
||||
|
||||
/* The caller may provide a region to be subtracted from the calculated
|
||||
* dirty region. This is to avoid migration of bits that don't
|
||||
* contribute to the result of the operation.
|
||||
*/
|
||||
if (migrate->pReg)
|
||||
RegionSubtract(&CopyReg, &CopyReg, migrate->pReg);
|
||||
}
|
||||
else {
|
||||
/* The caller may restrict the region to be migrated for source pixmaps
|
||||
* to what's relevant for the operation.
|
||||
*/
|
||||
if (migrate->pReg)
|
||||
RegionIntersect(&CopyReg, &CopyReg, migrate->pReg);
|
||||
}
|
||||
|
||||
pBox = RegionRects(&CopyReg);
|
||||
nbox = RegionNumRects(&CopyReg);
|
||||
|
||||
save_use_gpu_copy = pExaPixmap->use_gpu_copy;
|
||||
save_pitch = pPixmap->devKind;
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
|
||||
while (nbox--) {
|
||||
pBox->x1 = max(pBox->x1, 0);
|
||||
pBox->y1 = max(pBox->y1, 0);
|
||||
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||
|
||||
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||
continue;
|
||||
|
||||
if (!transfer || !transfer(pPixmap,
|
||||
pBox->x1, pBox->y1,
|
||||
pBox->x2 - pBox->x1,
|
||||
pBox->y2 - pBox->y1,
|
||||
(char *) (pExaPixmap->sys_ptr
|
||||
+ pBox->y1 * pExaPixmap->sys_pitch
|
||||
+
|
||||
pBox->x1 *
|
||||
pPixmap->drawable.bitsPerPixel /
|
||||
8), pExaPixmap->sys_pitch)) {
|
||||
if (!access_prepared) {
|
||||
ExaDoPrepareAccess(pPixmap, fallback_index);
|
||||
access_prepared = TRUE;
|
||||
}
|
||||
if (fallback_index == EXA_PREPARE_DEST) {
|
||||
exaMemcpyBox(pPixmap, pBox,
|
||||
pExaPixmap->sys_ptr, pExaPixmap->sys_pitch,
|
||||
pPixmap->devPrivate.ptr, pPixmap->devKind);
|
||||
}
|
||||
else {
|
||||
exaMemcpyBox(pPixmap, pBox,
|
||||
pPixmap->devPrivate.ptr, pPixmap->devKind,
|
||||
pExaPixmap->sys_ptr, pExaPixmap->sys_pitch);
|
||||
}
|
||||
}
|
||||
else
|
||||
need_sync = TRUE;
|
||||
|
||||
pBox++;
|
||||
}
|
||||
|
||||
pExaPixmap->use_gpu_copy = save_use_gpu_copy;
|
||||
pPixmap->devKind = save_pitch;
|
||||
|
||||
/* Try to prevent source valid region from growing too many rects by
|
||||
* removing parts of it which are also in the destination valid region.
|
||||
* Removing anything beyond that would lead to data loss.
|
||||
*/
|
||||
if (RegionNumRects(pValidSrc) > 20)
|
||||
RegionSubtract(pValidSrc, pValidSrc, pValidDst);
|
||||
|
||||
/* The copied bits are now valid in destination */
|
||||
RegionUnion(pValidDst, pValidDst, &CopyReg);
|
||||
|
||||
RegionUninit(&CopyReg);
|
||||
|
||||
if (access_prepared)
|
||||
exaFinishAccess(&pPixmap->drawable, fallback_index);
|
||||
else if (need_sync && sync)
|
||||
sync(pPixmap->drawable.pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* the framebuffer memory copy to the system memory copy. Both areas must be
|
||||
* allocated.
|
||||
*/
|
||||
void
|
||||
exaCopyDirtyToSys(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaCopyDirty(migrate, &pExaPixmap->validSys, &pExaPixmap->validFB,
|
||||
pExaScr->info->DownloadFromScreen, EXA_PREPARE_SRC,
|
||||
exaWaitSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap is currently dirty, this copies at least the dirty area from
|
||||
* the system memory copy to the framebuffer memory copy. Both areas must be
|
||||
* allocated.
|
||||
*/
|
||||
void
|
||||
exaCopyDirtyToFb(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaCopyDirty(migrate, &pExaPixmap->validFB, &pExaPixmap->validSys,
|
||||
pExaScr->info->UploadToScreen, EXA_PREPARE_DEST, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a framebuffer copy of the pixmap if necessary, and then copies
|
||||
* any necessary pixmap data into the framebuffer copy and points the pixmap at
|
||||
* it.
|
||||
*
|
||||
* Note that when first allocated, a pixmap will have FALSE dirty flag.
|
||||
* This is intentional because pixmap data starts out undefined. So if we move
|
||||
* it in due to the first operation against it being accelerated, it will have
|
||||
* undefined framebuffer contents that we didn't have to upload. If we do
|
||||
* moveouts (and moveins) after the first movein, then we will only have to copy
|
||||
* back and forth if the pixmap was written to after the last synchronization of
|
||||
* the two copies. Then, at exaPixmapSave (when the framebuffer copy goes away)
|
||||
* we mark the pixmap dirty, so that the next exaMoveInPixmap will actually move
|
||||
* all the data, since it's almost surely all valid now.
|
||||
*/
|
||||
static void
|
||||
exaDoMoveInPixmap(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
/* If we're VT-switched away, no touching card memory allowed. */
|
||||
if (pExaScr->swappedOut)
|
||||
return;
|
||||
|
||||
/* If we're not allowed to move, then fail. */
|
||||
if (exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
/* Don't migrate in pixmaps which are less than 8bpp. This avoids a lot of
|
||||
* fragility in EXA, and <8bpp is probably not used enough any more to care
|
||||
* (at least, not in acceleratd paths).
|
||||
*/
|
||||
if (pPixmap->drawable.bitsPerPixel < 8)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->accel_blocked)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->area == NULL) {
|
||||
pExaPixmap->area =
|
||||
exaOffscreenAlloc(pScreen, pExaPixmap->fb_size,
|
||||
pExaScr->info->pixmapOffsetAlign, FALSE,
|
||||
exaPixmapSave, (void *) pPixmap);
|
||||
if (pExaPixmap->area == NULL)
|
||||
return;
|
||||
|
||||
pExaPixmap->fb_ptr = (CARD8 *) pExaScr->info->memoryBase +
|
||||
pExaPixmap->area->offset;
|
||||
}
|
||||
|
||||
exaCopyDirtyToFb(migrate);
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap))
|
||||
return;
|
||||
|
||||
DBG_MIGRATE(("-> %p (0x%x) (%dx%d) (%c)\n", pPixmap,
|
||||
(ExaGetPixmapPriv(pPixmap)->area ?
|
||||
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height,
|
||||
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
|
||||
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
|
||||
void
|
||||
exaMoveInPixmap_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
|
||||
.pReg = NULL
|
||||
};
|
||||
|
||||
migrate.pPix = pPixmap;
|
||||
exaDoMoveInPixmap(&migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the current active location of the pixmap to system memory, copying
|
||||
* updated data out if necessary.
|
||||
*/
|
||||
static void
|
||||
exaDoMoveOutPixmap(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
if (!pExaPixmap->area || exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
exaCopyDirtyToSys(migrate);
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap)) {
|
||||
|
||||
DBG_MIGRATE(("<- %p (%p) (%dx%d) (%c)\n", pPixmap,
|
||||
(void *) (ExaGetPixmapPriv(pPixmap)->area ?
|
||||
ExaGetPixmapPriv(pPixmap)->area->offset : 0),
|
||||
pPixmap->drawable.width,
|
||||
pPixmap->drawable.height,
|
||||
exaPixmapIsDirty(pPixmap) ? 'd' : 'c'));
|
||||
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaMoveOutPixmap_classic(PixmapPtr pPixmap)
|
||||
{
|
||||
static ExaMigrationRec migrate = {.as_dst = FALSE,.as_src = TRUE,
|
||||
.pReg = NULL
|
||||
};
|
||||
|
||||
migrate.pPix = pPixmap;
|
||||
exaDoMoveOutPixmap(&migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies out important pixmap data and removes references to framebuffer area.
|
||||
* Called when the memory manager decides it's time to kick the pixmap out of
|
||||
* framebuffer entirely.
|
||||
*/
|
||||
void
|
||||
exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area)
|
||||
{
|
||||
PixmapPtr pPixmap = area->privData;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaMoveOutPixmap(pPixmap);
|
||||
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->area = NULL;
|
||||
|
||||
/* Mark all FB bits as invalid, so all valid system bits get copied to FB
|
||||
* next time */
|
||||
RegionEmpty(&pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the "greedy" migration scheme, pushes the pixmap toward being located in
|
||||
* framebuffer memory.
|
||||
*/
|
||||
static void
|
||||
exaMigrateTowardFb(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
|
||||
DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
|
||||
(void *) pPixmap));
|
||||
return;
|
||||
}
|
||||
|
||||
DBG_MIGRATE(("UseScreen %p score %d\n",
|
||||
(void *) pPixmap, pExaPixmap->score));
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT) {
|
||||
exaDoMoveInPixmap(migrate);
|
||||
pExaPixmap->score = 0;
|
||||
}
|
||||
|
||||
if (pExaPixmap->score < EXA_PIXMAP_SCORE_MAX)
|
||||
pExaPixmap->score++;
|
||||
|
||||
if (pExaPixmap->score >= EXA_PIXMAP_SCORE_MOVE_IN &&
|
||||
!exaPixmapHasGpuCopy(pPixmap)) {
|
||||
exaDoMoveInPixmap(migrate);
|
||||
}
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap)) {
|
||||
exaCopyDirtyToFb(migrate);
|
||||
ExaOffscreenMarkUsed(pPixmap);
|
||||
}
|
||||
else
|
||||
exaCopyDirtyToSys(migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* For the "greedy" migration scheme, pushes the pixmap toward being located in
|
||||
* system memory.
|
||||
*/
|
||||
static void
|
||||
exaMigrateTowardSys(ExaMigrationPtr migrate)
|
||||
{
|
||||
PixmapPtr pPixmap = migrate->pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
DBG_MIGRATE(("UseMem: %p score %d\n", (void *) pPixmap,
|
||||
pExaPixmap->score));
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
|
||||
return;
|
||||
|
||||
if (pExaPixmap->score == EXA_PIXMAP_SCORE_INIT)
|
||||
pExaPixmap->score = 0;
|
||||
|
||||
if (pExaPixmap->score > EXA_PIXMAP_SCORE_MIN)
|
||||
pExaPixmap->score--;
|
||||
|
||||
if (pExaPixmap->score <= EXA_PIXMAP_SCORE_MOVE_OUT && pExaPixmap->area)
|
||||
exaDoMoveOutPixmap(migrate);
|
||||
|
||||
if (exaPixmapHasGpuCopy(pPixmap)) {
|
||||
exaCopyDirtyToFb(migrate);
|
||||
ExaOffscreenMarkUsed(pPixmap);
|
||||
}
|
||||
else
|
||||
exaCopyDirtyToSys(migrate);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the pixmap has both a framebuffer and system memory copy, this function
|
||||
* asserts that both of them are the same.
|
||||
*/
|
||||
static Bool
|
||||
exaAssertNotDirty(PixmapPtr pPixmap)
|
||||
{
|
||||
ExaPixmapPriv(pPixmap);
|
||||
CARD8 *dst, *src;
|
||||
RegionRec ValidReg;
|
||||
int dst_pitch, src_pitch, cpp, y, nbox, save_pitch;
|
||||
BoxPtr pBox;
|
||||
Bool ret = TRUE, save_use_gpu_copy;
|
||||
|
||||
if (exaPixmapIsPinned(pPixmap) || pExaPixmap->area == NULL)
|
||||
return ret;
|
||||
|
||||
RegionNull(&ValidReg);
|
||||
RegionIntersect(&ValidReg, &pExaPixmap->validFB, &pExaPixmap->validSys);
|
||||
nbox = RegionNumRects(&ValidReg);
|
||||
|
||||
if (!nbox)
|
||||
goto out;
|
||||
|
||||
pBox = RegionRects(&ValidReg);
|
||||
|
||||
dst_pitch = pExaPixmap->sys_pitch;
|
||||
src_pitch = pExaPixmap->fb_pitch;
|
||||
cpp = pPixmap->drawable.bitsPerPixel / 8;
|
||||
|
||||
save_use_gpu_copy = pExaPixmap->use_gpu_copy;
|
||||
save_pitch = pPixmap->devKind;
|
||||
pExaPixmap->use_gpu_copy = TRUE;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
|
||||
if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
|
||||
goto skip;
|
||||
|
||||
while (nbox--) {
|
||||
int rowbytes;
|
||||
|
||||
pBox->x1 = max(pBox->x1, 0);
|
||||
pBox->y1 = max(pBox->y1, 0);
|
||||
pBox->x2 = min(pBox->x2, pPixmap->drawable.width);
|
||||
pBox->y2 = min(pBox->y2, pPixmap->drawable.height);
|
||||
|
||||
if (pBox->x1 >= pBox->x2 || pBox->y1 >= pBox->y2)
|
||||
continue;
|
||||
|
||||
rowbytes = (pBox->x2 - pBox->x1) * cpp;
|
||||
src =
|
||||
(CARD8 *) pPixmap->devPrivate.ptr + pBox->y1 * src_pitch +
|
||||
pBox->x1 * cpp;
|
||||
dst = pExaPixmap->sys_ptr + pBox->y1 * dst_pitch + pBox->x1 * cpp;
|
||||
|
||||
for (y = pBox->y1; y < pBox->y2;
|
||||
y++, src += src_pitch, dst += dst_pitch) {
|
||||
if (memcmp(dst, src, rowbytes) != 0) {
|
||||
ret = FALSE;
|
||||
exaPixmapDirty(pPixmap, pBox->x1, pBox->y1, pBox->x2, pBox->y2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
skip:
|
||||
exaFinishAccess(&pPixmap->drawable, EXA_PREPARE_SRC);
|
||||
|
||||
pExaPixmap->use_gpu_copy = save_use_gpu_copy;
|
||||
pPixmap->devKind = save_pitch;
|
||||
|
||||
out:
|
||||
RegionUninit(&ValidReg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs migration of the pixmaps according to the operation information
|
||||
* provided in pixmaps and can_accel and the migration scheme chosen in the
|
||||
* config file.
|
||||
*/
|
||||
void
|
||||
exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
|
||||
{
|
||||
ScreenPtr pScreen = pixmaps[0].pPix->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
int i, j;
|
||||
|
||||
/* If this debugging flag is set, check each pixmap for whether it is marked
|
||||
* as clean, and if so, actually check if that's the case. This should help
|
||||
* catch issues with failing to mark a drawable as dirty. While it will
|
||||
* catch them late (after the operation happened), it at least explains what
|
||||
* went wrong, and instrumenting the code to find what operation happened
|
||||
* to the pixmap last shouldn't be hard.
|
||||
*/
|
||||
if (pExaScr->checkDirtyCorrectness) {
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (!exaPixmapIsDirty(pixmaps[i].pPix) &&
|
||||
!exaAssertNotDirty(pixmaps[i].pPix))
|
||||
ErrorF("%s: Pixmap %d dirty but not marked as such!\n",
|
||||
__func__, i);
|
||||
}
|
||||
}
|
||||
/* If anything is pinned in system memory, we won't be able to
|
||||
* accelerate.
|
||||
*/
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (exaPixmapIsPinned(pixmaps[i].pPix) &&
|
||||
!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
EXA_FALLBACK(("Pixmap %p (%dx%d) pinned in sys\n", pixmaps[i].pPix,
|
||||
pixmaps[i].pPix->drawable.width,
|
||||
pixmaps[i].pPix->drawable.height));
|
||||
can_accel = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (pExaScr->migration == ExaMigrationSmart) {
|
||||
/* If we've got something as a destination that we shouldn't cause to
|
||||
* become newly dirtied, take the unaccelerated route.
|
||||
*/
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (pixmaps[i].as_dst && !exaPixmapShouldBeInFB(pixmaps[i].pPix) &&
|
||||
!exaPixmapIsDirty(pixmaps[i].pPix)) {
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (!exaPixmapIsDirty(pixmaps[i].pPix))
|
||||
exaDoMoveOutPixmap(pixmaps + i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we aren't going to accelerate, then we migrate everybody toward
|
||||
* system memory, and kick out if it's free.
|
||||
*/
|
||||
if (!can_accel) {
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
exaMigrateTowardSys(pixmaps + i);
|
||||
if (!exaPixmapIsDirty(pixmaps[i].pPix))
|
||||
exaDoMoveOutPixmap(pixmaps + i);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Finally, the acceleration path. Move them all in. */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
exaMigrateTowardFb(pixmaps + i);
|
||||
exaDoMoveInPixmap(pixmaps + i);
|
||||
}
|
||||
}
|
||||
else if (pExaScr->migration == ExaMigrationGreedy) {
|
||||
/* If we can't accelerate, either because the driver can't or because one of
|
||||
* the pixmaps is pinned in system memory, then we migrate everybody toward
|
||||
* system memory.
|
||||
*
|
||||
* We also migrate toward system if all pixmaps involved are currently in
|
||||
* system memory -- this can mitigate thrashing when there are significantly
|
||||
* more pixmaps active than would fit in memory.
|
||||
*
|
||||
* If not, then we migrate toward FB so that hopefully acceleration can
|
||||
* happen.
|
||||
*/
|
||||
if (!can_accel) {
|
||||
for (i = 0; i < npixmaps; i++)
|
||||
exaMigrateTowardSys(pixmaps + i);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
/* Found one in FB, so move all to FB. */
|
||||
for (j = 0; j < npixmaps; j++)
|
||||
exaMigrateTowardFb(pixmaps + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nobody's in FB, so move all away from FB. */
|
||||
for (i = 0; i < npixmaps; i++)
|
||||
exaMigrateTowardSys(pixmaps + i);
|
||||
}
|
||||
else if (pExaScr->migration == ExaMigrationAlways) {
|
||||
/* Always move the pixmaps out if we can't accelerate. If we can
|
||||
* accelerate, try to move them all in. If that fails, then move them
|
||||
* back out.
|
||||
*/
|
||||
if (!can_accel) {
|
||||
for (i = 0; i < npixmaps; i++)
|
||||
exaDoMoveOutPixmap(pixmaps + i);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now, try to move them all into FB */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
exaDoMoveInPixmap(pixmaps + i);
|
||||
}
|
||||
|
||||
/* If we couldn't fit everything in, abort */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Yay, everything has a gpu copy, mark memory as used */
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
ExaOffscreenMarkUsed(pixmaps[i].pPix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
|
||||
{
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
|
||||
pixmaps[0].as_dst = TRUE;
|
||||
pixmaps[0].as_src = FALSE;
|
||||
}
|
||||
else {
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
}
|
||||
pixmaps[0].pPix = pPixmap;
|
||||
pixmaps[0].pReg = pReg;
|
||||
|
||||
exaDoMigration(pixmaps, 1, FALSE);
|
||||
|
||||
(void) ExaDoPrepareAccess(pPixmap, index);
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
void
|
||||
exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
|
||||
int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
|
||||
int usage_hint = pPixmap->usage_hint;
|
||||
int paddedWidth = pExaPixmap->sys_pitch;
|
||||
|
||||
/* Already done. */
|
||||
if (pExaPixmap->driverPriv)
|
||||
return;
|
||||
|
||||
if (exaPixmapIsPinned(pPixmap))
|
||||
return;
|
||||
|
||||
/* Can't accel 1/4 bpp. */
|
||||
if (pExaPixmap->accel_blocked || bpp < 8)
|
||||
return;
|
||||
|
||||
if (pExaScr->info->CreatePixmap2) {
|
||||
int new_pitch = 0;
|
||||
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap2(pScreen, w, h, depth, usage_hint, bpp,
|
||||
&new_pitch);
|
||||
paddedWidth = pExaPixmap->fb_pitch = new_pitch;
|
||||
}
|
||||
else {
|
||||
if (paddedWidth < pExaPixmap->fb_pitch)
|
||||
paddedWidth = pExaPixmap->fb_pitch;
|
||||
pExaPixmap->driverPriv =
|
||||
pExaScr->info->CreatePixmap(pScreen, paddedWidth * h, 0);
|
||||
}
|
||||
|
||||
if (!pExaPixmap->driverPriv)
|
||||
return;
|
||||
|
||||
(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* If anything is pinned in system memory, we won't be able to
|
||||
* accelerate.
|
||||
*/
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
if (exaPixmapIsPinned(pixmaps[i].pPix) &&
|
||||
!exaPixmapHasGpuCopy(pixmaps[i].pPix)) {
|
||||
can_accel = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* We can do nothing. */
|
||||
if (!can_accel)
|
||||
return;
|
||||
|
||||
for (i = 0; i < npixmaps; i++) {
|
||||
PixmapPtr pPixmap = pixmaps[i].pPix;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
if (!pExaPixmap->driverPriv)
|
||||
exaCreateDriverPixmap_mixed(pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage && exaPixmapHasGpuCopy(pPixmap)) {
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
/* This pitch is needed for proper acceleration. For some reason
|
||||
* there are pixmaps without pDamage and a bad fb_pitch value.
|
||||
* So setting devKind when only exaPixmapHasGpuCopy() is true
|
||||
* causes corruption. Pixmaps without pDamage are not migrated
|
||||
* and should have a valid devKind at all times, so that's why this
|
||||
* isn't causing problems. Pixmaps have their gpu pitch set the
|
||||
* first time in the MPH call from exaCreateDriverPixmap_mixed().
|
||||
*/
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
exaCopyDirtyToFb(pixmaps + i);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap == pPixmap &&
|
||||
!pixmaps[i].as_dst && !pixmaps[i].pReg)
|
||||
pExaScr->deferred_mixed_pixmap = NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exaMoveInPixmap_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
pixmaps[0].pPix = pPixmap;
|
||||
pixmaps[0].pReg = NULL;
|
||||
|
||||
exaDoMigration(pixmaps, 1, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure)
|
||||
{
|
||||
PixmapPtr pPixmap = closure;
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
/* Move back results of software rendering on system memory copy of mixed driver
|
||||
* pixmap (see exaPrepareAccessReg_mixed).
|
||||
*
|
||||
* Defer moving the destination back into the driver pixmap, to try and save
|
||||
* overhead on multiple subsequent software fallbacks.
|
||||
*/
|
||||
if (!pExaPixmap->use_gpu_copy && exaPixmapHasGpuCopy(pPixmap)) {
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap &&
|
||||
pExaScr->deferred_mixed_pixmap != pPixmap)
|
||||
exaMoveInPixmap_mixed(pExaScr->deferred_mixed_pixmap);
|
||||
pExaScr->deferred_mixed_pixmap = pPixmap;
|
||||
}
|
||||
}
|
||||
|
||||
/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
|
||||
* use the DownloadFromScreen hook to retrieve contents to a copy in system
|
||||
* memory, perform software rendering on that and move back the results with the
|
||||
* UploadToScreen hook (see exaDamageReport_mixed).
|
||||
*/
|
||||
void
|
||||
exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
|
||||
{
|
||||
ExaPixmapPriv(pPixmap);
|
||||
Bool has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
Bool success;
|
||||
|
||||
success = ExaDoPrepareAccess(pPixmap, index);
|
||||
|
||||
if (success && has_gpu_copy && pExaPixmap->pDamage) {
|
||||
/* You cannot do accelerated operations while a buffer is mapped. */
|
||||
exaFinishAccess(&pPixmap->drawable, index);
|
||||
/* Update the gpu view of both deferred destination pixmaps and of
|
||||
* source pixmaps that were migrated with a bounding region.
|
||||
*/
|
||||
exaMoveInPixmap_mixed(pPixmap);
|
||||
success = ExaDoPrepareAccess(pPixmap, index);
|
||||
|
||||
if (success) {
|
||||
/* We have a gpu pixmap that can be accessed, we don't need the cpu
|
||||
* copy anymore. Drivers that prefer DFS, should fail prepare
|
||||
* access.
|
||||
*/
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
|
||||
free(pExaPixmap->sys_ptr);
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
ExaMigrationRec pixmaps[1];
|
||||
|
||||
/* Do we need to allocate our system buffer? */
|
||||
if (!pExaPixmap->sys_ptr) {
|
||||
pExaPixmap->sys_ptr = xallocarray(pExaPixmap->sys_pitch,
|
||||
pPixmap->drawable.height);
|
||||
if (!pExaPixmap->sys_ptr)
|
||||
FatalError("EXA: malloc failed for size %d bytes\n",
|
||||
pExaPixmap->sys_pitch * pPixmap->drawable.height);
|
||||
}
|
||||
|
||||
if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
|
||||
pixmaps[0].as_dst = TRUE;
|
||||
pixmaps[0].as_src = FALSE;
|
||||
}
|
||||
else {
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
}
|
||||
pixmaps[0].pPix = pPixmap;
|
||||
pixmaps[0].pReg = pReg;
|
||||
|
||||
if (!pExaPixmap->pDamage &&
|
||||
(has_gpu_copy || !exaPixmapIsPinned(pPixmap))) {
|
||||
Bool as_dst = pixmaps[0].as_dst;
|
||||
|
||||
/* Set up damage tracking */
|
||||
pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
|
||||
DamageReportNonEmpty, TRUE,
|
||||
pPixmap->drawable.pScreen,
|
||||
pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
|
||||
/* This ensures that pending damage reflects the current
|
||||
* operation. This is used by exa to optimize migration.
|
||||
*/
|
||||
DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
|
||||
}
|
||||
|
||||
if (has_gpu_copy) {
|
||||
exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
|
||||
pPixmap->drawable.height);
|
||||
|
||||
/* We don't know which region of the destination will be damaged,
|
||||
* have to assume all of it
|
||||
*/
|
||||
if (as_dst) {
|
||||
pixmaps[0].as_dst = FALSE;
|
||||
pixmaps[0].as_src = TRUE;
|
||||
pixmaps[0].pReg = NULL;
|
||||
}
|
||||
exaCopyDirtyToSys(pixmaps);
|
||||
}
|
||||
|
||||
if (as_dst)
|
||||
exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
|
||||
pPixmap->drawable.height);
|
||||
}
|
||||
else if (has_gpu_copy)
|
||||
exaCopyDirtyToSys(pixmaps);
|
||||
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
}
|
||||
}
|
330
exa/exa_mixed.c
330
exa/exa_mixed.c
|
@ -1,330 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2009 Maarten Maathuis
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "exa_priv.h"
|
||||
#include "exa.h"
|
||||
|
||||
/* This file holds the driver allocated pixmaps + better initial placement code.
|
||||
*/
|
||||
|
||||
static _X_INLINE void *
|
||||
ExaGetPixmapAddress(PixmapPtr p)
|
||||
{
|
||||
ExaPixmapPriv(p);
|
||||
|
||||
return pExaPixmap->sys_ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaCreatePixmap() creates a new pixmap.
|
||||
*/
|
||||
PixmapPtr
|
||||
exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint)
|
||||
{
|
||||
PixmapPtr pPixmap;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
int bpp;
|
||||
size_t paddedWidth;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (w > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
pPixmap = pScreen->CreatePixmap(pScreen, 0, 0, depth, usage_hint);
|
||||
swap(pExaScr, pScreen, CreatePixmap);
|
||||
|
||||
if (!pPixmap)
|
||||
return NULL;
|
||||
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
bpp = pPixmap->drawable.bitsPerPixel;
|
||||
|
||||
paddedWidth = ((w * bpp + FB_MASK) >> FB_SHIFT) * sizeof(FbBits);
|
||||
if (paddedWidth / 4 > 32767 || h > 32767)
|
||||
return NullPixmap;
|
||||
|
||||
/* We will allocate the system pixmap later if needed. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
pExaPixmap->sys_pitch = paddedWidth;
|
||||
|
||||
pExaPixmap->area = NULL;
|
||||
pExaPixmap->fb_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, w, h, bpp);
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, w, h, bpp);
|
||||
|
||||
(*pScreen->ModifyPixmapHeader) (pPixmap, w, h, 0, 0, paddedWidth, NULL);
|
||||
|
||||
/* A scratch pixmap will become a driver pixmap right away. */
|
||||
if (!w || !h) {
|
||||
exaCreateDriverPixmap_mixed(pPixmap);
|
||||
pExaPixmap->use_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
}
|
||||
else {
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
|
||||
if (w == 1 && h == 1) {
|
||||
pExaPixmap->sys_ptr = malloc(paddedWidth);
|
||||
|
||||
/* Set up damage tracking */
|
||||
pExaPixmap->pDamage = DamageCreate(exaDamageReport_mixed, NULL,
|
||||
DamageReportNonEmpty, TRUE,
|
||||
pPixmap->drawable.pScreen,
|
||||
pPixmap);
|
||||
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
|
||||
/* This ensures that pending damage reflects the current
|
||||
* operation. This is used by exa to optimize migration.
|
||||
*/
|
||||
DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* During a fallback we must prepare access. */
|
||||
if (pExaScr->fallback_counter)
|
||||
exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
return pPixmap;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
|
||||
int bitsPerPixel, int devKind, void *pPixData)
|
||||
{
|
||||
ScreenPtr pScreen;
|
||||
ExaScreenPrivPtr pExaScr;
|
||||
ExaPixmapPrivPtr pExaPixmap;
|
||||
Bool ret, has_gpu_copy;
|
||||
|
||||
if (!pPixmap)
|
||||
return FALSE;
|
||||
|
||||
pScreen = pPixmap->drawable.pScreen;
|
||||
pExaScr = ExaGetScreenPriv(pScreen);
|
||||
pExaPixmap = ExaGetPixmapPriv(pPixmap);
|
||||
|
||||
if (pPixData) {
|
||||
if (pExaPixmap->driverPriv) {
|
||||
if (pExaPixmap->pDamage) {
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
}
|
||||
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->use_gpu_copy = FALSE;
|
||||
pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
|
||||
}
|
||||
|
||||
has_gpu_copy = exaPixmapHasGpuCopy(pPixmap);
|
||||
|
||||
if (width <= 0)
|
||||
width = pPixmap->drawable.width;
|
||||
|
||||
if (height <= 0)
|
||||
height = pPixmap->drawable.height;
|
||||
|
||||
if (bitsPerPixel <= 0) {
|
||||
if (depth <= 0)
|
||||
bitsPerPixel = pPixmap->drawable.bitsPerPixel;
|
||||
else
|
||||
bitsPerPixel = BitsPerPixel(depth);
|
||||
}
|
||||
|
||||
if (depth <= 0)
|
||||
depth = pPixmap->drawable.depth;
|
||||
|
||||
if (width != pPixmap->drawable.width ||
|
||||
height != pPixmap->drawable.height ||
|
||||
depth != pPixmap->drawable.depth ||
|
||||
bitsPerPixel != pPixmap->drawable.bitsPerPixel) {
|
||||
if (pExaPixmap->driverPriv) {
|
||||
if (devKind > 0)
|
||||
pExaPixmap->fb_pitch = devKind;
|
||||
else
|
||||
exaSetFbPitch(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
|
||||
exaSetAccelBlock(pExaScr, pExaPixmap, width, height, bitsPerPixel);
|
||||
RegionEmpty(&pExaPixmap->validFB);
|
||||
}
|
||||
|
||||
/* Need to re-create system copy if there's also a GPU copy */
|
||||
if (has_gpu_copy) {
|
||||
if (pExaPixmap->sys_ptr) {
|
||||
free(pExaPixmap->sys_ptr);
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
DamageDestroy(pExaPixmap->pDamage);
|
||||
pExaPixmap->pDamage = NULL;
|
||||
RegionEmpty(&pExaPixmap->validSys);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap == pPixmap)
|
||||
pExaScr->deferred_mixed_pixmap = NULL;
|
||||
}
|
||||
|
||||
pExaPixmap->sys_pitch = PixmapBytePad(width, depth);
|
||||
}
|
||||
}
|
||||
|
||||
if (has_gpu_copy) {
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
|
||||
pPixmap->devKind = pExaPixmap->fb_pitch;
|
||||
}
|
||||
else {
|
||||
pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
|
||||
pPixmap->devKind = pExaPixmap->sys_pitch;
|
||||
}
|
||||
|
||||
/* Only pass driver pixmaps to the driver. */
|
||||
if (pExaScr->info->ModifyPixmapHeader && pExaPixmap->driverPriv) {
|
||||
ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind,
|
||||
pPixData);
|
||||
if (ret == TRUE)
|
||||
goto out;
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
ret = pScreen->ModifyPixmapHeader(pPixmap, width, height, depth,
|
||||
bitsPerPixel, devKind, pPixData);
|
||||
swap(pExaScr, pScreen, ModifyPixmapHeader);
|
||||
|
||||
out:
|
||||
if (has_gpu_copy) {
|
||||
pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->fb_pitch = pPixmap->devKind;
|
||||
}
|
||||
else {
|
||||
pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
|
||||
pExaPixmap->sys_pitch = pPixmap->devKind;
|
||||
}
|
||||
/* Always NULL this, we don't want lingering pointers. */
|
||||
pPixmap->devPrivate.ptr = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
if (pPixmap->refcnt == 1) {
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
exaDestroyPixmap(pPixmap);
|
||||
|
||||
if (pExaScr->deferred_mixed_pixmap == pPixmap)
|
||||
pExaScr->deferred_mixed_pixmap = NULL;
|
||||
|
||||
if (pExaPixmap->driverPriv)
|
||||
pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
|
||||
pExaPixmap->driverPriv = NULL;
|
||||
|
||||
if (pExaPixmap->pDamage) {
|
||||
free(pExaPixmap->sys_ptr);
|
||||
pExaPixmap->sys_ptr = NULL;
|
||||
pExaPixmap->pDamage = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
ret = pScreen->DestroyPixmap(pPixmap);
|
||||
swap(pExaScr, pScreen, DestroyPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaPixmapPriv(pPixmap);
|
||||
void *saved_ptr;
|
||||
Bool ret;
|
||||
|
||||
if (!pExaPixmap->driverPriv)
|
||||
return FALSE;
|
||||
|
||||
saved_ptr = pPixmap->devPrivate.ptr;
|
||||
pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
|
||||
ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
|
||||
pPixmap->devPrivate.ptr = saved_ptr;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret = FALSE;
|
||||
|
||||
exaMoveInPixmap(pPixmap);
|
||||
/* get the driver to give us a handle */
|
||||
if (pExaScr->info->SharePixmapBacking)
|
||||
ret = pExaScr->info->SharePixmapBacking(pPixmap, secondary, handle_p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Bool
|
||||
exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle)
|
||||
{
|
||||
ScreenPtr pScreen = pPixmap->drawable.pScreen;
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret = FALSE;
|
||||
|
||||
if (pExaScr->info->SetSharedPixmapBacking)
|
||||
ret = pExaScr->info->SetSharedPixmapBacking(pPixmap, handle);
|
||||
|
||||
if (ret == TRUE)
|
||||
exaMoveInPixmap(pPixmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1,677 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2003 Anders Carlsson
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Anders Carlsson not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Anders Carlsson makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* This allocator allocates blocks of memory by maintaining a list of areas.
|
||||
* When allocating, the contiguous block of areas with the minimum eviction
|
||||
* cost is found and evicted in order to make room for the new allocation.
|
||||
*/
|
||||
|
||||
#include "exa_priv.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
#define DBG_OFFSCREEN(a) ErrorF a
|
||||
#else
|
||||
#define DBG_OFFSCREEN(a)
|
||||
#endif
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
static void
|
||||
ExaOffscreenValidate(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *prev = 0, *area;
|
||||
|
||||
assert(pExaScr->info->offScreenAreas->base_offset ==
|
||||
pExaScr->info->offScreenBase);
|
||||
for (area = pExaScr->info->offScreenAreas; area; area = area->next) {
|
||||
assert(area->offset >= area->base_offset);
|
||||
assert(area->offset < (area->base_offset + area->size));
|
||||
if (prev)
|
||||
assert(prev->base_offset + prev->size == area->base_offset);
|
||||
prev = area;
|
||||
}
|
||||
assert(prev->base_offset + prev->size == pExaScr->info->memorySize);
|
||||
}
|
||||
#else
|
||||
#define ExaOffscreenValidate(s)
|
||||
#endif
|
||||
|
||||
static ExaOffscreenArea *
|
||||
ExaOffscreenKickOut(ScreenPtr pScreen, ExaOffscreenArea * area)
|
||||
{
|
||||
if (area->save)
|
||||
(*area->save) (pScreen, area);
|
||||
return exaOffscreenFree(pScreen, area);
|
||||
}
|
||||
|
||||
static void
|
||||
exaUpdateEvictionCost(ExaOffscreenArea * area, unsigned offScreenCounter)
|
||||
{
|
||||
unsigned age;
|
||||
|
||||
if (area->state == ExaOffscreenAvail)
|
||||
return;
|
||||
|
||||
age = offScreenCounter - area->last_use;
|
||||
|
||||
/* This is unlikely to happen, but could result in a division by zero... */
|
||||
if (age > (UINT_MAX / 2)) {
|
||||
age = UINT_MAX / 2;
|
||||
area->last_use = offScreenCounter - age;
|
||||
}
|
||||
|
||||
area->eviction_cost = area->size / age;
|
||||
}
|
||||
|
||||
static ExaOffscreenArea *
|
||||
exaFindAreaToEvict(ExaScreenPrivPtr pExaScr, int size, int align)
|
||||
{
|
||||
ExaOffscreenArea *begin, *end, *best;
|
||||
unsigned cost, best_cost;
|
||||
int avail, real_size;
|
||||
|
||||
best_cost = UINT_MAX;
|
||||
begin = end = pExaScr->info->offScreenAreas;
|
||||
avail = 0;
|
||||
cost = 0;
|
||||
best = 0;
|
||||
|
||||
while (end != NULL) {
|
||||
restart:
|
||||
while (begin != NULL && begin->state == ExaOffscreenLocked)
|
||||
begin = end = begin->next;
|
||||
|
||||
if (begin == NULL)
|
||||
break;
|
||||
|
||||
/* adjust size needed to account for alignment loss for this area */
|
||||
real_size = size + (begin->base_offset + begin->size - size) % align;
|
||||
|
||||
while (avail < real_size && end != NULL) {
|
||||
if (end->state == ExaOffscreenLocked) {
|
||||
/* Can't more room here, restart after this locked area */
|
||||
avail = 0;
|
||||
cost = 0;
|
||||
begin = end;
|
||||
goto restart;
|
||||
}
|
||||
avail += end->size;
|
||||
exaUpdateEvictionCost(end, pExaScr->offScreenCounter);
|
||||
cost += end->eviction_cost;
|
||||
end = end->next;
|
||||
}
|
||||
|
||||
/* Check the cost, update best */
|
||||
if (avail >= real_size && cost < best_cost) {
|
||||
best = begin;
|
||||
best_cost = cost;
|
||||
}
|
||||
|
||||
avail -= begin->size;
|
||||
cost -= begin->eviction_cost;
|
||||
begin = begin->next;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaOffscreenAlloc allocates offscreen memory
|
||||
*
|
||||
* @param pScreen current screen
|
||||
* @param size size in bytes of the allocation
|
||||
* @param align byte alignment requirement for the offset of the allocated area
|
||||
* @param locked whether the allocated area is locked and can't be kicked out
|
||||
* @param save callback for when the area is evicted from memory
|
||||
* @param privdata private data for the save callback.
|
||||
*
|
||||
* Allocates offscreen memory from the device associated with pScreen. size
|
||||
* and align determine where and how large the allocated area is, and locked
|
||||
* will mark whether it should be held in card memory. privdata may be any
|
||||
* pointer for the save callback when the area is removed.
|
||||
*
|
||||
* Note that locked areas do get evicted on VT switch unless the driver
|
||||
* requested version 2.1 or newer behavior. In that case, the save callback is
|
||||
* still called.
|
||||
*/
|
||||
ExaOffscreenArea *
|
||||
exaOffscreenAlloc(ScreenPtr pScreen, int size, int align,
|
||||
Bool locked, ExaOffscreenSaveProc save, void *privData)
|
||||
{
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
int real_size = 0, largest_avail = 0;
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
static int number = 0;
|
||||
|
||||
ErrorF("================= ============ allocating a new pixmap %d\n",
|
||||
++number);
|
||||
#endif
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
if (!align)
|
||||
align = 1;
|
||||
|
||||
if (!size) {
|
||||
DBG_OFFSCREEN(("Alloc 0x%x -> EMPTY\n", size));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* throw out requests that cannot fit */
|
||||
if (size > (pExaScr->info->memorySize - pExaScr->info->offScreenBase)) {
|
||||
DBG_OFFSCREEN(("Alloc 0x%x vs (0x%lx) -> TOBIG\n", size,
|
||||
pExaScr->info->memorySize -
|
||||
pExaScr->info->offScreenBase));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Try to find a free space that'll fit. */
|
||||
for (area = pExaScr->info->offScreenAreas; area; area = area->next) {
|
||||
/* skip allocated areas */
|
||||
if (area->state != ExaOffscreenAvail)
|
||||
continue;
|
||||
|
||||
/* adjust size to match alignment requirement */
|
||||
real_size = size + (area->base_offset + area->size - size) % align;
|
||||
|
||||
/* does it fit? */
|
||||
if (real_size <= area->size)
|
||||
break;
|
||||
|
||||
if (area->size > largest_avail)
|
||||
largest_avail = area->size;
|
||||
}
|
||||
|
||||
if (!area) {
|
||||
area = exaFindAreaToEvict(pExaScr, size, align);
|
||||
|
||||
if (!area) {
|
||||
DBG_OFFSCREEN(("Alloc 0x%x -> NOSPACE\n", size));
|
||||
/* Could not allocate memory */
|
||||
ExaOffscreenValidate(pScreen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* adjust size needed to account for alignment loss for this area */
|
||||
real_size = size + (area->base_offset + area->size - size) % align;
|
||||
|
||||
/*
|
||||
* Kick out first area if in use
|
||||
*/
|
||||
if (area->state != ExaOffscreenAvail)
|
||||
area = ExaOffscreenKickOut(pScreen, area);
|
||||
/*
|
||||
* Now get the system to merge the other needed areas together
|
||||
*/
|
||||
while (area->size < real_size) {
|
||||
assert(area->next);
|
||||
assert(area->next->state == ExaOffscreenRemovable);
|
||||
(void) ExaOffscreenKickOut(pScreen, area->next);
|
||||
}
|
||||
}
|
||||
|
||||
/* save extra space in new area */
|
||||
if (real_size < area->size) {
|
||||
ExaOffscreenArea *new_area = malloc(sizeof(ExaOffscreenArea));
|
||||
|
||||
if (!new_area)
|
||||
return NULL;
|
||||
new_area->base_offset = area->base_offset;
|
||||
|
||||
new_area->offset = new_area->base_offset;
|
||||
new_area->align = 0;
|
||||
new_area->size = area->size - real_size;
|
||||
new_area->state = ExaOffscreenAvail;
|
||||
new_area->save = NULL;
|
||||
new_area->last_use = 0;
|
||||
new_area->eviction_cost = 0;
|
||||
new_area->next = area;
|
||||
new_area->prev = area->prev;
|
||||
if (area->prev->next)
|
||||
area->prev->next = new_area;
|
||||
else
|
||||
pExaScr->info->offScreenAreas = new_area;
|
||||
area->prev = new_area;
|
||||
area->base_offset = new_area->base_offset + new_area->size;
|
||||
area->size = real_size;
|
||||
}
|
||||
else
|
||||
pExaScr->numOffscreenAvailable--;
|
||||
|
||||
/*
|
||||
* Mark this area as in use
|
||||
*/
|
||||
if (locked)
|
||||
area->state = ExaOffscreenLocked;
|
||||
else
|
||||
area->state = ExaOffscreenRemovable;
|
||||
area->privData = privData;
|
||||
area->save = save;
|
||||
area->last_use = pExaScr->offScreenCounter++;
|
||||
area->offset = (area->base_offset + align - 1);
|
||||
area->offset -= area->offset % align;
|
||||
area->align = align;
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
|
||||
DBG_OFFSCREEN(("Alloc 0x%x -> 0x%x (0x%x)\n", size,
|
||||
area->base_offset, area->offset));
|
||||
return area;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ejects all offscreen areas, and uninitializes the offscreen memory manager.
|
||||
*/
|
||||
void
|
||||
ExaOffscreenSwapOut(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
/* loop until a single free area spans the space */
|
||||
for (;;) {
|
||||
ExaOffscreenArea *area = pExaScr->info->offScreenAreas;
|
||||
|
||||
if (!area)
|
||||
break;
|
||||
if (area->state == ExaOffscreenAvail) {
|
||||
area = area->next;
|
||||
if (!area)
|
||||
break;
|
||||
}
|
||||
assert(area->state != ExaOffscreenAvail);
|
||||
(void) ExaOffscreenKickOut(pScreen, area);
|
||||
ExaOffscreenValidate(pScreen);
|
||||
}
|
||||
ExaOffscreenValidate(pScreen);
|
||||
ExaOffscreenFini(pScreen);
|
||||
}
|
||||
|
||||
/** Ejects all pixmaps managed by EXA. */
|
||||
static void
|
||||
ExaOffscreenEjectPixmaps(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
/* loop until a single free area spans the space */
|
||||
for (;;) {
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
for (area = pExaScr->info->offScreenAreas; area != NULL;
|
||||
area = area->next) {
|
||||
if (area->state == ExaOffscreenRemovable &&
|
||||
area->save == exaPixmapSave) {
|
||||
(void) ExaOffscreenKickOut(pScreen, area);
|
||||
ExaOffscreenValidate(pScreen);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (area == NULL)
|
||||
break;
|
||||
}
|
||||
ExaOffscreenValidate(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaOffscreenSwapIn(ScreenPtr pScreen)
|
||||
{
|
||||
exaOffscreenInit(pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares EXA for disabling of FB access, or restoring it.
|
||||
*
|
||||
* In version 2.1, the disabling results in pixmaps being ejected, while other
|
||||
* allocations remain. With this plus the prevention of migration while
|
||||
* swappedOut is set, EXA by itself should not cause any access of the
|
||||
* framebuffer to occur while swapped out. Any remaining issues are the
|
||||
* responsibility of the driver.
|
||||
*
|
||||
* Prior to version 2.1, all allocations, including locked ones, are ejected
|
||||
* when access is disabled, and the allocator is torn down while swappedOut
|
||||
* is set. This is more drastic, and caused implementation difficulties for
|
||||
* many drivers that could otherwise handle the lack of FB access while
|
||||
* swapped out.
|
||||
*/
|
||||
void
|
||||
exaEnableDisableFBAccess(ScreenPtr pScreen, Bool enable)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
|
||||
return;
|
||||
|
||||
if (!enable && pExaScr->disableFbCount++ == 0) {
|
||||
if (pExaScr->info->exa_minor < 1)
|
||||
ExaOffscreenSwapOut(pScreen);
|
||||
else
|
||||
ExaOffscreenEjectPixmaps(pScreen);
|
||||
pExaScr->swappedOut = TRUE;
|
||||
}
|
||||
|
||||
if (enable && --pExaScr->disableFbCount == 0) {
|
||||
if (pExaScr->info->exa_minor < 1)
|
||||
ExaOffscreenSwapIn(pScreen);
|
||||
pExaScr->swappedOut = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* merge the next free area into this one */
|
||||
static void
|
||||
ExaOffscreenMerge(ExaScreenPrivPtr pExaScr, ExaOffscreenArea * area)
|
||||
{
|
||||
ExaOffscreenArea *next = area->next;
|
||||
|
||||
/* account for space */
|
||||
area->size += next->size;
|
||||
/* frob pointer */
|
||||
area->next = next->next;
|
||||
if (area->next)
|
||||
area->next->prev = area;
|
||||
else
|
||||
pExaScr->info->offScreenAreas->prev = area;
|
||||
free(next);
|
||||
|
||||
pExaScr->numOffscreenAvailable--;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaOffscreenFree frees an allocation.
|
||||
*
|
||||
* @param pScreen current screen
|
||||
* @param area offscreen area to free
|
||||
*
|
||||
* exaOffscreenFree frees an allocation created by exaOffscreenAlloc. Note that
|
||||
* the save callback of the area is not called, and it is up to the driver to
|
||||
* do any cleanup necessary as a result.
|
||||
*
|
||||
* @return pointer to the newly freed area. This behavior should not be relied
|
||||
* on.
|
||||
*/
|
||||
ExaOffscreenArea *
|
||||
exaOffscreenFree(ScreenPtr pScreen, ExaOffscreenArea * area)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *next = area->next;
|
||||
ExaOffscreenArea *prev;
|
||||
|
||||
DBG_OFFSCREEN(("Free 0x%x -> 0x%x (0x%x)\n", area->size,
|
||||
area->base_offset, area->offset));
|
||||
ExaOffscreenValidate(pScreen);
|
||||
|
||||
area->state = ExaOffscreenAvail;
|
||||
area->save = NULL;
|
||||
area->last_use = 0;
|
||||
area->eviction_cost = 0;
|
||||
/*
|
||||
* Find previous area
|
||||
*/
|
||||
if (area == pExaScr->info->offScreenAreas)
|
||||
prev = NULL;
|
||||
else
|
||||
prev = area->prev;
|
||||
|
||||
pExaScr->numOffscreenAvailable++;
|
||||
|
||||
/* link with next area if free */
|
||||
if (next && next->state == ExaOffscreenAvail)
|
||||
ExaOffscreenMerge(pExaScr, area);
|
||||
|
||||
/* link with prev area if free */
|
||||
if (prev && prev->state == ExaOffscreenAvail) {
|
||||
area = prev;
|
||||
ExaOffscreenMerge(pExaScr, area);
|
||||
}
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
DBG_OFFSCREEN(("\tdone freeing\n"));
|
||||
return area;
|
||||
}
|
||||
|
||||
void
|
||||
ExaOffscreenMarkUsed(PixmapPtr pPixmap)
|
||||
{
|
||||
ExaPixmapPriv(pPixmap);
|
||||
ExaScreenPriv(pPixmap->drawable.pScreen);
|
||||
|
||||
if (!pExaPixmap || !pExaPixmap->area)
|
||||
return;
|
||||
|
||||
pExaPixmap->area->last_use = pExaScr->offScreenCounter++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defragment offscreen memory by compacting allocated areas at the end of it,
|
||||
* leaving the total amount of memory available as a single area at the
|
||||
* beginning (when there are no pinned allocations).
|
||||
*/
|
||||
_X_HIDDEN ExaOffscreenArea *
|
||||
ExaOffscreenDefragment(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *area, *largest_available = NULL;
|
||||
int largest_size = 0;
|
||||
PixmapPtr pDstPix;
|
||||
ExaPixmapPrivPtr pExaDstPix;
|
||||
|
||||
pDstPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, 0, 0);
|
||||
|
||||
if (!pDstPix)
|
||||
return NULL;
|
||||
|
||||
pExaDstPix = ExaGetPixmapPriv(pDstPix);
|
||||
pExaDstPix->use_gpu_copy = TRUE;
|
||||
|
||||
for (area = pExaScr->info->offScreenAreas->prev;
|
||||
area != pExaScr->info->offScreenAreas;) {
|
||||
ExaOffscreenArea *prev = area->prev;
|
||||
PixmapPtr pSrcPix;
|
||||
ExaPixmapPrivPtr pExaSrcPix;
|
||||
Bool save_use_gpu_copy;
|
||||
int save_pitch;
|
||||
|
||||
if (area->state != ExaOffscreenAvail ||
|
||||
prev->state == ExaOffscreenLocked ||
|
||||
(prev->state == ExaOffscreenRemovable &&
|
||||
prev->save != exaPixmapSave)) {
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (prev->state == ExaOffscreenAvail) {
|
||||
if (area == largest_available) {
|
||||
largest_available = prev;
|
||||
largest_size += prev->size;
|
||||
}
|
||||
area = prev;
|
||||
ExaOffscreenMerge(pExaScr, area);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (area->size > largest_size) {
|
||||
largest_available = area;
|
||||
largest_size = area->size;
|
||||
}
|
||||
|
||||
pSrcPix = prev->privData;
|
||||
pExaSrcPix = ExaGetPixmapPriv(pSrcPix);
|
||||
|
||||
pExaDstPix->fb_ptr = pExaScr->info->memoryBase +
|
||||
area->base_offset + area->size - prev->size + prev->base_offset -
|
||||
prev->offset;
|
||||
pExaDstPix->fb_ptr -= (unsigned long) pExaDstPix->fb_ptr % prev->align;
|
||||
|
||||
if (pExaDstPix->fb_ptr <= pExaSrcPix->fb_ptr) {
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(pExaScr->info->flags & EXA_SUPPORTS_OFFSCREEN_OVERLAPS) &&
|
||||
(pExaSrcPix->fb_ptr + prev->size) > pExaDstPix->fb_ptr) {
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
save_use_gpu_copy = pExaSrcPix->use_gpu_copy;
|
||||
save_pitch = pSrcPix->devKind;
|
||||
|
||||
pExaSrcPix->use_gpu_copy = TRUE;
|
||||
pSrcPix->devKind = pExaSrcPix->fb_pitch;
|
||||
|
||||
pDstPix->drawable.width = pSrcPix->drawable.width;
|
||||
pDstPix->devKind = pSrcPix->devKind;
|
||||
pDstPix->drawable.height = pSrcPix->drawable.height;
|
||||
pDstPix->drawable.depth = pSrcPix->drawable.depth;
|
||||
pDstPix->drawable.bitsPerPixel = pSrcPix->drawable.bitsPerPixel;
|
||||
|
||||
if (!pExaScr->info->PrepareCopy(pSrcPix, pDstPix, -1, -1, GXcopy, ~0)) {
|
||||
pExaSrcPix->use_gpu_copy = save_use_gpu_copy;
|
||||
pSrcPix->devKind = save_pitch;
|
||||
area = prev;
|
||||
continue;
|
||||
}
|
||||
|
||||
pExaScr->info->Copy(pDstPix, 0, 0, 0, 0, pDstPix->drawable.width,
|
||||
pDstPix->drawable.height);
|
||||
pExaScr->info->DoneCopy(pDstPix);
|
||||
exaMarkSync(pScreen);
|
||||
|
||||
DBG_OFFSCREEN(("Before swap: prev=0x%08x-0x%08x-0x%08x area=0x%08x-0x%08x-0x%08x\n", prev->base_offset, prev->offset, prev->base_offset + prev->size, area->base_offset, area->offset, area->base_offset + area->size));
|
||||
|
||||
/* Calculate swapped area offsets and sizes */
|
||||
area->base_offset = prev->base_offset;
|
||||
area->offset = area->base_offset;
|
||||
prev->offset += pExaDstPix->fb_ptr - pExaSrcPix->fb_ptr;
|
||||
assert(prev->offset >= pExaScr->info->offScreenBase);
|
||||
assert(prev->offset < pExaScr->info->memorySize);
|
||||
prev->base_offset = prev->offset;
|
||||
if (area->next)
|
||||
prev->size = area->next->base_offset - prev->base_offset;
|
||||
else
|
||||
prev->size = pExaScr->info->memorySize - prev->base_offset;
|
||||
area->size = prev->base_offset - area->base_offset;
|
||||
|
||||
DBG_OFFSCREEN(("After swap: area=0x%08x-0x%08x-0x%08x prev=0x%08x-0x%08x-0x%08x\n", area->base_offset, area->offset, area->base_offset + area->size, prev->base_offset, prev->offset, prev->base_offset + prev->size));
|
||||
|
||||
/* Swap areas in list */
|
||||
if (area->next)
|
||||
area->next->prev = prev;
|
||||
else
|
||||
pExaScr->info->offScreenAreas->prev = prev;
|
||||
if (prev->prev->next)
|
||||
prev->prev->next = area;
|
||||
else
|
||||
pExaScr->info->offScreenAreas = area;
|
||||
prev->next = area->next;
|
||||
area->next = prev;
|
||||
area->prev = prev->prev;
|
||||
prev->prev = area;
|
||||
if (!area->prev->next)
|
||||
pExaScr->info->offScreenAreas = area;
|
||||
|
||||
#if DEBUG_OFFSCREEN
|
||||
if (prev->prev == prev || prev->next == prev)
|
||||
ErrorF("Whoops, prev points to itself!\n");
|
||||
|
||||
if (area->prev == area || area->next == area)
|
||||
ErrorF("Whoops, area points to itself!\n");
|
||||
#endif
|
||||
|
||||
pExaSrcPix->fb_ptr = pExaDstPix->fb_ptr;
|
||||
pExaSrcPix->use_gpu_copy = save_use_gpu_copy;
|
||||
pSrcPix->devKind = save_pitch;
|
||||
}
|
||||
|
||||
pDstPix->drawable.width = 0;
|
||||
pDstPix->drawable.height = 0;
|
||||
pDstPix->drawable.depth = 0;
|
||||
pDstPix->drawable.bitsPerPixel = 0;
|
||||
|
||||
(*pScreen->DestroyPixmap) (pDstPix);
|
||||
|
||||
if (area->state == ExaOffscreenAvail && area->size > largest_size)
|
||||
return area;
|
||||
|
||||
return largest_available;
|
||||
}
|
||||
|
||||
/**
|
||||
* exaOffscreenInit initializes the offscreen memory manager.
|
||||
*
|
||||
* @param pScreen current screen
|
||||
*
|
||||
* exaOffscreenInit is called by exaDriverInit to set up the memory manager for
|
||||
* the screen, if any offscreen memory is available.
|
||||
*/
|
||||
Bool
|
||||
exaOffscreenInit(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
/* Allocate a big free area */
|
||||
area = malloc(sizeof(ExaOffscreenArea));
|
||||
|
||||
if (!area)
|
||||
return FALSE;
|
||||
|
||||
area->state = ExaOffscreenAvail;
|
||||
area->base_offset = pExaScr->info->offScreenBase;
|
||||
area->offset = area->base_offset;
|
||||
area->align = 0;
|
||||
area->size = pExaScr->info->memorySize - area->base_offset;
|
||||
area->save = NULL;
|
||||
area->next = NULL;
|
||||
area->prev = area;
|
||||
area->last_use = 0;
|
||||
area->eviction_cost = 0;
|
||||
|
||||
/* Add it to the free areas */
|
||||
pExaScr->info->offScreenAreas = area;
|
||||
pExaScr->offScreenCounter = 1;
|
||||
pExaScr->numOffscreenAvailable = 1;
|
||||
|
||||
ExaOffscreenValidate(pScreen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ExaOffscreenFini(ScreenPtr pScreen)
|
||||
{
|
||||
ExaScreenPriv(pScreen);
|
||||
ExaOffscreenArea *area;
|
||||
|
||||
/* just free all of the area records */
|
||||
while ((area = pExaScr->info->offScreenAreas)) {
|
||||
pExaScr->info->offScreenAreas = area->next;
|
||||
free(area);
|
||||
}
|
||||
}
|
735
exa/exa_priv.h
735
exa/exa_priv.h
|
@ -1,735 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright (C) 2000 Keith Packard, member of The XFree86 Project, Inc.
|
||||
* 2005 Zack Rusin, Trolltech
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
||||
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef EXAPRIV_H
|
||||
#define EXAPRIV_H
|
||||
|
||||
#ifdef HAVE_DIX_CONFIG_H
|
||||
#include <dix-config.h>
|
||||
#endif
|
||||
|
||||
#include "exa.h"
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xproto.h>
|
||||
#ifdef MITSHM
|
||||
#include "shmint.h"
|
||||
#endif
|
||||
#include "scrnintstr.h"
|
||||
#include "pixmapstr.h"
|
||||
#include "windowstr.h"
|
||||
#include "servermd.h"
|
||||
#include "colormapst.h"
|
||||
#include "gcstruct.h"
|
||||
#include "input.h"
|
||||
#include "mipointer.h"
|
||||
#include "mi.h"
|
||||
#include "dix.h"
|
||||
#include "fb.h"
|
||||
#include "fboverlay.h"
|
||||
#include "fbpict.h"
|
||||
#include "glyphstr.h"
|
||||
#include "damage.h"
|
||||
|
||||
#define DEBUG_TRACE_FALL 0
|
||||
#define DEBUG_MIGRATE 0
|
||||
#define DEBUG_PIXMAP 0
|
||||
#define DEBUG_OFFSCREEN 0
|
||||
#define DEBUG_GLYPH_CACHE 0
|
||||
|
||||
#if DEBUG_TRACE_FALL
|
||||
#define EXA_FALLBACK(x) \
|
||||
do { \
|
||||
ErrorF("EXA fallback at %s: ", __FUNCTION__); \
|
||||
ErrorF x; \
|
||||
} while (0)
|
||||
|
||||
char
|
||||
exaDrawableLocation(DrawablePtr pDrawable);
|
||||
#else
|
||||
#define EXA_FALLBACK(x)
|
||||
#endif
|
||||
|
||||
#if DEBUG_PIXMAP
|
||||
#define DBG_PIXMAP(a) ErrorF a
|
||||
#else
|
||||
#define DBG_PIXMAP(a)
|
||||
#endif
|
||||
|
||||
#ifndef EXA_MAX_FB
|
||||
#define EXA_MAX_FB FB_OVERLAY_MAX
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define EXA_FatalErrorDebug(x) FatalError x
|
||||
#define EXA_FatalErrorDebugWithRet(x, ret) FatalError x
|
||||
#else
|
||||
#define EXA_FatalErrorDebug(x) ErrorF x
|
||||
#define EXA_FatalErrorDebugWithRet(x, ret) \
|
||||
do { \
|
||||
ErrorF x; \
|
||||
return ret; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This is the list of migration heuristics supported by EXA. See
|
||||
* exaDoMigration() for what their implementations do.
|
||||
*/
|
||||
enum ExaMigrationHeuristic {
|
||||
ExaMigrationGreedy,
|
||||
ExaMigrationAlways,
|
||||
ExaMigrationSmart
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned char sha1[20];
|
||||
} ExaCachedGlyphRec, *ExaCachedGlyphPtr;
|
||||
|
||||
typedef struct {
|
||||
/* The identity of the cache, statically configured at initialization */
|
||||
unsigned int format;
|
||||
int glyphWidth;
|
||||
int glyphHeight;
|
||||
|
||||
int size; /* Size of cache; eventually this should be dynamically determined */
|
||||
|
||||
/* Hash table mapping from glyph sha1 to position in the glyph; we use
|
||||
* open addressing with a hash table size determined based on size and large
|
||||
* enough so that we always have a good amount of free space, so we can
|
||||
* use linear probing. (Linear probing is preferable to double hashing
|
||||
* here because it allows us to easily remove entries.)
|
||||
*/
|
||||
int *hashEntries;
|
||||
int hashSize;
|
||||
|
||||
ExaCachedGlyphPtr glyphs;
|
||||
int glyphCount; /* Current number of glyphs */
|
||||
|
||||
PicturePtr picture; /* Where the glyphs of the cache are stored */
|
||||
int yOffset; /* y location within the picture where the cache starts */
|
||||
int columns; /* Number of columns the glyphs are laid out in */
|
||||
int evictionPosition; /* Next random position to evict a glyph */
|
||||
} ExaGlyphCacheRec, *ExaGlyphCachePtr;
|
||||
|
||||
#define EXA_NUM_GLYPH_CACHES 4
|
||||
|
||||
#define EXA_FALLBACK_COPYWINDOW (1 << 0)
|
||||
#define EXA_ACCEL_COPYWINDOW (1 << 1)
|
||||
|
||||
typedef struct _ExaMigrationRec {
|
||||
Bool as_dst;
|
||||
Bool as_src;
|
||||
PixmapPtr pPix;
|
||||
RegionPtr pReg;
|
||||
} ExaMigrationRec, *ExaMigrationPtr;
|
||||
|
||||
typedef void (*EnableDisableFBAccessProcPtr) (ScreenPtr, Bool);
|
||||
typedef struct {
|
||||
ExaDriverPtr info;
|
||||
ScreenBlockHandlerProcPtr SavedBlockHandler;
|
||||
ScreenWakeupHandlerProcPtr SavedWakeupHandler;
|
||||
CreateGCProcPtr SavedCreateGC;
|
||||
CloseScreenProcPtr SavedCloseScreen;
|
||||
GetImageProcPtr SavedGetImage;
|
||||
GetSpansProcPtr SavedGetSpans;
|
||||
CreatePixmapProcPtr SavedCreatePixmap;
|
||||
DestroyPixmapProcPtr SavedDestroyPixmap;
|
||||
CopyWindowProcPtr SavedCopyWindow;
|
||||
ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
|
||||
BitmapToRegionProcPtr SavedBitmapToRegion;
|
||||
CreateScreenResourcesProcPtr SavedCreateScreenResources;
|
||||
ModifyPixmapHeaderProcPtr SavedModifyPixmapHeader;
|
||||
SharePixmapBackingProcPtr SavedSharePixmapBacking;
|
||||
SetSharedPixmapBackingProcPtr SavedSetSharedPixmapBacking;
|
||||
SourceValidateProcPtr SavedSourceValidate;
|
||||
CompositeProcPtr SavedComposite;
|
||||
TrianglesProcPtr SavedTriangles;
|
||||
GlyphsProcPtr SavedGlyphs;
|
||||
TrapezoidsProcPtr SavedTrapezoids;
|
||||
AddTrapsProcPtr SavedAddTraps;
|
||||
void (*do_migration) (ExaMigrationPtr pixmaps, int npixmaps,
|
||||
Bool can_accel);
|
||||
Bool (*pixmap_has_gpu_copy) (PixmapPtr pPixmap);
|
||||
void (*do_move_in_pixmap) (PixmapPtr pPixmap);
|
||||
void (*do_move_out_pixmap) (PixmapPtr pPixmap);
|
||||
void (*prepare_access_reg) (PixmapPtr pPixmap, int index, RegionPtr pReg);
|
||||
|
||||
Bool swappedOut;
|
||||
enum ExaMigrationHeuristic migration;
|
||||
Bool checkDirtyCorrectness;
|
||||
unsigned disableFbCount;
|
||||
Bool optimize_migration;
|
||||
unsigned offScreenCounter;
|
||||
unsigned numOffscreenAvailable;
|
||||
CARD32 lastDefragment;
|
||||
CARD32 nextDefragment;
|
||||
PixmapPtr deferred_mixed_pixmap;
|
||||
|
||||
/* Reference counting for accessed pixmaps */
|
||||
struct {
|
||||
PixmapPtr pixmap;
|
||||
int count;
|
||||
Bool retval;
|
||||
} access[EXA_NUM_PREPARE_INDICES];
|
||||
|
||||
/* Holds information on fallbacks that cannot be relayed otherwise. */
|
||||
unsigned int fallback_flags;
|
||||
unsigned int fallback_counter;
|
||||
|
||||
ExaGlyphCacheRec glyphCaches[EXA_NUM_GLYPH_CACHES];
|
||||
|
||||
/**
|
||||
* Regions affected by fallback composite source / mask operations.
|
||||
*/
|
||||
|
||||
RegionRec srcReg;
|
||||
RegionRec maskReg;
|
||||
PixmapPtr srcPix;
|
||||
PixmapPtr maskPix;
|
||||
|
||||
DevPrivateKeyRec pixmapPrivateKeyRec;
|
||||
DevPrivateKeyRec gcPrivateKeyRec;
|
||||
} ExaScreenPrivRec, *ExaScreenPrivPtr;
|
||||
|
||||
extern DevPrivateKeyRec exaScreenPrivateKeyRec;
|
||||
|
||||
#define exaScreenPrivateKey (&exaScreenPrivateKeyRec)
|
||||
|
||||
#define ExaGetScreenPriv(s) ((ExaScreenPrivPtr)dixGetPrivate(&(s)->devPrivates, exaScreenPrivateKey))
|
||||
#define ExaScreenPriv(s) ExaScreenPrivPtr pExaScr = ExaGetScreenPriv(s)
|
||||
|
||||
#define ExaGetGCPriv(gc) ((ExaGCPrivPtr)dixGetPrivateAddr(&(gc)->devPrivates, &ExaGetScreenPriv(gc->pScreen)->gcPrivateKeyRec))
|
||||
#define ExaGCPriv(gc) ExaGCPrivPtr pExaGC = ExaGetGCPriv(gc)
|
||||
|
||||
/*
|
||||
* Some macros to deal with function wrapping.
|
||||
*/
|
||||
#define wrap(priv, real, mem, func) {\
|
||||
priv->Saved##mem = real->mem; \
|
||||
real->mem = func; \
|
||||
}
|
||||
|
||||
#define unwrap(priv, real, mem) {\
|
||||
real->mem = priv->Saved##mem; \
|
||||
}
|
||||
|
||||
#ifdef HAVE_TYPEOF
|
||||
#define swap(priv, real, mem) {\
|
||||
typeof(real->mem) tmp = priv->Saved##mem; \
|
||||
priv->Saved##mem = real->mem; \
|
||||
real->mem = tmp; \
|
||||
}
|
||||
#else
|
||||
#define swap(priv, real, mem) {\
|
||||
const void *tmp = priv->Saved##mem; \
|
||||
priv->Saved##mem = real->mem; \
|
||||
real->mem = tmp; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define EXA_PRE_FALLBACK(_screen_) \
|
||||
ExaScreenPriv(_screen_); \
|
||||
pExaScr->fallback_counter++;
|
||||
|
||||
#define EXA_POST_FALLBACK(_screen_) \
|
||||
pExaScr->fallback_counter--;
|
||||
|
||||
#define EXA_PRE_FALLBACK_GC(_gc_) \
|
||||
ExaScreenPriv(_gc_->pScreen); \
|
||||
ExaGCPriv(_gc_); \
|
||||
pExaScr->fallback_counter++; \
|
||||
swap(pExaGC, _gc_, ops);
|
||||
|
||||
#define EXA_POST_FALLBACK_GC(_gc_) \
|
||||
pExaScr->fallback_counter--; \
|
||||
swap(pExaGC, _gc_, ops);
|
||||
|
||||
/** Align an offset to an arbitrary alignment */
|
||||
#define EXA_ALIGN(offset, align) (((offset) + (align) - 1) - \
|
||||
(((offset) + (align) - 1) % (align)))
|
||||
/** Align an offset to a power-of-two alignment */
|
||||
#define EXA_ALIGN2(offset, align) (((offset) + (align) - 1) & ~((align) - 1))
|
||||
|
||||
#define EXA_PIXMAP_SCORE_MOVE_IN 10
|
||||
#define EXA_PIXMAP_SCORE_MAX 20
|
||||
#define EXA_PIXMAP_SCORE_MOVE_OUT -10
|
||||
#define EXA_PIXMAP_SCORE_MIN -20
|
||||
#define EXA_PIXMAP_SCORE_PINNED 1000
|
||||
#define EXA_PIXMAP_SCORE_INIT 1001
|
||||
|
||||
#define ExaGetPixmapPriv(p) ((ExaPixmapPrivPtr)dixGetPrivateAddr(&(p)->devPrivates, &ExaGetScreenPriv((p)->drawable.pScreen)->pixmapPrivateKeyRec))
|
||||
#define ExaPixmapPriv(p) ExaPixmapPrivPtr pExaPixmap = ExaGetPixmapPriv(p)
|
||||
|
||||
#define EXA_RANGE_PITCH (1 << 0)
|
||||
#define EXA_RANGE_WIDTH (1 << 1)
|
||||
#define EXA_RANGE_HEIGHT (1 << 2)
|
||||
|
||||
typedef struct {
|
||||
ExaOffscreenArea *area;
|
||||
int score; /**< score for the move-in vs move-out heuristic */
|
||||
Bool use_gpu_copy;
|
||||
|
||||
CARD8 *sys_ptr; /**< pointer to pixmap data in system memory */
|
||||
int sys_pitch; /**< pitch of pixmap in system memory */
|
||||
|
||||
CARD8 *fb_ptr; /**< pointer to pixmap data in framebuffer memory */
|
||||
int fb_pitch; /**< pitch of pixmap in framebuffer memory */
|
||||
unsigned int fb_size; /**< size of pixmap in framebuffer memory */
|
||||
|
||||
/**
|
||||
* Holds information about whether this pixmap can be used for
|
||||
* acceleration (== 0) or not (> 0).
|
||||
*
|
||||
* Contains a OR'ed combination of the following values:
|
||||
* EXA_RANGE_PITCH - set if the pixmap's pitch is out of range
|
||||
* EXA_RANGE_WIDTH - set if the pixmap's width is out of range
|
||||
* EXA_RANGE_HEIGHT - set if the pixmap's height is out of range
|
||||
*/
|
||||
unsigned int accel_blocked;
|
||||
|
||||
/**
|
||||
* The damage record contains the areas of the pixmap's current location
|
||||
* (framebuffer or system) that have been damaged compared to the other
|
||||
* location.
|
||||
*/
|
||||
DamagePtr pDamage;
|
||||
/**
|
||||
* The valid regions mark the valid bits (at least, as they're derived from
|
||||
* damage, which may be overreported) of a pixmap's system and FB copies.
|
||||
*/
|
||||
RegionRec validSys, validFB;
|
||||
/**
|
||||
* Driver private storage per EXA pixmap
|
||||
*/
|
||||
void *driverPriv;
|
||||
} ExaPixmapPrivRec, *ExaPixmapPrivPtr;
|
||||
|
||||
typedef struct {
|
||||
/* GC values from the layer below. */
|
||||
const GCOps *Savedops;
|
||||
const GCFuncs *Savedfuncs;
|
||||
} ExaGCPrivRec, *ExaGCPrivPtr;
|
||||
|
||||
typedef struct {
|
||||
PicturePtr pDst;
|
||||
INT16 xSrc;
|
||||
INT16 ySrc;
|
||||
INT16 xMask;
|
||||
INT16 yMask;
|
||||
INT16 xDst;
|
||||
INT16 yDst;
|
||||
INT16 width;
|
||||
INT16 height;
|
||||
} ExaCompositeRectRec, *ExaCompositeRectPtr;
|
||||
|
||||
/**
|
||||
* exaDDXDriverInit must be implemented by the DDX using EXA, and is the place
|
||||
* to set EXA options or hook in screen functions to handle using EXA as the AA.
|
||||
*/
|
||||
void exaDDXDriverInit(ScreenPtr pScreen);
|
||||
|
||||
/* exa_unaccel.c */
|
||||
void
|
||||
exaPrepareAccessGC(GCPtr pGC);
|
||||
|
||||
void
|
||||
exaFinishAccessGC(GCPtr pGC);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
|
||||
DDXPointPtr ppt, int *pwidth, int fSorted);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
|
||||
int x, int y, int w, int h, int leftPad, int format,
|
||||
char *bits);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
|
||||
Bool upsidedown, Pixel bitplane, void *closure);
|
||||
|
||||
RegionPtr
|
||||
|
||||
ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty);
|
||||
|
||||
RegionPtr
|
||||
|
||||
ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty,
|
||||
unsigned long bitPlane);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
|
||||
DDXPointPtr pptInit);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int mode, int npt, DDXPointPtr ppt);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nsegInit, xSegment * pSegInit);
|
||||
|
||||
void
|
||||
ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nrect, xRectangle *prect);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckPushPixels(GCPtr pGC, PixmapPtr pBitmap,
|
||||
DrawablePtr pDrawable, int w, int h, int x, int y);
|
||||
|
||||
void
|
||||
ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
||||
unsigned int format, unsigned long planeMask, char *d);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckGetSpans(DrawablePtr pDrawable,
|
||||
int wMax,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckAddTraps(PicturePtr pPicture,
|
||||
INT16 x_off, INT16 y_off, int ntrap, xTrap * traps);
|
||||
|
||||
/* exa_accel.c */
|
||||
|
||||
static _X_INLINE Bool
|
||||
exaGCReadsDestination(DrawablePtr pDrawable, unsigned long planemask,
|
||||
unsigned int fillStyle, unsigned char alu,
|
||||
Bool clientClip)
|
||||
{
|
||||
return ((alu != GXcopy && alu != GXclear && alu != GXset &&
|
||||
alu != GXcopyInverted) || fillStyle == FillStippled ||
|
||||
clientClip != FALSE || !EXA_PM_IS_SOLID(pDrawable, planemask));
|
||||
}
|
||||
|
||||
void
|
||||
exaCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
|
||||
|
||||
Bool
|
||||
|
||||
exaFillRegionTiled(DrawablePtr pDrawable, RegionPtr pRegion, PixmapPtr pTile,
|
||||
DDXPointPtr pPatOrg, CARD32 planemask, CARD32 alu,
|
||||
Bool clientClip);
|
||||
|
||||
void
|
||||
|
||||
exaGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
||||
unsigned int format, unsigned long planeMask, char *d);
|
||||
|
||||
RegionPtr
|
||||
|
||||
exaCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
|
||||
int srcx, int srcy, int width, int height, int dstx, int dsty);
|
||||
|
||||
Bool
|
||||
|
||||
exaHWCopyNtoN(DrawablePtr pSrcDrawable,
|
||||
DrawablePtr pDstDrawable,
|
||||
GCPtr pGC,
|
||||
BoxPtr pbox,
|
||||
int nbox, int dx, int dy, Bool reverse, Bool upsidedown);
|
||||
|
||||
void
|
||||
|
||||
exaCopyNtoN(DrawablePtr pSrcDrawable,
|
||||
DrawablePtr pDstDrawable,
|
||||
GCPtr pGC,
|
||||
BoxPtr pbox,
|
||||
int nbox,
|
||||
int dx,
|
||||
int dy,
|
||||
Bool reverse, Bool upsidedown, Pixel bitplane, void *closure);
|
||||
|
||||
extern const GCOps exaOps;
|
||||
|
||||
void
|
||||
|
||||
ExaCheckComposite(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
|
||||
|
||||
void
|
||||
|
||||
ExaCheckGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs);
|
||||
|
||||
/* exa_offscreen.c */
|
||||
void
|
||||
ExaOffscreenSwapOut(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ExaOffscreenSwapIn(ScreenPtr pScreen);
|
||||
|
||||
ExaOffscreenArea *ExaOffscreenDefragment(ScreenPtr pScreen);
|
||||
|
||||
Bool
|
||||
exaOffscreenInit(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
ExaOffscreenFini(ScreenPtr pScreen);
|
||||
|
||||
/* exa.c */
|
||||
Bool
|
||||
ExaDoPrepareAccess(PixmapPtr pPixmap, int index);
|
||||
|
||||
void
|
||||
exaPrepareAccess(DrawablePtr pDrawable, int index);
|
||||
|
||||
void
|
||||
exaFinishAccess(DrawablePtr pDrawable, int index);
|
||||
|
||||
void
|
||||
exaDestroyPixmap(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaPixmapDirty(PixmapPtr pPix, int x1, int y1, int x2, int y2);
|
||||
|
||||
void
|
||||
|
||||
exaGetDrawableDeltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
|
||||
int *xp, int *yp);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy(PixmapPtr p);
|
||||
|
||||
PixmapPtr
|
||||
exaGetOffscreenPixmap(DrawablePtr pDrawable, int *xp, int *yp);
|
||||
|
||||
PixmapPtr
|
||||
exaGetDrawablePixmap(DrawablePtr pDrawable);
|
||||
|
||||
void
|
||||
|
||||
exaSetFbPitch(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
|
||||
int w, int h, int bpp);
|
||||
|
||||
void
|
||||
|
||||
exaSetAccelBlock(ExaScreenPrivPtr pExaScr, ExaPixmapPrivPtr pExaPixmap,
|
||||
int w, int h, int bpp);
|
||||
|
||||
void
|
||||
exaDoMigration(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
Bool
|
||||
exaPixmapIsPinned(PixmapPtr pPix);
|
||||
|
||||
extern const GCFuncs exaGCFuncs;
|
||||
|
||||
/* exa_classic.c */
|
||||
PixmapPtr
|
||||
|
||||
exaCreatePixmap_classic(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint);
|
||||
|
||||
Bool
|
||||
|
||||
exaModifyPixmapHeader_classic(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData);
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_classic(PixmapPtr pPixmap);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap);
|
||||
|
||||
/* exa_driver.c */
|
||||
PixmapPtr
|
||||
|
||||
exaCreatePixmap_driver(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint);
|
||||
|
||||
Bool
|
||||
|
||||
exaModifyPixmapHeader_driver(PixmapPtr pPixmap, int width, int height,
|
||||
int depth, int bitsPerPixel, int devKind,
|
||||
void *pPixData);
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_driver(PixmapPtr pPixmap);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_driver(PixmapPtr pPixmap);
|
||||
|
||||
/* exa_mixed.c */
|
||||
PixmapPtr
|
||||
|
||||
exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
|
||||
unsigned usage_hint);
|
||||
|
||||
Bool
|
||||
|
||||
exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
|
||||
int bitsPerPixel, int devKind, void *pPixData);
|
||||
|
||||
Bool
|
||||
exaDestroyPixmap_mixed(PixmapPtr pPixmap);
|
||||
|
||||
Bool
|
||||
exaPixmapHasGpuCopy_mixed(PixmapPtr pPixmap);
|
||||
|
||||
/* exa_migration_mixed.c */
|
||||
void
|
||||
exaCreateDriverPixmap_mixed(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
void
|
||||
exaMoveInPixmap_mixed(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaDamageReport_mixed(DamagePtr pDamage, RegionPtr pRegion, void *closure);
|
||||
|
||||
void
|
||||
exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg);
|
||||
|
||||
Bool
|
||||
exaSetSharedPixmapBacking_mixed(PixmapPtr pPixmap, void *handle);
|
||||
Bool
|
||||
exaSharePixmapBacking_mixed(PixmapPtr pPixmap, ScreenPtr secondary, void **handle_p);
|
||||
|
||||
/* exa_render.c */
|
||||
Bool
|
||||
exaOpReadsDestination(CARD8 op);
|
||||
|
||||
void
|
||||
|
||||
exaComposite(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
|
||||
|
||||
void
|
||||
|
||||
exaCompositeRects(CARD8 op,
|
||||
PicturePtr Src,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst, int nrect, ExaCompositeRectPtr rects);
|
||||
|
||||
void
|
||||
|
||||
exaTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
|
||||
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
|
||||
int ntrap, xTrapezoid * traps);
|
||||
|
||||
void
|
||||
|
||||
exaTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
|
||||
PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
|
||||
int ntri, xTriangle * tris);
|
||||
|
||||
/* exa_glyph.c */
|
||||
void
|
||||
exaGlyphsInit(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
exaGlyphsFini(ScreenPtr pScreen);
|
||||
|
||||
void
|
||||
|
||||
exaGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs);
|
||||
|
||||
/* exa_migration_classic.c */
|
||||
void
|
||||
exaCopyDirtyToSys(ExaMigrationPtr migrate);
|
||||
|
||||
void
|
||||
exaCopyDirtyToFb(ExaMigrationPtr migrate);
|
||||
|
||||
void
|
||||
exaDoMigration_classic(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
|
||||
|
||||
void
|
||||
exaPixmapSave(ScreenPtr pScreen, ExaOffscreenArea * area);
|
||||
|
||||
void
|
||||
exaMoveOutPixmap_classic(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaMoveInPixmap_classic(PixmapPtr pPixmap);
|
||||
|
||||
void
|
||||
exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg);
|
||||
|
||||
#endif /* EXAPRIV_H */
|
1229
exa/exa_render.c
1229
exa/exa_render.c
File diff suppressed because it is too large
Load Diff
|
@ -1,733 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* Copyright © 1999 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation, and that the name of Keith Packard not be used in
|
||||
* advertising or publicity pertaining to distribution of the software without
|
||||
* specific, written prior permission. Keith Packard makes no
|
||||
* representations about the suitability of this software for any purpose. It
|
||||
* is provided "as is" without express or implied warranty.
|
||||
*
|
||||
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "exa_priv.h"
|
||||
|
||||
#include "mipict.h"
|
||||
|
||||
/*
|
||||
* These functions wrap the low-level fb rendering functions and
|
||||
* synchronize framebuffer/accelerated drawing by stalling until
|
||||
* the accelerator is idle
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calls exaPrepareAccess with EXA_PREPARE_SRC for the tile, if that is the
|
||||
* current fill style.
|
||||
*
|
||||
* Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
|
||||
* 1bpp and never in fb, so we don't worry about them.
|
||||
* We should worry about them for completeness sake and going forward.
|
||||
*/
|
||||
void
|
||||
exaPrepareAccessGC(GCPtr pGC)
|
||||
{
|
||||
if (pGC->stipple)
|
||||
exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
|
||||
if (pGC->fillStyle == FillTiled)
|
||||
exaPrepareAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes access to the tile in the GC, if used.
|
||||
*/
|
||||
void
|
||||
exaFinishAccessGC(GCPtr pGC)
|
||||
{
|
||||
if (pGC->fillStyle == FillTiled)
|
||||
exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_SRC);
|
||||
if (pGC->stipple)
|
||||
exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
|
||||
}
|
||||
|
||||
#if DEBUG_TRACE_FALL
|
||||
char
|
||||
exaDrawableLocation(DrawablePtr pDrawable)
|
||||
{
|
||||
return exaDrawableIsOffscreen(pDrawable) ? 's' : 'm';
|
||||
}
|
||||
#endif /* DEBUG_TRACE_FALL */
|
||||
|
||||
void
|
||||
ExaCheckFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
|
||||
DDXPointPtr ppt, int *pwidth, int fSorted)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->FillSpans(pDrawable, pGC, nspans, ppt, pwidth, fSorted);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
pGC->ops->SetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPutImage(DrawablePtr pDrawable, GCPtr pGC, int depth,
|
||||
int x, int y, int w, int h, int leftPad, int format,
|
||||
char *bits)
|
||||
{
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
|
||||
|
||||
ExaPixmapPriv(pPixmap);
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
|
||||
exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
|
||||
pGC->alu, pGC->clientClip != NULL))
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
else
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
|
||||
DamagePendingRegion(pExaPixmap->pDamage));
|
||||
pGC->ops->PutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
|
||||
bits);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckCopyNtoN(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
BoxPtr pbox, int nbox, int dx, int dy, Bool reverse,
|
||||
Bool upsidedown, Pixel bitplane, void *closure)
|
||||
{
|
||||
RegionRec reg;
|
||||
int xoff, yoff;
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
|
||||
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
|
||||
|
||||
if (pExaScr->prepare_access_reg && RegionInitBoxes(®, pbox, nbox)) {
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pSrc);
|
||||
|
||||
exaGetDrawableDeltas(pSrc, pPixmap, &xoff, &yoff);
|
||||
RegionTranslate(®, xoff + dx, yoff + dy);
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, ®);
|
||||
RegionUninit(®);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pSrc, EXA_PREPARE_SRC);
|
||||
|
||||
if (pExaScr->prepare_access_reg &&
|
||||
!exaGCReadsDestination(pDst, pGC->planemask, pGC->fillStyle,
|
||||
pGC->alu, pGC->clientClip != NULL) &&
|
||||
RegionInitBoxes(®, pbox, nbox)) {
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pDst);
|
||||
|
||||
exaGetDrawableDeltas(pDst, pPixmap, &xoff, &yoff);
|
||||
RegionTranslate(®, xoff, yoff);
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST, ®);
|
||||
RegionUninit(®);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pDst, EXA_PREPARE_DEST);
|
||||
|
||||
/* This will eventually call fbCopyNtoN, with some calculation overhead. */
|
||||
while (nbox--) {
|
||||
pGC->ops->CopyArea(pSrc, pDst, pGC, pbox->x1 - pSrc->x + dx,
|
||||
pbox->y1 - pSrc->y + dy, pbox->x2 - pbox->x1,
|
||||
pbox->y2 - pbox->y1, pbox->x1 - pDst->x,
|
||||
pbox->y1 - pDst->y);
|
||||
pbox++;
|
||||
}
|
||||
exaFinishAccess(pSrc, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
static void
|
||||
ExaFallbackPrepareReg(DrawablePtr pDrawable,
|
||||
GCPtr pGC,
|
||||
int x, int y, int width, int height,
|
||||
int index, Bool checkReads)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
|
||||
if (pExaScr->prepare_access_reg &&
|
||||
!(checkReads && exaGCReadsDestination(pDrawable, pGC->planemask,
|
||||
pGC->fillStyle, pGC->alu,
|
||||
pGC->clientClip != NULL))) {
|
||||
BoxRec box;
|
||||
RegionRec reg;
|
||||
int xoff, yoff;
|
||||
PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
|
||||
|
||||
exaGetDrawableDeltas(pDrawable, pPixmap, &xoff, &yoff);
|
||||
box.x1 = pDrawable->x + x + xoff;
|
||||
box.y1 = pDrawable->y + y + yoff;
|
||||
box.x2 = box.x1 + width;
|
||||
box.y2 = box.y1 + height;
|
||||
|
||||
RegionInit(®, &box, 1);
|
||||
pExaScr->prepare_access_reg(pPixmap, index, ®);
|
||||
RegionUninit(®);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pDrawable, index);
|
||||
}
|
||||
|
||||
RegionPtr
|
||||
ExaCheckCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty)
|
||||
{
|
||||
RegionPtr ret;
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
|
||||
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
|
||||
ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE);
|
||||
ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE);
|
||||
ret = pGC->ops->CopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty);
|
||||
exaFinishAccess(pSrc, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
RegionPtr
|
||||
ExaCheckCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
|
||||
int srcx, int srcy, int w, int h, int dstx, int dsty,
|
||||
unsigned long bitPlane)
|
||||
{
|
||||
RegionPtr ret;
|
||||
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
|
||||
exaDrawableLocation(pSrc), exaDrawableLocation(pDst)));
|
||||
ExaFallbackPrepareReg(pSrc, pGC, srcx, srcy, w, h, EXA_PREPARE_SRC, FALSE);
|
||||
ExaFallbackPrepareReg(pDst, pGC, dstx, dsty, w, h, EXA_PREPARE_DEST, TRUE);
|
||||
ret = pGC->ops->CopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty,
|
||||
bitPlane);
|
||||
exaFinishAccess(pSrc, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
|
||||
DDXPointPtr pptInit)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
pGC->ops->PolyPoint(pDrawable, pGC, mode, npt, pptInit);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolylines(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int mode, int npt, DDXPointPtr ppt)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
|
||||
pDrawable, exaDrawableLocation(pDrawable),
|
||||
pGC->lineWidth, mode, npt));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->Polylines(pDrawable, pGC, mode, npt, ppt);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolySegment(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nsegInit, xSegment * pSegInit)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
|
||||
exaDrawableLocation(pDrawable), pGC->lineWidth, nsegInit));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolySegment(pDrawable, pGC, nsegInit, pSegInit);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyArc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolyArc(pDrawable, pGC, narcs, pArcs);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int nrect, xRectangle *prect)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolyFillRect(pDrawable, pGC, nrect, prect);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC,
|
||||
int x, int y, unsigned int nglyph,
|
||||
CharInfoPtr * ppci, void *pglyphBase)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
|
||||
exaDrawableLocation(pDrawable), pGC->fillStyle, pGC->alu));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckPushPixels(GCPtr pGC, PixmapPtr pBitmap,
|
||||
DrawablePtr pDrawable, int w, int h, int x, int y)
|
||||
{
|
||||
EXA_PRE_FALLBACK_GC(pGC);
|
||||
EXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
|
||||
exaDrawableLocation(&pBitmap->drawable),
|
||||
exaDrawableLocation(pDrawable)));
|
||||
ExaFallbackPrepareReg(pDrawable, pGC, x, y, w, h, EXA_PREPARE_DEST, TRUE);
|
||||
ExaFallbackPrepareReg(&pBitmap->drawable, pGC, 0, 0, w, h,
|
||||
EXA_PREPARE_SRC, FALSE);
|
||||
exaPrepareAccessGC(pGC);
|
||||
pGC->ops->PushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
|
||||
exaFinishAccessGC(pGC);
|
||||
exaFinishAccess(&pBitmap->drawable, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK_GC(pGC);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
|
||||
{
|
||||
DrawablePtr pDrawable = &pWin->drawable;
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
EXA_FALLBACK(("from %p\n", pWin));
|
||||
|
||||
/* Only need the source bits, the destination region will be overwritten */
|
||||
if (pExaScr->prepare_access_reg) {
|
||||
PixmapPtr pPixmap = pScreen->GetWindowPixmap(pWin);
|
||||
int xoff, yoff;
|
||||
|
||||
exaGetDrawableDeltas(&pWin->drawable, pPixmap, &xoff, &yoff);
|
||||
RegionTranslate(prgnSrc, xoff, yoff);
|
||||
pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_SRC, prgnSrc);
|
||||
RegionTranslate(prgnSrc, -xoff, -yoff);
|
||||
}
|
||||
else
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
|
||||
swap(pExaScr, pScreen, CopyWindow);
|
||||
pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
|
||||
swap(pExaScr, pScreen, CopyWindow);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
|
||||
unsigned int format, unsigned long planeMask, char *d)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
|
||||
ExaFallbackPrepareReg(pDrawable, NULL, x, y, w, h, EXA_PREPARE_SRC, FALSE);
|
||||
swap(pExaScr, pScreen, GetImage);
|
||||
pScreen->GetImage(pDrawable, x, y, w, h, format, planeMask, d);
|
||||
swap(pExaScr, pScreen, GetImage);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckGetSpans(DrawablePtr pDrawable,
|
||||
int wMax,
|
||||
DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
EXA_FALLBACK(("from %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
|
||||
exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
swap(pExaScr, pScreen, GetSpans);
|
||||
pScreen->GetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
|
||||
swap(pExaScr, pScreen, GetSpans);
|
||||
exaFinishAccess(pDrawable, EXA_PREPARE_SRC);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
static void
|
||||
ExaSrcValidate(DrawablePtr pDrawable,
|
||||
int x, int y, int width, int height, unsigned int subWindowMode)
|
||||
{
|
||||
ScreenPtr pScreen = pDrawable->pScreen;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
PixmapPtr pPix = exaGetDrawablePixmap(pDrawable);
|
||||
BoxRec box;
|
||||
RegionRec reg;
|
||||
RegionPtr dst;
|
||||
int xoff, yoff;
|
||||
|
||||
if (pExaScr->srcPix == pPix)
|
||||
dst = &pExaScr->srcReg;
|
||||
else if (pExaScr->maskPix == pPix)
|
||||
dst = &pExaScr->maskReg;
|
||||
else
|
||||
return;
|
||||
|
||||
exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
|
||||
|
||||
box.x1 = x + xoff;
|
||||
box.y1 = y + yoff;
|
||||
box.x2 = box.x1 + width;
|
||||
box.y2 = box.y1 + height;
|
||||
|
||||
RegionInit(®, &box, 1);
|
||||
RegionUnion(dst, dst, ®);
|
||||
RegionUninit(®);
|
||||
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
pScreen->SourceValidate(pDrawable, x, y, width, height, subWindowMode);
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
}
|
||||
|
||||
static Bool
|
||||
ExaPrepareCompositeReg(ScreenPtr pScreen,
|
||||
CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
|
||||
{
|
||||
RegionRec region;
|
||||
RegionPtr dstReg = NULL;
|
||||
RegionPtr srcReg = NULL;
|
||||
RegionPtr maskReg = NULL;
|
||||
PixmapPtr pSrcPix = NULL;
|
||||
PixmapPtr pMaskPix = NULL;
|
||||
PixmapPtr pDstPix;
|
||||
|
||||
ExaScreenPriv(pScreen);
|
||||
Bool ret;
|
||||
|
||||
RegionNull(®ion);
|
||||
|
||||
if (pSrc->pDrawable) {
|
||||
pSrcPix = exaGetDrawablePixmap(pSrc->pDrawable);
|
||||
RegionNull(&pExaScr->srcReg);
|
||||
srcReg = &pExaScr->srcReg;
|
||||
pExaScr->srcPix = pSrcPix;
|
||||
if (pSrc != pDst)
|
||||
RegionTranslate(pSrc->pCompositeClip,
|
||||
-pSrc->pDrawable->x, -pSrc->pDrawable->y);
|
||||
} else
|
||||
pExaScr->srcPix = NULL;
|
||||
|
||||
if (pMask && pMask->pDrawable) {
|
||||
pMaskPix = exaGetDrawablePixmap(pMask->pDrawable);
|
||||
RegionNull(&pExaScr->maskReg);
|
||||
maskReg = &pExaScr->maskReg;
|
||||
pExaScr->maskPix = pMaskPix;
|
||||
if (pMask != pDst && pMask != pSrc)
|
||||
RegionTranslate(pMask->pCompositeClip,
|
||||
-pMask->pDrawable->x, -pMask->pDrawable->y);
|
||||
} else
|
||||
pExaScr->maskPix = NULL;
|
||||
|
||||
RegionTranslate(pDst->pCompositeClip,
|
||||
-pDst->pDrawable->x, -pDst->pDrawable->y);
|
||||
|
||||
pExaScr->SavedSourceValidate = ExaSrcValidate;
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
ret = miComputeCompositeRegion(®ion, pSrc, pMask, pDst,
|
||||
xSrc, ySrc, xMask, yMask,
|
||||
xDst, yDst, width, height);
|
||||
swap(pExaScr, pScreen, SourceValidate);
|
||||
|
||||
RegionTranslate(pDst->pCompositeClip,
|
||||
pDst->pDrawable->x, pDst->pDrawable->y);
|
||||
if (pSrc->pDrawable && pSrc != pDst)
|
||||
RegionTranslate(pSrc->pCompositeClip,
|
||||
pSrc->pDrawable->x, pSrc->pDrawable->y);
|
||||
if (pMask && pMask->pDrawable && pMask != pDst && pMask != pSrc)
|
||||
RegionTranslate(pMask->pCompositeClip,
|
||||
pMask->pDrawable->x, pMask->pDrawable->y);
|
||||
|
||||
if (!ret) {
|
||||
if (srcReg)
|
||||
RegionUninit(srcReg);
|
||||
if (maskReg)
|
||||
RegionUninit(maskReg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't limit alphamaps readbacks for now until we've figured out how that
|
||||
* should be done.
|
||||
*/
|
||||
|
||||
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
|
||||
pExaScr->
|
||||
prepare_access_reg(exaGetDrawablePixmap(pSrc->alphaMap->pDrawable),
|
||||
EXA_PREPARE_AUX_SRC, NULL);
|
||||
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
|
||||
pExaScr->
|
||||
prepare_access_reg(exaGetDrawablePixmap(pMask->alphaMap->pDrawable),
|
||||
EXA_PREPARE_AUX_MASK, NULL);
|
||||
|
||||
if (pSrcPix)
|
||||
pExaScr->prepare_access_reg(pSrcPix, EXA_PREPARE_SRC, srcReg);
|
||||
|
||||
if (pMaskPix)
|
||||
pExaScr->prepare_access_reg(pMaskPix, EXA_PREPARE_MASK, maskReg);
|
||||
|
||||
if (srcReg)
|
||||
RegionUninit(srcReg);
|
||||
if (maskReg)
|
||||
RegionUninit(maskReg);
|
||||
|
||||
pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
|
||||
if (!exaOpReadsDestination(op)) {
|
||||
int xoff;
|
||||
int yoff;
|
||||
|
||||
exaGetDrawableDeltas(pDst->pDrawable, pDstPix, &xoff, &yoff);
|
||||
RegionTranslate(®ion, pDst->pDrawable->x + xoff,
|
||||
pDst->pDrawable->y + yoff);
|
||||
dstReg = ®ion;
|
||||
}
|
||||
|
||||
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
|
||||
pExaScr->
|
||||
prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
|
||||
EXA_PREPARE_AUX_DEST, dstReg);
|
||||
pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, dstReg);
|
||||
|
||||
RegionUninit(®ion);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckComposite(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pMask,
|
||||
PicturePtr pDst,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc,
|
||||
INT16 xMask,
|
||||
INT16 yMask,
|
||||
INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
||||
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
|
||||
if (pExaScr->prepare_access_reg) {
|
||||
if (!ExaPrepareCompositeReg(pScreen, op, pSrc, pMask, pDst, xSrc,
|
||||
ySrc, xMask, yMask, xDst, yDst, width,
|
||||
height))
|
||||
goto out_no_clip;
|
||||
}
|
||||
else {
|
||||
|
||||
/* We need to prepare access to any separate alpha maps first,
|
||||
* in case the driver doesn't support EXA_PREPARE_AUX*,
|
||||
* in which case EXA_PREPARE_SRC may be used for moving them out.
|
||||
*/
|
||||
|
||||
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
|
||||
exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
|
||||
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
|
||||
exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
|
||||
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
|
||||
exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
|
||||
|
||||
exaPrepareAccess(pDst->pDrawable, EXA_PREPARE_DEST);
|
||||
|
||||
EXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
|
||||
|
||||
if (pSrc->pDrawable != NULL)
|
||||
exaPrepareAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
|
||||
if (pMask && pMask->pDrawable != NULL)
|
||||
exaPrepareAccess(pMask->pDrawable, EXA_PREPARE_MASK);
|
||||
}
|
||||
|
||||
swap(pExaScr, ps, Composite);
|
||||
ps->Composite(op,
|
||||
pSrc,
|
||||
pMask,
|
||||
pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
|
||||
swap(pExaScr, ps, Composite);
|
||||
if (pMask && pMask->pDrawable != NULL)
|
||||
exaFinishAccess(pMask->pDrawable, EXA_PREPARE_MASK);
|
||||
if (pSrc->pDrawable != NULL)
|
||||
exaFinishAccess(pSrc->pDrawable, EXA_PREPARE_SRC);
|
||||
exaFinishAccess(pDst->pDrawable, EXA_PREPARE_DEST);
|
||||
if (pDst->alphaMap && pDst->alphaMap->pDrawable)
|
||||
exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
|
||||
if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
|
||||
exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
|
||||
if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
|
||||
exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
|
||||
|
||||
out_no_clip:
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid migration ping-pong when using a mask.
|
||||
*/
|
||||
void
|
||||
ExaCheckGlyphs(CARD8 op,
|
||||
PicturePtr pSrc,
|
||||
PicturePtr pDst,
|
||||
PictFormatPtr maskFormat,
|
||||
INT16 xSrc,
|
||||
INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
|
||||
{
|
||||
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
|
||||
miGlyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
|
||||
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
void
|
||||
ExaCheckAddTraps(PicturePtr pPicture,
|
||||
INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
|
||||
{
|
||||
ScreenPtr pScreen = pPicture->pDrawable->pScreen;
|
||||
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
||||
|
||||
EXA_PRE_FALLBACK(pScreen);
|
||||
|
||||
EXA_FALLBACK(("to pict %p (%c)\n", pPicture,
|
||||
exaDrawableLocation(pPicture->pDrawable)));
|
||||
exaPrepareAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||
swap(pExaScr, ps, AddTraps);
|
||||
ps->AddTraps(pPicture, x_off, y_off, ntrap, traps);
|
||||
swap(pExaScr, ps, AddTraps);
|
||||
exaFinishAccess(pPicture->pDrawable, EXA_PREPARE_DEST);
|
||||
EXA_POST_FALLBACK(pScreen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 0,0 pixel of a pixmap. Used for doing solid fills of tiled pixmaps
|
||||
* that happen to be 1x1. Pixmap must be at least 8bpp.
|
||||
*/
|
||||
CARD32
|
||||
exaGetPixmapFirstPixel(PixmapPtr pPixmap)
|
||||
{
|
||||
switch (pPixmap->drawable.bitsPerPixel) {
|
||||
case 32:
|
||||
{
|
||||
CARD32 pixel;
|
||||
|
||||
pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
|
||||
ZPixmap, ~0, (char *) &pixel);
|
||||
return pixel;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
CARD16 pixel;
|
||||
|
||||
pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
|
||||
ZPixmap, ~0, (char *) &pixel);
|
||||
return pixel;
|
||||
}
|
||||
case 8:
|
||||
case 4:
|
||||
case 1:
|
||||
{
|
||||
CARD8 pixel;
|
||||
|
||||
pPixmap->drawable.pScreen->GetImage(&pPixmap->drawable, 0, 0, 1, 1,
|
||||
ZPixmap, ~0, (char *) &pixel);
|
||||
return pixel;
|
||||
}
|
||||
default:
|
||||
FatalError("%s called for invalid bpp %d\n", __func__,
|
||||
pPixmap->drawable.bitsPerPixel);
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
srcs_exa = [
|
||||
'exa.c',
|
||||
'exa_classic.c',
|
||||
'exa_migration_classic.c',
|
||||
'exa_driver.c',
|
||||
'exa_mixed.c',
|
||||
'exa_migration_mixed.c',
|
||||
'exa_accel.c',
|
||||
'exa_glyphs.c',
|
||||
'exa_offscreen.c',
|
||||
'exa_render.c',
|
||||
'exa_unaccel.c',
|
||||
]
|
||||
|
||||
libxserver_exa = static_library('libxserver_exa',
|
||||
srcs_exa,
|
||||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
c_args: '-DHAVE_XORG_CONFIG_H'
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data('exa.h', install_dir: xorgsdkdir)
|
||||
endif
|
|
@ -1,49 +0,0 @@
|
|||
noinst_LTLIBRARIES = libfb.la libwfb.la
|
||||
|
||||
AM_CFLAGS = $(DIX_CFLAGS)
|
||||
|
||||
if XORG
|
||||
sdk_HEADERS = fb.h fbrop.h fboverlay.h wfbrename.h fbpict.h
|
||||
endif
|
||||
|
||||
libfb_la_CFLAGS = $(AM_CFLAGS)
|
||||
libfb_la_LIBADD = $(PIXMAN_LIBS)
|
||||
|
||||
libwfb_la_CFLAGS = $(AM_CFLAGS) -DFB_ACCESS_WRAPPER
|
||||
libwfb_la_LIBADD = $(PIXMAN_LIBS)
|
||||
|
||||
libfb_la_SOURCES = \
|
||||
fb.h \
|
||||
fballpriv.c \
|
||||
fbarc.c \
|
||||
fbbits.c \
|
||||
fbbits.h \
|
||||
fbblt.c \
|
||||
fbbltone.c \
|
||||
fbcmap_mi.c \
|
||||
fbcopy.c \
|
||||
fbfill.c \
|
||||
fbfillrect.c \
|
||||
fbfillsp.c \
|
||||
fbgc.c \
|
||||
fbgetsp.c \
|
||||
fbglyph.c \
|
||||
fbimage.c \
|
||||
fbline.c \
|
||||
fboverlay.c \
|
||||
fboverlay.h \
|
||||
fbpict.c \
|
||||
fbpict.h \
|
||||
fbpixmap.c \
|
||||
fbpoint.c \
|
||||
fbpush.c \
|
||||
fbrop.h \
|
||||
fbscreen.c \
|
||||
fbseg.c \
|
||||
fbsetsp.c \
|
||||
fbsolid.c \
|
||||
fbtrap.c \
|
||||
fbutil.c \
|
||||
fbwindow.c
|
||||
|
||||
libwfb_la_SOURCES = $(libfb_la_SOURCES)
|
|
@ -53,5 +53,3 @@ libxserver_wfb = static_library('libxserver_wfb',
|
|||
pic: true,
|
||||
build_by_default: false,
|
||||
)
|
||||
|
||||
install_data(hdrs_fb, install_dir: xorgsdkdir)
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
noinst_LTLIBRARIES = libglamor.la libglamor_egl_stubs.la
|
||||
|
||||
libglamor_la_LIBADD = $(GLAMOR_LIBS)
|
||||
|
||||
AM_CFLAGS = $(CWARNFLAGS) $(DIX_CFLAGS) $(GLAMOR_CFLAGS)
|
||||
|
||||
libglamor_la_SOURCES = \
|
||||
glamor.c \
|
||||
glamor_context.h \
|
||||
glamor_copy.c \
|
||||
glamor_core.c \
|
||||
glamor_dash.c \
|
||||
glamor_debug.h \
|
||||
glamor_font.c \
|
||||
glamor_font.h \
|
||||
glamor_glx.c \
|
||||
glamor_composite_glyphs.c \
|
||||
glamor_image.c \
|
||||
glamor_lines.c \
|
||||
glamor_segs.c \
|
||||
glamor_render.c \
|
||||
glamor_gradient.c \
|
||||
glamor_prepare.c \
|
||||
glamor_prepare.h \
|
||||
glamor_program.c \
|
||||
glamor_program.h \
|
||||
glamor_rects.c \
|
||||
glamor_spans.c \
|
||||
glamor_text.c \
|
||||
glamor_transfer.c \
|
||||
glamor_transfer.h \
|
||||
glamor_transform.c \
|
||||
glamor_transform.h \
|
||||
glamor_trapezoid.c \
|
||||
glamor_triangles.c\
|
||||
glamor_addtraps.c\
|
||||
glamor_glyphblt.c\
|
||||
glamor_points.c\
|
||||
glamor_priv.h\
|
||||
glamor_pixmap.c\
|
||||
glamor_largepixmap.c\
|
||||
glamor_picture.c\
|
||||
glamor_vbo.c \
|
||||
glamor_window.c\
|
||||
glamor_fbo.c\
|
||||
glamor_compositerects.c\
|
||||
glamor_utils.c\
|
||||
glamor_utils.h\
|
||||
glamor_sync.c \
|
||||
glamor.h
|
||||
|
||||
if XV
|
||||
libglamor_la_SOURCES += \
|
||||
glamor_xv.c
|
||||
endif
|
||||
|
||||
libglamor_egl_stubs_la_SOURCES = \
|
||||
glamor_egl_stubs.c \
|
||||
glamor_egl_ext.h \
|
||||
glamor_egl.h
|
||||
|
||||
sdk_HEADERS = glamor.h
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,7 +54,3 @@ glamor_egl_stubs = static_library('glamor_egl_stubs',
|
|||
include_directories: inc,
|
||||
dependencies: common_dep,
|
||||
)
|
||||
|
||||
if build_xorg
|
||||
install_data('glamor.h', install_dir: xorgsdkdir)
|
||||
endif
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
if DRI2
|
||||
GLXDRI_LIBRARY = libglxdri.la
|
||||
endif
|
||||
|
||||
noinst_LTLIBRARIES = libglx.la $(GLXDRI_LIBRARY) libglxvnd.la
|
||||
|
||||
AM_CFLAGS = \
|
||||
@DIX_CFLAGS@ \
|
||||
@GL_CFLAGS@ \
|
||||
@XLIB_CFLAGS@ \
|
||||
@LIBDRM_CFLAGS@ \
|
||||
@GLX_DEFINES@ \
|
||||
@GLX_ARCH_DEFINES@
|
||||
|
||||
sdk_HEADERS = vndserver.h
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/hw/xfree86/os-support \
|
||||
-I$(top_srcdir)/hw/xfree86/os-support/bus \
|
||||
-I$(top_srcdir)/hw/xfree86/common \
|
||||
-I$(top_srcdir)/hw/xfree86/dri \
|
||||
-I$(top_srcdir)/hw/xfree86/dri2 \
|
||||
-I$(top_srcdir)/mi \
|
||||
-I$(top_srcdir)/present
|
||||
|
||||
indirect_sources = \
|
||||
indirect_dispatch.c \
|
||||
indirect_dispatch.h \
|
||||
indirect_dispatch_swap.c \
|
||||
indirect_reqsize.c \
|
||||
indirect_reqsize.h \
|
||||
indirect_size.h \
|
||||
indirect_size_get.c \
|
||||
indirect_size_get.h \
|
||||
indirect_table.c
|
||||
|
||||
libglxdri_la_SOURCES =
|
||||
if DRI2
|
||||
libglxdri_la_SOURCES += glxdri2.c
|
||||
endif
|
||||
|
||||
libglxdri_la_LIBADD = $(DLOPEN_LIBS)
|
||||
|
||||
libglx_la_SOURCES = \
|
||||
$(indirect_sources) \
|
||||
clientinfo.c \
|
||||
createcontext.c \
|
||||
extension_string.c \
|
||||
extension_string.h \
|
||||
indirect_util.c \
|
||||
indirect_util.h \
|
||||
indirect_program.c \
|
||||
indirect_table.h \
|
||||
indirect_texture_compression.c \
|
||||
glxbyteorder.h \
|
||||
glxcmds.c \
|
||||
glxcmdsswap.c \
|
||||
glxcontext.h \
|
||||
glxdrawable.h \
|
||||
glxext.c \
|
||||
glxext.h \
|
||||
glxdriswrast.c \
|
||||
glxdricommon.c \
|
||||
glxdricommon.h \
|
||||
glxscreens.c \
|
||||
glxscreens.h \
|
||||
glxserver.h \
|
||||
glxutil.h \
|
||||
render2.c \
|
||||
render2swap.c \
|
||||
renderpix.c \
|
||||
renderpixswap.c \
|
||||
rensize.c \
|
||||
single2.c \
|
||||
single2swap.c \
|
||||
singlepix.c \
|
||||
singlepixswap.c \
|
||||
singlesize.c \
|
||||
singlesize.h \
|
||||
swap_interval.c \
|
||||
unpack.h \
|
||||
xfont.c
|
||||
|
||||
libglx_la_LIBADD = $(DLOPEN_LIBS) $(top_builddir)/Xext/libhashtable.la
|
||||
|
||||
libglxvnd_la_SOURCES = \
|
||||
vndcmds.c \
|
||||
vndext.c \
|
||||
vndservermapping.c \
|
||||
vndservervendor.h \
|
||||
vndservervendor.c
|
||||
|
||||
libglxvnd_la_LIBADD = $(top_builddir)/Xext/libhashtable.la
|
||||
|
||||
EXTRA_DIST = vnd_dispatch_stubs.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) {
|
||||
|
|
|
@ -51,7 +51,7 @@ if build_glx
|
|||
endif
|
||||
|
||||
srcs_glxdri2 = []
|
||||
if build_dri2 or build_dri3
|
||||
if build_dri3
|
||||
srcs_glxdri2 = files('glxdri2.c')
|
||||
endif
|
||||
|
||||
|
@ -78,6 +78,4 @@ if build_glx
|
|||
dependency('gl', version: '>= 1.2'),
|
||||
],
|
||||
)
|
||||
|
||||
install_data(hdrs_vnd, install_dir : xorgsdkdir)
|
||||
endif
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
if DMX
|
||||
DMX_SUBDIRS = dmx
|
||||
endif
|
||||
|
||||
if XORG
|
||||
XORG_SUBDIRS = xfree86
|
||||
endif
|
||||
|
||||
if XVFB
|
||||
XVFB_SUBDIRS = vfb
|
||||
endif
|
||||
|
||||
if XNEST
|
||||
XNEST_SUBDIRS = xnest
|
||||
endif
|
||||
|
||||
if XWIN
|
||||
XWIN_SUBDIRS = xwin
|
||||
endif
|
||||
|
||||
if KDRIVE
|
||||
KDRIVE_SUBDIRS = kdrive
|
||||
endif
|
||||
|
||||
if XQUARTZ
|
||||
XQUARTZ_SUBDIRS = xquartz
|
||||
endif
|
||||
|
||||
if XWAYLAND
|
||||
XWAYLAND_SUBDIRS = xwayland
|
||||
endif
|
||||
|
||||
SUBDIRS = \
|
||||
$(XORG_SUBDIRS) \
|
||||
$(XWIN_SUBDIRS) \
|
||||
$(XVFB_SUBDIRS) \
|
||||
$(XNEST_SUBDIRS) \
|
||||
$(DMX_SUBDIRS) \
|
||||
$(KDRIVE_SUBDIRS) \
|
||||
$(XQUARTZ_SUBDIRS) \
|
||||
$(XWAYLAND_SUBDIRS)
|
||||
|
||||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland
|
||||
|
||||
relink:
|
||||
$(AM_V_at)for i in $(SUBDIRS) ; do $(MAKE) -C $$i relink || exit 1 ; done
|
|
@ -1,2 +0,0 @@
|
|||
# Add & Override for this directory and its subdirectories
|
||||
Xdmx
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
SUBDIRS = input config examples doc doxygen man
|
||||
bin_PROGRAMS = Xdmx
|
||||
|
||||
if XINERAMA
|
||||
PANORAMIX_SRCS = $(top_srcdir)/Xext/panoramiX.c
|
||||
endif
|
||||
|
||||
if GLX
|
||||
SUBDIRS += glxProxy
|
||||
GLX_LIBS = glxProxy/libglxproxy.a
|
||||
GLX_SRCS = $(PANORAMIX_SRCS) dmx_glxvisuals.c dmx_glxvisuals.h
|
||||
GLX_INCS = -I$(top_srcdir)/hw/xfree86/dixmods/extmod
|
||||
GLX_DEFS = @GL_CFLAGS@
|
||||
endif
|
||||
|
||||
AM_CFLAGS = \
|
||||
-DHAVE_DMX_CONFIG_H \
|
||||
$(DIX_CFLAGS) \
|
||||
$(GLX_INCS) \
|
||||
$(GLX_DEFS) \
|
||||
$(DMX_CFLAGS) \
|
||||
@DMXMODULES_CFLAGS@
|
||||
|
||||
Xdmx_SOURCES = dmx.c \
|
||||
dmxcb.c \
|
||||
dmxcb.h \
|
||||
dmxclient.h \
|
||||
dmxcmap.c \
|
||||
dmxcmap.h \
|
||||
dmx-config.h \
|
||||
dmxcursor.c \
|
||||
dmxcursor.h \
|
||||
dmxdpms.c \
|
||||
dmxdpms.h \
|
||||
dmxextension.c \
|
||||
dmxextension.h \
|
||||
dmxfont.c \
|
||||
dmxfont.h \
|
||||
dmxgc.c \
|
||||
dmxgc.h \
|
||||
dmxgcops.c \
|
||||
dmxgcops.h \
|
||||
dmx.h \
|
||||
dmxinit.c \
|
||||
dmxinit.h \
|
||||
dmxinput.c \
|
||||
dmxinput.h \
|
||||
dmxlog.c \
|
||||
dmxlog.h \
|
||||
dmxpict.c \
|
||||
dmxpict.h \
|
||||
dmxpixmap.c \
|
||||
dmxpixmap.h \
|
||||
dmxprop.c \
|
||||
dmxprop.h \
|
||||
dmxscrinit.c \
|
||||
dmxscrinit.h \
|
||||
dmxstat.c \
|
||||
dmxstat.h \
|
||||
dmxsync.c \
|
||||
dmxsync.h \
|
||||
dmxvisual.c \
|
||||
dmxvisual.h \
|
||||
dmxwindow.c \
|
||||
dmxwindow.h \
|
||||
$(top_srcdir)/mi/miinitext.c \
|
||||
$(top_srcdir)/mi/miinitext.h \
|
||||
$(GLX_SRCS)
|
||||
|
||||
|
||||
#if COMPOSITE
|
||||
#Xdmx_SOURCES += fakecw.c
|
||||
#endif
|
||||
|
||||
XDMX_LIBS = \
|
||||
$(GLX_LIBS) \
|
||||
@XDMX_LIBS@ \
|
||||
input/libdmxinput.a \
|
||||
config/libdmxconfig.a
|
||||
|
||||
Xdmx_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
|
||||
Xdmx_DEPENDENCIES= $(XDMX_LIBS)
|
||||
Xdmx_LDADD = $(XDMX_LIBS) $(XDMX_SYS_LIBS) $(XSERVER_SYS_LIBS)
|
||||
|
||||
relink:
|
||||
$(AM_V_at)rm -f Xdmx$(EXEEXT) && $(MAKE) Xdmx$(EXEEXT)
|
|
@ -1,7 +0,0 @@
|
|||
# Add & Override for this directory and its subdirectories
|
||||
dmxtodmx
|
||||
parser.c
|
||||
parser.h
|
||||
scanner.c
|
||||
vdltodmx
|
||||
xdmxconfig
|
|
@ -1,165 +0,0 @@
|
|||
/*
|
||||
* Copyright 1987, 1998 The Open Group
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that
|
||||
* copyright notice and this permission notice appear in supporting
|
||||
* documentation.
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Except as contained in this notice, the name of The Open Group shall not be
|
||||
* used in advertising or otherwise to promote the sale, use or other dealings
|
||||
* in this Software without prior written authorization from The Open Group.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
* This file was originally taken from xc/lib/Xaw/Template.c
|
||||
*/
|
||||
|
||||
#include <X11/IntrinsicP.h>
|
||||
#include <X11/StringDefs.h>
|
||||
#include "CanvasP.h"
|
||||
|
||||
static void
|
||||
CanvasInitialize(Widget request, Widget w, ArgList args, Cardinal * num_args)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
CanvasExpose(Widget w, XEvent * event, Region region)
|
||||
{
|
||||
CanvasExposeDataRec data;
|
||||
|
||||
data.w = w;
|
||||
data.event = event;
|
||||
data.region = region;
|
||||
|
||||
if (!XtIsRealized(w))
|
||||
return;
|
||||
XtCallCallbacks(w, XtNcanvasExposeCallback, (XtPointer) &data);
|
||||
}
|
||||
|
||||
static void
|
||||
CanvasResize(Widget w)
|
||||
{
|
||||
if (!XtIsRealized(w))
|
||||
return;
|
||||
XtCallCallbacks(w, XtNcanvasResizeCallback, (XtPointer) w);
|
||||
}
|
||||
|
||||
static void
|
||||
CanvasAction(Widget w, XEvent * event, String * params, Cardinal * num_params)
|
||||
{
|
||||
XtCallCallbacks(w, XtNcallback, (XtPointer) event);
|
||||
}
|
||||
|
||||
#define offset(field) XtOffsetOf(CanvasRec, canvas.field)
|
||||
static XtResource resources[] = {
|
||||
{XtNcallback, XtCCallback, XtRCallback,
|
||||
sizeof(XtCallbackList), offset(input_callback), XtRCallback, NULL}
|
||||
,
|
||||
{(char *) XtNcanvasExposeCallback, (char *) XtCcanvasExposeCallback, XtRCallback,
|
||||
sizeof(XtCallbackList), offset(expose_callback), XtRCallback, NULL}
|
||||
,
|
||||
{(char *) XtNcanvasResizeCallback, (char *) XtCcanvasResizeCallback, XtRCallback,
|
||||
sizeof(XtCallbackList), offset(resize_callback), XtRCallback, NULL}
|
||||
,
|
||||
};
|
||||
|
||||
#undef offset
|
||||
|
||||
static XtActionsRec actions[] = {
|
||||
{(char *) "canvas", CanvasAction},
|
||||
};
|
||||
|
||||
static char translations[] = "<Key>: canvas()\n\
|
||||
<Motion>: canvas()\n\
|
||||
<BtnDown>: canvas()\n\
|
||||
<BtnUp>: canvas()\n\
|
||||
";
|
||||
|
||||
#define Superclass (&widgetClassRec)
|
||||
CanvasClassRec canvasClassRec = {
|
||||
/* core */
|
||||
{
|
||||
(WidgetClass) Superclass, /* superclass */
|
||||
(char *) "Canvas", /* class_name */
|
||||
sizeof(CanvasRec), /* widget_size */
|
||||
NULL, /* class_initialize */
|
||||
NULL, /* class_part_initialize */
|
||||
False, /* class_inited */
|
||||
CanvasInitialize, /* initialize */
|
||||
NULL, /* initialize_hook */
|
||||
XtInheritRealize, /* realize */
|
||||
actions, /* actions */
|
||||
XtNumber(actions), /* num_actions */
|
||||
resources, /* resources */
|
||||
XtNumber(resources), /* num_resources */
|
||||
NULLQUARK, /* xrm_class */
|
||||
True, /* compress_motion */
|
||||
True, /* compress_exposure */
|
||||
True, /* compress_enterleave */
|
||||
False, /* visible_interest */
|
||||
NULL, /* destroy */
|
||||
CanvasResize, /* resize */
|
||||
CanvasExpose, /* expose */
|
||||
NULL, /* set_values */
|
||||
NULL, /* set_values_hook */
|
||||
XtInheritSetValuesAlmost, /* set_values_almost */
|
||||
NULL, /* get_values_hook */
|
||||
NULL, /* accept_focus */
|
||||
XtVersion, /* version */
|
||||
NULL, /* callback_private */
|
||||
translations, /* tm_table */
|
||||
XtInheritQueryGeometry, /* query_geometry */
|
||||
XtInheritDisplayAccelerator, /* display_accelerator */
|
||||
NULL, /* extension */
|
||||
}
|
||||
,
|
||||
/* canvas */
|
||||
{
|
||||
NULL, /* extension */
|
||||
}
|
||||
};
|
||||
|
||||
WidgetClass canvasWidgetClass = (WidgetClass) &canvasClassRec;
|
|
@ -1,55 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright 1987, 1998 The Open Group
|
||||
Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from The Open Group.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
* This file was originally taken from xc/lib/Xaw/Template.h
|
||||
*/
|
||||
|
||||
#ifndef _Canvas_h
|
||||
#define _Canvas_h
|
||||
|
||||
#include <X11/Intrinsic.h>
|
||||
|
||||
#define XtNcanvasExposeCallback "canvasExposeCallback"
|
||||
#define XtCcanvasExposeCallback "CanvasExposeCallback"
|
||||
#define XtNcanvasResizeCallback "canvasResizeCallback"
|
||||
#define XtCcanvasResizeCallback "CanvasResizeCallback"
|
||||
|
||||
typedef struct _CanvasClassRec *CanvasWidgetClass;
|
||||
typedef struct _CanvasRec *CanvasWidget;
|
||||
extern WidgetClass canvasWidgetClass;
|
||||
|
||||
typedef struct _CanvasExposeDataRec {
|
||||
Widget w;
|
||||
XEvent *event;
|
||||
Region region;
|
||||
} CanvasExposeDataRec, *CanvasExposeDataPtr;
|
||||
|
||||
#endif /* _Canvas_h */
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
|
||||
Copyright 1987, 1998 The Open Group
|
||||
Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this software and its
|
||||
documentation for any purpose is hereby granted without fee, provided that
|
||||
the above copyright notice appear in all copies and that both that
|
||||
copyright notice and this permission notice appear in supporting
|
||||
documentation.
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of The Open Group shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from The Open Group.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
* This file was originally taken from xc/lib/Xaw/TemplateP.h
|
||||
*/
|
||||
|
||||
#ifndef _CanvasP_h
|
||||
#define _CanvasP_h
|
||||
|
||||
#include "Canvas.h"
|
||||
|
||||
/* include superclass private header file */
|
||||
#include <X11/CoreP.h>
|
||||
|
||||
typedef struct {
|
||||
XtPointer extension;
|
||||
} CanvasClassPart;
|
||||
|
||||
typedef struct _CanvasClassRec {
|
||||
CoreClassPart core_class;
|
||||
CanvasClassPart canvas_class;
|
||||
} CanvasClassRec;
|
||||
|
||||
extern CanvasClassRec canvasClassRec;
|
||||
|
||||
typedef struct {
|
||||
XtCallbackList input_callback;
|
||||
XtCallbackList expose_callback;
|
||||
XtCallbackList resize_callback;
|
||||
} CanvasPart;
|
||||
|
||||
typedef struct _CanvasRec {
|
||||
CorePart core;
|
||||
CanvasPart canvas;
|
||||
} CanvasRec;
|
||||
|
||||
#endif /* _CanvasP_h */
|
|
@ -1,71 +0,0 @@
|
|||
SUBDIRS = man
|
||||
|
||||
noinst_LIBRARIES = libdmxconfig.a
|
||||
|
||||
LIBSRCS = parser.y \
|
||||
scanner.l \
|
||||
dmxparse.c \
|
||||
dmxparse.h \
|
||||
dmxprint.c \
|
||||
dmxprint.h \
|
||||
dmxcompat.c \
|
||||
dmxcompat.h \
|
||||
dmxconfig.c \
|
||||
dmxconfig.h
|
||||
|
||||
parser.h: parser.c
|
||||
scanner.c: scanner.l parser.h
|
||||
|
||||
BUILT_SOURCES = parser.c parser.h scanner.c
|
||||
|
||||
MAINTAINERCLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
libdmxconfig_a_SOURCES = $(LIBSRCS)
|
||||
libdmxconfig_a_SOURCES += $(top_srcdir)/os/strlcpy.c
|
||||
|
||||
if GLX
|
||||
GLX_DEFS = @GL_CFLAGS@
|
||||
endif
|
||||
|
||||
AM_YFLAGS = -d
|
||||
AM_CFLAGS = \
|
||||
$(DIX_CFLAGS) \
|
||||
-I$(top_srcdir)/hw/dmx \
|
||||
-DHAVE_DMX_CONFIG_H \
|
||||
-DDMX_LOG_STANDALONE \
|
||||
$(GLX_DEFS) \
|
||||
@DMXMODULES_CFLAGS@
|
||||
|
||||
bin_PROGRAMS = xdmxconfig vdltodmx dmxtodmx
|
||||
|
||||
xdmxconfig_DEPENDENCIES = libdmxconfig.a
|
||||
xdmxconfig_SOURCES = \
|
||||
xdmxconfig.c \
|
||||
$(top_srcdir)/hw/dmx/dmxlog.c \
|
||||
Canvas.c \
|
||||
Canvas.h \
|
||||
CanvasP.h
|
||||
xdmxconfig_LDADD = -L. -ldmxconfig @XDMXCONFIG_DEP_LIBS@
|
||||
xdmxconfig_CFLAGS = $(AM_CFLAGS) @XDMXCONFIG_DEP_CFLAGS@
|
||||
|
||||
vdltodmx_DEPENDENCIES = libdmxconfig.a
|
||||
vdltodmx_SOURCES = vdltodmx.c
|
||||
vdltodmx_LDADD = -L. -ldmxconfig
|
||||
|
||||
dmxtodmx_DEPENDENCIES = libdmxconfig.a
|
||||
dmxtodmx_SOURCES = dmxtodmx.c
|
||||
dmxtodmx_LDADD = -L. -ldmxconfig
|
||||
|
||||
EXTRA_DIST = \
|
||||
test-a.in test-a.out \
|
||||
test-b.in test-b.out \
|
||||
test-c.in test-c.out \
|
||||
test-d.in test-d.out \
|
||||
test-e.in test-e.out \
|
||||
test-f.in test-f.out \
|
||||
test-g.in test-g.out \
|
||||
test-h.in test-h.out \
|
||||
test-i.in test-i.out \
|
||||
test-j.in test-j.out \
|
||||
test-k.in test-k.out \
|
||||
test-l.in test-l.out
|
|
@ -1,7 +0,0 @@
|
|||
Fri May 31 13:20:17 2002
|
||||
|
||||
1) Sanitize values from input boxes.
|
||||
|
||||
2) Add canvas colors to cavas widget resources or to command-line options.
|
||||
|
||||
3) Add ability to edit option line(s) and wall.
|
|
@ -1,234 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* This file provides some compatibility support for reading VDL files
|
||||
* that are used by xmovie
|
||||
* (http://www.llnl.gov/icc/sdd/img/xmovie/xmovie.shtml).
|
||||
*
|
||||
* This file is not used by the DMX server.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include "os.h"
|
||||
#include "dmxconfig.h"
|
||||
#include "dmxparse.h"
|
||||
#include "dmxcompat.h"
|
||||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static int
|
||||
dmxVDLReadLine(FILE * str, char *buf, int len)
|
||||
{
|
||||
if (fgets(buf, len, str))
|
||||
return strlen(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dmxVDLCount(const char *buf)
|
||||
{
|
||||
return strtol(buf, NULL, 10);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxVDLVirtualEntry(const char *buf, char *name, int *len, int *x, int *y)
|
||||
{
|
||||
char *end;
|
||||
const char *s;
|
||||
char *d;
|
||||
int start;
|
||||
|
||||
*x = strtol(buf, &end, 10);
|
||||
*y = strtol(end, &end, 10);
|
||||
|
||||
for (s = end, d = name, start = 1; *s && *s != '['; ++s) {
|
||||
if (start && isspace(*s))
|
||||
continue;
|
||||
*d++ = *s;
|
||||
start = 0;
|
||||
}
|
||||
*d = '\0';
|
||||
while (d > name && isspace(d[-1]))
|
||||
*--d = '\0'; /* remove trailing space */
|
||||
*len = strlen(name);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxVDLDisplayEntry(const char *buf,
|
||||
char *name, int *len,
|
||||
int *x, int *y, int *xoff, int *yoff, int *xorig, int *yorig)
|
||||
{
|
||||
const char *pt;
|
||||
char *end;
|
||||
|
||||
pt = strchr(buf, ' ');
|
||||
strlcpy(name, buf, 1 + pt - buf);
|
||||
*len = strlen(name);
|
||||
|
||||
*x = strtol(pt, &end, 10);
|
||||
*y = strtol(end, &end, 10);
|
||||
*xorig = strtol(end, &end, 10);
|
||||
*yorig = strtol(end, &end, 10);
|
||||
*xoff = strtol(end, &end, 10);
|
||||
*yoff = strtol(end, NULL, 10);
|
||||
}
|
||||
|
||||
/** Read from the VDL format \a filename and return a newly allocated \a
|
||||
* DMXConfigEntryPtr */
|
||||
DMXConfigEntryPtr
|
||||
dmxVDLRead(const char *filename)
|
||||
{
|
||||
FILE *str;
|
||||
char buf[2048]; /* RATS: Use ok */
|
||||
char *pt;
|
||||
int lineno = 0;
|
||||
DMXConfigEntryPtr entry = NULL;
|
||||
DMXConfigVirtualPtr virtual = NULL;
|
||||
DMXConfigSubPtr sub = NULL;
|
||||
DMXConfigDisplayPtr display = NULL;
|
||||
DMXConfigFullDimPtr fdim = NULL;
|
||||
int dcount = 0;
|
||||
int icount = 0;
|
||||
int x, y, xoff, yoff, xorig, yorig;
|
||||
char name[2048]; /* RATS: Use ok */
|
||||
const char *tmp;
|
||||
int len;
|
||||
enum {
|
||||
simulateFlag,
|
||||
virtualCount,
|
||||
virtualEntry,
|
||||
displayCount,
|
||||
displayEntry,
|
||||
ignoreCount,
|
||||
ignoreEntry
|
||||
} state = simulateFlag;
|
||||
|
||||
if (!filename)
|
||||
str = stdin;
|
||||
else
|
||||
str = fopen(filename, "r");
|
||||
if (!str)
|
||||
return NULL;
|
||||
|
||||
while (dmxVDLReadLine(str, buf, sizeof(buf))) {
|
||||
DMXConfigCommentPtr comment = NULL;
|
||||
|
||||
++lineno;
|
||||
for (pt = buf; *pt; pt++)
|
||||
if (*pt == '\r' || *pt == '\n') {
|
||||
*pt = '\0';
|
||||
break;
|
||||
}
|
||||
if (buf[0] == '#') {
|
||||
tmp = dmxConfigCopyString(buf + 1, strlen(buf + 1));
|
||||
comment = dmxConfigCreateComment(T_COMMENT, lineno, tmp);
|
||||
entry = dmxConfigAddEntry(entry, dmxConfigComment, comment, NULL);
|
||||
continue;
|
||||
}
|
||||
switch (state) {
|
||||
case simulateFlag:
|
||||
state = virtualCount;
|
||||
break;
|
||||
case virtualCount:
|
||||
state = virtualEntry;
|
||||
break;
|
||||
case virtualEntry:
|
||||
len = sizeof(name);
|
||||
dmxVDLVirtualEntry(buf, name, &len, &x, &y);
|
||||
tmp = dmxConfigCopyString(name, len);
|
||||
virtual = dmxConfigCreateVirtual(NULL,
|
||||
dmxConfigCreateString(T_STRING,
|
||||
lineno,
|
||||
NULL,
|
||||
tmp),
|
||||
dmxConfigCreatePair(T_DIMENSION,
|
||||
lineno,
|
||||
NULL,
|
||||
x, y, 0, 0),
|
||||
NULL, NULL, NULL);
|
||||
state = displayCount;
|
||||
break;
|
||||
case displayCount:
|
||||
dcount = dmxVDLCount(buf);
|
||||
state = displayEntry;
|
||||
break;
|
||||
case displayEntry:
|
||||
dmxVDLDisplayEntry(buf, name, &len, &x, &y, &xoff, &yoff,
|
||||
&xorig, &yorig);
|
||||
tmp = dmxConfigCopyString(name, len);
|
||||
fdim =
|
||||
dmxConfigCreateFullDim(dmxConfigCreatePartDim
|
||||
(dmxConfigCreatePair
|
||||
(T_DIMENSION, lineno, NULL, x, y, 0, 0),
|
||||
dmxConfigCreatePair(T_OFFSET, lineno,
|
||||
NULL, xoff, yoff,
|
||||
xoff, yoff)), NULL);
|
||||
display =
|
||||
dmxConfigCreateDisplay(NULL,
|
||||
dmxConfigCreateString(T_STRING, lineno,
|
||||
NULL, tmp), fdim,
|
||||
dmxConfigCreatePair(T_ORIGIN, lineno,
|
||||
NULL, xorig, yorig,
|
||||
0, 0), NULL);
|
||||
sub = dmxConfigAddSub(sub, dmxConfigSubDisplay(display));
|
||||
if (!--dcount) {
|
||||
state = ignoreCount;
|
||||
virtual->subentry = sub;
|
||||
entry = dmxConfigAddEntry(entry,
|
||||
dmxConfigVirtual, NULL, virtual);
|
||||
virtual = NULL;
|
||||
sub = NULL;
|
||||
}
|
||||
break;
|
||||
case ignoreCount:
|
||||
icount = dmxVDLCount(buf);
|
||||
state = ignoreEntry;
|
||||
break;
|
||||
case ignoreEntry:
|
||||
if (!--icount)
|
||||
state = virtualEntry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (str != stdin)
|
||||
fclose(str);
|
||||
|
||||
return entry;
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Interface to VDL compatibility support. \see dmxcompat.c
|
||||
*
|
||||
* This file is not used by the DMX server.
|
||||
*/
|
||||
|
||||
#ifndef _DMXCOMPAT_H_
|
||||
#define _DMXCOMPAT_H_
|
||||
|
||||
extern DMXConfigEntryPtr dmxVDLRead(const char *filename);
|
||||
#endif
|
|
@ -1,561 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Provides interface for reading DMX configuration files and for
|
||||
* combining that information with command-line configuration parameters. */
|
||||
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include "dmx.h"
|
||||
#include "dmxinput.h"
|
||||
#include "dmxconfig.h"
|
||||
#include "dmxparse.h"
|
||||
#include "dmxlog.h"
|
||||
#include "dmxcb.h"
|
||||
#include "dmxstat.h"
|
||||
#include "parser.h"
|
||||
|
||||
extern int yydebug;
|
||||
extern FILE *yyin;
|
||||
|
||||
static char *dmxXkbRules;
|
||||
static char *dmxXkbModel;
|
||||
static char *dmxXkbLayout;
|
||||
static char *dmxXkbVariant;
|
||||
static char *dmxXkbOptions;
|
||||
|
||||
/** Stores lists of configuration information. */
|
||||
typedef struct DMXConfigListStruct {
|
||||
const char *name;
|
||||
struct DMXConfigListStruct *next;
|
||||
} DMXConfigList, *DMXConfigListPtr;
|
||||
|
||||
/** This structure stores the parsed configuration information. */
|
||||
typedef struct DMXConfigCmdStruct {
|
||||
const char *filename;
|
||||
const char *config;
|
||||
DMXConfigList *displays;
|
||||
DMXConfigList *inputs;
|
||||
DMXConfigList *xinputs;
|
||||
} DMXConfigCmd, *DMXConfigCmdPtr;
|
||||
|
||||
extern DMXConfigEntryPtr dmxConfigEntry;
|
||||
static DMXConfigCmd dmxConfigCmd;
|
||||
|
||||
static int dmxDisplaysFromCommandLine;
|
||||
|
||||
/** Make a note that \a display is the name of an X11 display that
|
||||
* should be initialized as a backend (output) display. Called from
|
||||
* #ddxProcessArgument. */
|
||||
void
|
||||
dmxConfigStoreDisplay(const char *display)
|
||||
{
|
||||
DMXConfigListPtr entry = malloc(sizeof(*entry));
|
||||
|
||||
entry->name = strdup(display);
|
||||
entry->next = NULL;
|
||||
if (!dmxConfigCmd.displays)
|
||||
dmxConfigCmd.displays = entry;
|
||||
else {
|
||||
DMXConfigList *pt;
|
||||
|
||||
for (pt = dmxConfigCmd.displays; pt->next; pt = pt->next);
|
||||
if (!pt)
|
||||
dmxLog(dmxFatal, "dmxConfigStoreDisplay: end of list non-NULL\n");
|
||||
pt->next = entry;
|
||||
}
|
||||
++dmxDisplaysFromCommandLine;
|
||||
}
|
||||
|
||||
/** Make a note that \a input is the name of an X11 display that should
|
||||
* be used for input (either a backend or a console input device). */
|
||||
void
|
||||
dmxConfigStoreInput(const char *input)
|
||||
{
|
||||
DMXConfigListPtr entry = malloc(sizeof(*entry));
|
||||
|
||||
entry->name = strdup(input);
|
||||
entry->next = NULL;
|
||||
if (!dmxConfigCmd.inputs)
|
||||
dmxConfigCmd.inputs = entry;
|
||||
else {
|
||||
DMXConfigList *pt;
|
||||
|
||||
for (pt = dmxConfigCmd.inputs; pt->next; pt = pt->next);
|
||||
if (!pt)
|
||||
dmxLog(dmxFatal, "dmxConfigStoreInput: end of list non-NULL\n");
|
||||
pt->next = entry;
|
||||
}
|
||||
}
|
||||
|
||||
/** Make a note that \a input is the name of an X11 display that should
|
||||
* be used for input from XInput extension devices. */
|
||||
void
|
||||
dmxConfigStoreXInput(const char *input)
|
||||
{
|
||||
DMXConfigListPtr entry = malloc(sizeof(*entry));
|
||||
|
||||
entry->name = strdup(input);
|
||||
entry->next = NULL;
|
||||
if (!dmxConfigCmd.xinputs)
|
||||
dmxConfigCmd.xinputs = entry;
|
||||
else {
|
||||
DMXConfigList *pt;
|
||||
|
||||
for (pt = dmxConfigCmd.xinputs; pt->next; pt = pt->next);
|
||||
if (!pt)
|
||||
dmxLog(dmxFatal, "dmxConfigStoreXInput: end of list non-NULL\n");
|
||||
pt->next = entry;
|
||||
}
|
||||
}
|
||||
|
||||
/** Make a note that \a file is the configuration file. */
|
||||
void
|
||||
dmxConfigStoreFile(const char *file)
|
||||
{
|
||||
if (dmxConfigCmd.filename)
|
||||
dmxLog(dmxFatal, "Only one -configfile allowed\n");
|
||||
dmxConfigCmd.filename = strdup(file);
|
||||
}
|
||||
|
||||
/** Make a note that \a config should be used as the configuration for
|
||||
* current instantiation of the DMX server. */
|
||||
void
|
||||
dmxConfigStoreConfig(const char *config)
|
||||
{
|
||||
if (dmxConfigCmd.config)
|
||||
dmxLog(dmxFatal, "Only one -config allowed\n");
|
||||
dmxConfigCmd.config = strdup(config);
|
||||
}
|
||||
|
||||
static int
|
||||
dmxConfigReadFile(const char *filename, int debug)
|
||||
{
|
||||
FILE *str;
|
||||
|
||||
if (!(str = fopen(filename, "r")))
|
||||
return -1;
|
||||
dmxLog(dmxInfo, "Reading configuration file \"%s\"\n", filename);
|
||||
yyin = str;
|
||||
yydebug = debug;
|
||||
yyparse();
|
||||
fclose(str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *
|
||||
dmxConfigMatch(const char *target, DMXConfigEntryPtr entry)
|
||||
{
|
||||
DMXConfigVirtualPtr v = entry->virtual;
|
||||
const char *name = NULL;
|
||||
|
||||
if (v && v->name)
|
||||
name = v->name;
|
||||
|
||||
if (v && !dmxConfigCmd.config)
|
||||
return v->name ? v->name : "<noname>";
|
||||
if (!name)
|
||||
return NULL;
|
||||
if (!strcmp(name, target))
|
||||
return name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DMXScreenInfo *
|
||||
dmxConfigAddDisplay(const char *name,
|
||||
int scrnWidth, int scrnHeight,
|
||||
int scrnX, int scrnY,
|
||||
int scrnXSign, int scrnYSign,
|
||||
int rootWidth, int rootHeight,
|
||||
int rootX, int rootY, int rootXSign, int rootYSign)
|
||||
{
|
||||
DMXScreenInfo *dmxScreen;
|
||||
|
||||
if (!(dmxScreens = reallocarray(dmxScreens, dmxNumScreens + 1,
|
||||
sizeof(*dmxScreens))))
|
||||
dmxLog(dmxFatal,
|
||||
"dmxConfigAddDisplay: realloc failed for screen %d (%s)\n",
|
||||
dmxNumScreens, name);
|
||||
|
||||
dmxScreen = &dmxScreens[dmxNumScreens];
|
||||
memset(dmxScreen, 0, sizeof(*dmxScreen));
|
||||
dmxScreen->name = name;
|
||||
dmxScreen->index = dmxNumScreens;
|
||||
dmxScreen->scrnWidth = scrnWidth;
|
||||
dmxScreen->scrnHeight = scrnHeight;
|
||||
dmxScreen->scrnX = scrnX;
|
||||
dmxScreen->scrnY = scrnY;
|
||||
dmxScreen->scrnXSign = scrnXSign;
|
||||
dmxScreen->scrnYSign = scrnYSign;
|
||||
dmxScreen->rootWidth = rootWidth;
|
||||
dmxScreen->rootHeight = rootHeight;
|
||||
dmxScreen->rootX = rootX;
|
||||
dmxScreen->rootY = rootY;
|
||||
dmxScreen->stat = dmxStatAlloc();
|
||||
++dmxNumScreens;
|
||||
return dmxScreen;
|
||||
}
|
||||
|
||||
DMXInputInfo *
|
||||
dmxConfigAddInput(const char *name, int core)
|
||||
{
|
||||
DMXInputInfo *dmxInput;
|
||||
|
||||
if (!(dmxInputs = reallocarray(dmxInputs, dmxNumInputs + 1,
|
||||
sizeof(*dmxInputs))))
|
||||
dmxLog(dmxFatal,
|
||||
"dmxConfigAddInput: realloc failed for input %d (%s)\n",
|
||||
dmxNumInputs, name);
|
||||
|
||||
dmxInput = &dmxInputs[dmxNumInputs];
|
||||
|
||||
memset(dmxInput, 0, sizeof(*dmxInput));
|
||||
dmxInput->name = name;
|
||||
dmxInput->inputIdx = dmxNumInputs;
|
||||
dmxInput->scrnIdx = -1;
|
||||
dmxInput->core = core;
|
||||
++dmxNumInputs;
|
||||
return dmxInput;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigCopyFromDisplay(DMXConfigDisplayPtr d)
|
||||
{
|
||||
DMXScreenInfo *dmxScreen;
|
||||
|
||||
dmxScreen = dmxConfigAddDisplay(d->name,
|
||||
d->scrnWidth, d->scrnHeight,
|
||||
d->scrnX, d->scrnY,
|
||||
d->scrnXSign, d->scrnYSign,
|
||||
d->rootWidth, d->rootHeight,
|
||||
d->rootX, d->rootY,
|
||||
d->rootXSign, d->rootXSign);
|
||||
dmxScreen->where = PosAbsolute;
|
||||
dmxScreen->whereX = d->rootXOrigin;
|
||||
dmxScreen->whereY = d->rootYOrigin;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigCopyFromWall(DMXConfigWallPtr w)
|
||||
{
|
||||
DMXConfigStringPtr pt;
|
||||
DMXScreenInfo *dmxScreen;
|
||||
int edge = dmxNumScreens;
|
||||
int last = dmxNumScreens;
|
||||
|
||||
if (!w->xwall && !w->ywall) { /* Try to make it square */
|
||||
int count;
|
||||
|
||||
for (pt = w->nameList, count = 0; pt; pt = pt->next)
|
||||
++count;
|
||||
w->xwall = sqrt(count) + .5;
|
||||
}
|
||||
|
||||
for (pt = w->nameList; pt; pt = pt->next) {
|
||||
dmxScreen = dmxConfigAddDisplay(pt->string, w->width, w->height,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
if (pt == w->nameList) { /* Upper left */
|
||||
dmxScreen->where = PosAbsolute;
|
||||
dmxScreen->whereX = 0;
|
||||
dmxScreen->whereY = 0;
|
||||
}
|
||||
else if (w->xwall) { /* Tile left to right, then top to bottom */
|
||||
if (!((dmxNumScreens - 1) % w->xwall)) {
|
||||
dmxScreen->where = PosBelow;
|
||||
dmxScreen->whereRefScreen = edge;
|
||||
edge = dmxNumScreens - 1;
|
||||
}
|
||||
else {
|
||||
dmxScreen->where = PosRightOf;
|
||||
dmxScreen->whereRefScreen = last;
|
||||
}
|
||||
}
|
||||
else { /* Tile top to bottom, then left to right */
|
||||
if (!((dmxNumScreens - 1) % w->ywall)) {
|
||||
dmxScreen->where = PosRightOf;
|
||||
dmxScreen->whereRefScreen = edge;
|
||||
edge = dmxNumScreens - 1;
|
||||
}
|
||||
else {
|
||||
dmxScreen->where = PosBelow;
|
||||
dmxScreen->whereRefScreen = last;
|
||||
}
|
||||
|
||||
}
|
||||
last = dmxNumScreens - 1;
|
||||
if (dmxScreen->where == PosAbsolute)
|
||||
dmxLog(dmxInfo, "Added %s at %d %d\n",
|
||||
pt->string, dmxScreen->whereX, dmxScreen->whereY);
|
||||
else
|
||||
dmxLog(dmxInfo, "Added %s %s %s\n",
|
||||
pt->string,
|
||||
dmxScreen->where == PosBelow ? "below" : "right of",
|
||||
dmxScreens[dmxScreen->whereRefScreen].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigCopyFromOption(DMXConfigOptionPtr o)
|
||||
{
|
||||
DMXConfigStringPtr pt;
|
||||
int argc = 0;
|
||||
char **argv = NULL;
|
||||
|
||||
if (serverGeneration != 1)
|
||||
return; /* FIXME: only do once, for now */
|
||||
if (!o || !o->string)
|
||||
return;
|
||||
for (pt = o->option; pt; pt = pt->next) {
|
||||
if (pt->string) {
|
||||
++argc;
|
||||
argv = reallocarray(argv, argc + 1, sizeof(*argv));
|
||||
argv[argc] = (char *) pt->string;
|
||||
}
|
||||
}
|
||||
argv[0] = NULL;
|
||||
ProcessCommandLine(argc + 1, argv);
|
||||
free(argv);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigCopyFromParam(DMXConfigParamPtr p)
|
||||
{
|
||||
const char **argv;
|
||||
int argc;
|
||||
|
||||
if ((argv = dmxConfigLookupParam(p, "xkbrules", &argc)) && argc == 2) {
|
||||
dmxConfigSetXkbRules(argv[1]);
|
||||
}
|
||||
else if ((argv = dmxConfigLookupParam(p, "xkbmodel", &argc))
|
||||
&& argc == 2) {
|
||||
dmxConfigSetXkbModel(argv[1]);
|
||||
}
|
||||
else if ((argv = dmxConfigLookupParam(p, "xkblayout", &argc))
|
||||
&& argc == 2) {
|
||||
dmxConfigSetXkbLayout(argv[1]);
|
||||
}
|
||||
else if ((argv = dmxConfigLookupParam(p, "xkbvariant", &argc))
|
||||
&& argc == 2) {
|
||||
dmxConfigSetXkbVariant(argv[1]);
|
||||
}
|
||||
else if ((argv = dmxConfigLookupParam(p, "xkboptions", &argc))
|
||||
&& argc == 2) {
|
||||
dmxConfigSetXkbOptions(argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigCopyData(DMXConfigVirtualPtr v)
|
||||
{
|
||||
DMXConfigSubPtr sub;
|
||||
|
||||
if (v->dim)
|
||||
dmxSetWidthHeight(v->dim->x, v->dim->y);
|
||||
else
|
||||
dmxSetWidthHeight(0, 0);
|
||||
for (sub = v->subentry; sub; sub = sub->next) {
|
||||
switch (sub->type) {
|
||||
case dmxConfigDisplay:
|
||||
dmxConfigCopyFromDisplay(sub->display);
|
||||
break;
|
||||
case dmxConfigWall:
|
||||
dmxConfigCopyFromWall(sub->wall);
|
||||
break;
|
||||
case dmxConfigOption:
|
||||
dmxConfigCopyFromOption(sub->option);
|
||||
break;
|
||||
case dmxConfigParam:
|
||||
dmxConfigCopyFromParam(sub->param);
|
||||
break;
|
||||
default:
|
||||
dmxLog(dmxFatal,
|
||||
"dmxConfigCopyData: not a display, wall, or value\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigFromCommandLine(void)
|
||||
{
|
||||
DMXConfigListPtr pt;
|
||||
|
||||
dmxLog(dmxInfo, "Using configuration from command line\n");
|
||||
for (pt = dmxConfigCmd.displays; pt; pt = pt->next) {
|
||||
DMXScreenInfo *dmxScreen = dmxConfigAddDisplay(pt->name,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0);
|
||||
|
||||
if (dmxNumScreens == 1) {
|
||||
dmxScreen->where = PosAbsolute;
|
||||
dmxScreen->whereX = 0;
|
||||
dmxScreen->whereY = 0;
|
||||
dmxLog(dmxInfo, "Added %s at %d %d\n",
|
||||
dmxScreen->name, dmxScreen->whereX, dmxScreen->whereY);
|
||||
}
|
||||
else {
|
||||
dmxScreen->where = PosRightOf;
|
||||
dmxScreen->whereRefScreen = dmxNumScreens - 2;
|
||||
if (dmxScreen->whereRefScreen < 0)
|
||||
dmxScreen->whereRefScreen = 0;
|
||||
dmxLog(dmxInfo, "Added %s %s %s\n",
|
||||
dmxScreen->name,
|
||||
dmxScreen->where == PosBelow ? "below" : "right of",
|
||||
dmxScreens[dmxScreen->whereRefScreen].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigFromConfigFile(void)
|
||||
{
|
||||
DMXConfigEntryPtr pt;
|
||||
const char *name;
|
||||
|
||||
for (pt = dmxConfigEntry; pt; pt = pt->next) {
|
||||
/* FIXME -- if an input is specified, use it */
|
||||
if (pt->type != dmxConfigVirtual)
|
||||
continue;
|
||||
if ((name = dmxConfigMatch(dmxConfigCmd.config, pt))) {
|
||||
dmxLog(dmxInfo, "Using configuration \"%s\"\n", name);
|
||||
dmxConfigCopyData(pt->virtual);
|
||||
return;
|
||||
}
|
||||
}
|
||||
dmxLog(dmxFatal, "Could not find configuration \"%s\" in \"%s\"\n",
|
||||
dmxConfigCmd.config, dmxConfigCmd.filename);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigConfigInputs(void)
|
||||
{
|
||||
DMXConfigListPtr pt;
|
||||
|
||||
if (dmxNumInputs)
|
||||
return;
|
||||
|
||||
if (dmxConfigCmd.inputs) { /* Use command line */
|
||||
for (pt = dmxConfigCmd.inputs; pt; pt = pt->next)
|
||||
dmxConfigAddInput(pt->name, TRUE);
|
||||
}
|
||||
else if (dmxNumScreens) { /* Use first display */
|
||||
dmxConfigAddInput(dmxScreens[0].name, TRUE);
|
||||
}
|
||||
else { /* Use dummy */
|
||||
dmxConfigAddInput("dummy", TRUE);
|
||||
}
|
||||
|
||||
if (dmxConfigCmd.xinputs) { /* Non-core devices from command line */
|
||||
for (pt = dmxConfigCmd.xinputs; pt; pt = pt->next)
|
||||
dmxConfigAddInput(pt->name, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Set up the appropriate global variables so that the DMX server will
|
||||
* be initialized using the configuration specified in the config file
|
||||
* and on the command line. */
|
||||
void
|
||||
dmxConfigConfigure(void)
|
||||
{
|
||||
if (dmxConfigEntry) {
|
||||
dmxConfigFreeEntry(dmxConfigEntry);
|
||||
dmxConfigEntry = NULL;
|
||||
}
|
||||
if (dmxConfigCmd.filename) {
|
||||
if (dmxConfigCmd.displays)
|
||||
dmxLog(dmxWarning,
|
||||
"Using configuration file \"%s\" instead of command line\n",
|
||||
dmxConfigCmd.filename);
|
||||
dmxConfigReadFile(dmxConfigCmd.filename, 0);
|
||||
dmxConfigFromConfigFile();
|
||||
}
|
||||
else {
|
||||
if (dmxConfigCmd.config)
|
||||
dmxLog(dmxWarning,
|
||||
"Configuration name (%s) without configuration file\n",
|
||||
dmxConfigCmd.config);
|
||||
dmxConfigFromCommandLine();
|
||||
}
|
||||
dmxConfigConfigInputs();
|
||||
}
|
||||
|
||||
/** This function determines the number of displays we WILL have and
|
||||
* sets MAXSCREENS to that value. This is difficult since the number
|
||||
* depends on the command line (which is easy to count) or on the config
|
||||
* file, which has to be parsed. */
|
||||
void
|
||||
dmxConfigSetMaxScreens(void)
|
||||
{
|
||||
static int processing = 0;
|
||||
|
||||
if (processing)
|
||||
return; /* Prevent reentry via ProcessCommandLine */
|
||||
processing = 1;
|
||||
if (dmxConfigCmd.filename) {
|
||||
if (!dmxNumScreens)
|
||||
dmxConfigConfigure();
|
||||
#ifndef MAXSCREENS
|
||||
SetMaxScreens(dmxNumScreens);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#ifndef MAXSCREENS
|
||||
SetMaxScreens(dmxDisplaysFromCommandLine);
|
||||
#endif
|
||||
processing = 0;
|
||||
}
|
||||
|
||||
/** This macro is used to generate the following access methods:
|
||||
* - dmxConfig{Set,Get}rules
|
||||
* - dmxConfig{Set,Get}model
|
||||
* - dmxConfig{Set,Get}layout
|
||||
* - dmxConfig{Set,Get}variant
|
||||
* - dmxConfig{Set,Get}options
|
||||
* These methods are used to read and write information about the keyboard. */
|
||||
|
||||
#define GEN(param,glob,def) \
|
||||
void dmxConfigSet##glob(const char *param) { \
|
||||
if (dmx##glob) free((void *)dmx##glob); \
|
||||
dmx##glob = strdup(param); \
|
||||
} \
|
||||
char *dmxConfigGet##glob(void) { \
|
||||
return (char *)(dmx##glob ? dmx##glob : def); \
|
||||
}
|
||||
|
||||
GEN(rules, XkbRules, XKB_DFLT_RULES)
|
||||
GEN(model, XkbModel, XKB_DFLT_MODEL)
|
||||
GEN(layout, XkbLayout, XKB_DFLT_LAYOUT)
|
||||
GEN(variant, XkbVariant, XKB_DFLT_VARIANT)
|
||||
GEN(options, XkbOptions, XKB_DFLT_OPTIONS)
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Interface for DMX configuration file support. \see dmxconfig.c */
|
||||
|
||||
#ifndef _DMXCONFIG_H_
|
||||
#define _DMXCONFIG_H_
|
||||
|
||||
#include <xkb-config.h>
|
||||
|
||||
extern void dmxConfigStoreDisplay(const char *display);
|
||||
extern void dmxConfigStoreInput(const char *input); /* Core devices */
|
||||
extern void dmxConfigStoreXInput(const char *input); /* Non-core devices */
|
||||
extern void dmxConfigStoreFile(const char *file);
|
||||
extern void dmxConfigStoreConfig(const char *config);
|
||||
extern void dmxConfigConfigure(void);
|
||||
extern void dmxConfigSetMaxScreens(void);
|
||||
|
||||
extern void dmxConfigSetXkbRules(const char *rules);
|
||||
extern void dmxConfigSetXkbModel(const char *model);
|
||||
extern void dmxConfigSetXkbLayout(const char *layout);
|
||||
extern void dmxConfigSetXkbVariant(const char *variant);
|
||||
extern void dmxConfigSetXkbOptions(const char *options);
|
||||
|
||||
extern char *dmxConfigGetXkbRules(void);
|
||||
extern char *dmxConfigGetXkbModel(void);
|
||||
extern char *dmxConfigGetXkbLayout(void);
|
||||
extern char *dmxConfigGetXkbVariant(void);
|
||||
extern char *dmxConfigGetXkbOptions(void);
|
||||
#endif
|
|
@ -1,688 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* This file provides support routines and helper functions to be used
|
||||
* by the DMX configuration file parser.
|
||||
*
|
||||
* Because the DMX configuration file parsing should be capable of being
|
||||
* used in a stand-alone fashion (i.e., independent from the DMX server
|
||||
* source tree), no dependencies on other DMX routines are made. */
|
||||
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include "dmxparse.h"
|
||||
|
||||
/** A general error logging routine that does not depend on the dmxLog
|
||||
* functions. */
|
||||
void
|
||||
dmxConfigLog(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
vprintf(format, args); /* RATS: All calls to dmxConfigLog from
|
||||
* dmxparse.c and dmxprint.c use a
|
||||
* trusted format. */
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void *
|
||||
dmxConfigAlloc(unsigned long bytes)
|
||||
{
|
||||
void *area = calloc(1, bytes);
|
||||
|
||||
if (!area) {
|
||||
dmxConfigLog("dmxConfigAlloc: out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
return area;
|
||||
}
|
||||
|
||||
void *
|
||||
dmxConfigRealloc(void *orig, unsigned long orig_bytes, unsigned long bytes)
|
||||
{
|
||||
unsigned char *area = realloc(orig, bytes);
|
||||
|
||||
if (!area) {
|
||||
dmxConfigLog("dmxConfigRealloc: out of memory\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(area + orig_bytes, 0, bytes - orig_bytes);
|
||||
return area;
|
||||
}
|
||||
|
||||
const char *
|
||||
dmxConfigCopyString(const char *string, int length)
|
||||
{
|
||||
char *copy;
|
||||
|
||||
if (!length)
|
||||
length = strlen(string);
|
||||
copy = dmxConfigAlloc(length + 1);
|
||||
if (length)
|
||||
strncpy(copy, string, length);
|
||||
copy[length] = '\0';
|
||||
return copy;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFree(void *area)
|
||||
{
|
||||
free(area);
|
||||
}
|
||||
|
||||
DMXConfigTokenPtr
|
||||
dmxConfigCreateToken(int token, int line, const char *comment)
|
||||
{
|
||||
DMXConfigTokenPtr pToken = dmxConfigAlloc(sizeof(*pToken));
|
||||
|
||||
pToken->token = token;
|
||||
pToken->line = line;
|
||||
pToken->comment = comment;
|
||||
return pToken;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeToken(DMXConfigTokenPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFree((void *) p->comment);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigStringPtr
|
||||
dmxConfigCreateString(int token, int line,
|
||||
const char *comment, const char *string)
|
||||
{
|
||||
DMXConfigStringPtr pString = dmxConfigAlloc(sizeof(*pString));
|
||||
|
||||
pString->token = token;
|
||||
pString->line = line;
|
||||
pString->comment = comment;
|
||||
pString->string = string;
|
||||
return pString;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeString(DMXConfigStringPtr p)
|
||||
{
|
||||
DMXConfigStringPtr next;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
do {
|
||||
next = p->next;
|
||||
dmxConfigFree((void *) p->comment);
|
||||
dmxConfigFree((void *) p->string);
|
||||
dmxConfigFree(p);
|
||||
} while ((p = next));
|
||||
}
|
||||
|
||||
DMXConfigNumberPtr
|
||||
dmxConfigCreateNumber(int token, int line, const char *comment, int number)
|
||||
{
|
||||
DMXConfigNumberPtr pNumber = dmxConfigAlloc(sizeof(*pNumber));
|
||||
|
||||
pNumber->token = token;
|
||||
pNumber->line = line;
|
||||
pNumber->comment = comment;
|
||||
pNumber->number = number;
|
||||
return pNumber;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeNumber(DMXConfigNumberPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFree((void *) p->comment);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigPairPtr
|
||||
dmxConfigCreatePair(int token, int line,
|
||||
const char *comment, int x, int y, int xsign, int ysign)
|
||||
{
|
||||
DMXConfigPairPtr pPair = dmxConfigAlloc(sizeof(*pPair));
|
||||
|
||||
pPair->token = token;
|
||||
pPair->line = line;
|
||||
pPair->comment = comment;
|
||||
pPair->x = x;
|
||||
pPair->y = y;
|
||||
pPair->xsign = (xsign < 0) ? -1 : 1;
|
||||
pPair->ysign = (ysign < 0) ? -1 : 1;
|
||||
return pPair;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreePair(DMXConfigPairPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFree((void *) p->comment);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigCommentPtr
|
||||
dmxConfigCreateComment(int token, int line, const char *comment)
|
||||
{
|
||||
DMXConfigCommentPtr pComment = dmxConfigAlloc(sizeof(*pComment));
|
||||
|
||||
pComment->token = token;
|
||||
pComment->line = line;
|
||||
pComment->comment = comment;
|
||||
return pComment;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeComment(DMXConfigCommentPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFree((void *) p->comment);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigPartDimPtr
|
||||
dmxConfigCreatePartDim(DMXConfigPairPtr pDim, DMXConfigPairPtr pOffset)
|
||||
{
|
||||
DMXConfigPartDimPtr pPart = dmxConfigAlloc(sizeof(*pPart));
|
||||
|
||||
pPart->dim = pDim;
|
||||
pPart->offset = pOffset;
|
||||
return pPart;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreePartDim(DMXConfigPartDimPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFreePair(p->dim);
|
||||
dmxConfigFreePair(p->offset);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigFullDimPtr
|
||||
dmxConfigCreateFullDim(DMXConfigPartDimPtr pScrn, DMXConfigPartDimPtr pRoot)
|
||||
{
|
||||
DMXConfigFullDimPtr pFull = dmxConfigAlloc(sizeof(*pFull));
|
||||
|
||||
pFull->scrn = pScrn;
|
||||
pFull->root = pRoot;
|
||||
return pFull;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeFullDim(DMXConfigFullDimPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFreePartDim(p->scrn);
|
||||
dmxConfigFreePartDim(p->root);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigDisplayPtr
|
||||
dmxConfigCreateDisplay(DMXConfigTokenPtr pStart,
|
||||
DMXConfigStringPtr pName,
|
||||
DMXConfigFullDimPtr pDim,
|
||||
DMXConfigPairPtr pOrigin, DMXConfigTokenPtr pEnd)
|
||||
{
|
||||
DMXConfigDisplayPtr pDisplay = dmxConfigAlloc(sizeof(*pDisplay));
|
||||
|
||||
pDisplay->start = pStart;
|
||||
pDisplay->dname = pName;
|
||||
pDisplay->dim = pDim;
|
||||
pDisplay->origin = pOrigin;
|
||||
pDisplay->end = pEnd;
|
||||
|
||||
pDisplay->name = pName ? pName->string : NULL;
|
||||
pDisplay->rootXOrigin = pOrigin ? pOrigin->x : 0;
|
||||
pDisplay->rootYOrigin = pOrigin ? pOrigin->y : 0;
|
||||
|
||||
if (pDim && pDim->scrn && pDim->scrn->dim) {
|
||||
pDisplay->scrnWidth = pDim->scrn->dim->x;
|
||||
pDisplay->scrnHeight = pDim->scrn->dim->y;
|
||||
}
|
||||
if (pDim && pDim->scrn && pDim->scrn->offset) {
|
||||
pDisplay->scrnX = pDim->scrn->offset->x;
|
||||
pDisplay->scrnY = pDim->scrn->offset->y;
|
||||
pDisplay->scrnXSign = pDim->scrn->offset->xsign;
|
||||
pDisplay->scrnYSign = pDim->scrn->offset->ysign;
|
||||
}
|
||||
|
||||
if (pDim && pDim->root) {
|
||||
if (pDim->root->dim) {
|
||||
pDisplay->rootWidth = pDim->root->dim->x;
|
||||
pDisplay->rootHeight = pDim->root->dim->y;
|
||||
}
|
||||
if (pDim->root->offset) {
|
||||
pDisplay->rootX = pDim->root->offset->x;
|
||||
pDisplay->rootY = pDim->root->offset->y;
|
||||
pDisplay->rootXSign = pDim->root->offset->xsign;
|
||||
pDisplay->rootYSign = pDim->root->offset->ysign;
|
||||
}
|
||||
}
|
||||
else { /* If no root specification, copy width
|
||||
* and height from scrn -- leave offset
|
||||
* as zero, since it is relative to
|
||||
* scrn. */
|
||||
pDisplay->rootWidth = pDisplay->scrnWidth;
|
||||
pDisplay->rootHeight = pDisplay->scrnHeight;
|
||||
}
|
||||
|
||||
return pDisplay;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeDisplay(DMXConfigDisplayPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFreeToken(p->start);
|
||||
dmxConfigFreeString(p->dname);
|
||||
dmxConfigFreeFullDim(p->dim);
|
||||
dmxConfigFreeToken(p->end);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigWallPtr
|
||||
dmxConfigCreateWall(DMXConfigTokenPtr pStart,
|
||||
DMXConfigPairPtr pWallDim,
|
||||
DMXConfigPairPtr pDisplayDim,
|
||||
DMXConfigStringPtr pNameList, DMXConfigTokenPtr pEnd)
|
||||
{
|
||||
DMXConfigWallPtr pWall = dmxConfigAlloc(sizeof(*pWall));
|
||||
|
||||
pWall->start = pStart;
|
||||
pWall->wallDim = pWallDim;
|
||||
pWall->displayDim = pDisplayDim;
|
||||
pWall->nameList = pNameList;
|
||||
pWall->end = pEnd;
|
||||
|
||||
pWall->width = pDisplayDim ? pDisplayDim->x : 0;
|
||||
pWall->height = pDisplayDim ? pDisplayDim->y : 0;
|
||||
pWall->xwall = pWallDim ? pWallDim->x : 0;
|
||||
pWall->ywall = pWallDim ? pWallDim->y : 0;
|
||||
|
||||
return pWall;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeWall(DMXConfigWallPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
dmxConfigFreeToken(p->start);
|
||||
dmxConfigFreePair(p->wallDim);
|
||||
dmxConfigFreePair(p->displayDim);
|
||||
dmxConfigFreeString(p->nameList);
|
||||
dmxConfigFreeToken(p->end);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
DMXConfigOptionPtr
|
||||
dmxConfigCreateOption(DMXConfigTokenPtr pStart,
|
||||
DMXConfigStringPtr pOption, DMXConfigTokenPtr pEnd)
|
||||
{
|
||||
int length = 0;
|
||||
int offset = 0;
|
||||
DMXConfigStringPtr p;
|
||||
DMXConfigOptionPtr option = dmxConfigAlloc(sizeof(*option));
|
||||
|
||||
for (p = pOption; p; p = p->next) {
|
||||
if (p->string)
|
||||
length += strlen(p->string) + 1;
|
||||
}
|
||||
|
||||
option->string = dmxConfigAlloc(length + 1);
|
||||
|
||||
for (p = pOption; p; p = p->next) {
|
||||
if (p->string) {
|
||||
int len = strlen(p->string);
|
||||
|
||||
memcpy(option->string + offset, p->string, len);
|
||||
offset += len;
|
||||
if (p->next)
|
||||
option->string[offset++] = ' ';
|
||||
}
|
||||
}
|
||||
option->string[offset] = '\0';
|
||||
|
||||
option->start = pStart;
|
||||
option->option = pOption;
|
||||
option->end = pEnd;
|
||||
|
||||
return option;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeOption(DMXConfigOptionPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
free(p->string);
|
||||
dmxConfigFreeToken(p->start);
|
||||
dmxConfigFreeString(p->option);
|
||||
dmxConfigFreeToken(p->end);
|
||||
dmxConfigFree(p);
|
||||
}
|
||||
|
||||
const char **
|
||||
dmxConfigLookupParam(DMXConfigParamPtr p, const char *key, int *argc)
|
||||
{
|
||||
DMXConfigParamPtr pt;
|
||||
|
||||
for (pt = p; pt; pt = pt->next) {
|
||||
if (pt->argv && !strcasecmp(pt->argv[0], key)) {
|
||||
*argc = pt->argc;
|
||||
return pt->argv;
|
||||
}
|
||||
}
|
||||
*argc = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DMXConfigParamPtr
|
||||
dmxConfigCreateParam(DMXConfigTokenPtr pStart,
|
||||
DMXConfigTokenPtr pOpen,
|
||||
DMXConfigStringPtr pParam,
|
||||
DMXConfigTokenPtr pClose, DMXConfigTokenPtr pEnd)
|
||||
{
|
||||
DMXConfigParamPtr param = dmxConfigAlloc(sizeof(*param));
|
||||
DMXConfigStringPtr pt;
|
||||
|
||||
param->argc = 0;
|
||||
param->argv = NULL;
|
||||
for (pt = pParam; pt; pt = pt->next) {
|
||||
if (pt->string) {
|
||||
param->argv = realloc(param->argv,
|
||||
(param->argc + 2) * sizeof(*param->argv));
|
||||
param->argv[param->argc] = pt->string;
|
||||
++param->argc;
|
||||
}
|
||||
}
|
||||
if (param->argv)
|
||||
param->argv[param->argc] = NULL;
|
||||
|
||||
param->start = pStart;
|
||||
param->open = pOpen;
|
||||
param->param = pParam;
|
||||
param->close = pClose;
|
||||
param->end = pEnd;
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeParam(DMXConfigParamPtr p)
|
||||
{
|
||||
DMXConfigParamPtr next;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
do {
|
||||
next = p->next;
|
||||
dmxConfigFreeToken(p->start);
|
||||
dmxConfigFreeToken(p->open);
|
||||
dmxConfigFreeString(p->param);
|
||||
dmxConfigFreeToken(p->close);
|
||||
dmxConfigFreeToken(p->end);
|
||||
dmxConfigFree(p->argv);
|
||||
dmxConfigFree(p);
|
||||
} while ((p = next));
|
||||
}
|
||||
|
||||
DMXConfigSubPtr
|
||||
dmxConfigCreateSub(DMXConfigType type,
|
||||
DMXConfigCommentPtr comment,
|
||||
DMXConfigDisplayPtr display,
|
||||
DMXConfigWallPtr wall,
|
||||
DMXConfigOptionPtr option, DMXConfigParamPtr param)
|
||||
{
|
||||
DMXConfigSubPtr pSub = dmxConfigAlloc(sizeof(*pSub));
|
||||
|
||||
pSub->type = type;
|
||||
switch (type) {
|
||||
case dmxConfigComment:
|
||||
pSub->comment = comment;
|
||||
break;
|
||||
case dmxConfigDisplay:
|
||||
pSub->display = display;
|
||||
break;
|
||||
case dmxConfigWall:
|
||||
pSub->wall = wall;
|
||||
break;
|
||||
case dmxConfigOption:
|
||||
pSub->option = option;
|
||||
break;
|
||||
case dmxConfigParam:
|
||||
pSub->param = param;
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("Type %d not supported in subentry\n", type);
|
||||
break;
|
||||
}
|
||||
return pSub;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeSub(DMXConfigSubPtr sub)
|
||||
{
|
||||
DMXConfigSubPtr pt;
|
||||
|
||||
for (pt = sub; pt; pt = pt->next) {
|
||||
switch (pt->type) {
|
||||
case dmxConfigComment:
|
||||
dmxConfigFreeComment(pt->comment);
|
||||
break;
|
||||
case dmxConfigDisplay:
|
||||
dmxConfigFreeDisplay(pt->display);
|
||||
break;
|
||||
case dmxConfigWall:
|
||||
dmxConfigFreeWall(pt->wall);
|
||||
break;
|
||||
case dmxConfigOption:
|
||||
dmxConfigFreeOption(pt->option);
|
||||
break;
|
||||
case dmxConfigParam:
|
||||
dmxConfigFreeParam(pt->param);
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("Type %d not supported in subentry\n", pt->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
dmxConfigFree(sub);
|
||||
}
|
||||
|
||||
DMXConfigSubPtr
|
||||
dmxConfigSubComment(DMXConfigCommentPtr comment)
|
||||
{
|
||||
return dmxConfigCreateSub(dmxConfigComment, comment, NULL, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
DMXConfigSubPtr
|
||||
dmxConfigSubDisplay(DMXConfigDisplayPtr display)
|
||||
{
|
||||
return dmxConfigCreateSub(dmxConfigDisplay, NULL, display, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
DMXConfigSubPtr
|
||||
dmxConfigSubWall(DMXConfigWallPtr wall)
|
||||
{
|
||||
return dmxConfigCreateSub(dmxConfigWall, NULL, NULL, wall, NULL, NULL);
|
||||
}
|
||||
|
||||
DMXConfigSubPtr
|
||||
dmxConfigSubOption(DMXConfigOptionPtr option)
|
||||
{
|
||||
return dmxConfigCreateSub(dmxConfigOption, NULL, NULL, NULL, option, NULL);
|
||||
}
|
||||
|
||||
DMXConfigSubPtr
|
||||
dmxConfigSubParam(DMXConfigParamPtr param)
|
||||
{
|
||||
return dmxConfigCreateSub(dmxConfigParam, NULL, NULL, NULL, NULL, param);
|
||||
}
|
||||
|
||||
extern DMXConfigSubPtr
|
||||
dmxConfigAddSub(DMXConfigSubPtr head, DMXConfigSubPtr sub)
|
||||
{
|
||||
DMXConfigSubPtr pt;
|
||||
|
||||
if (!head)
|
||||
return sub;
|
||||
for (pt = head; pt->next; pt = pt->next);
|
||||
pt->next = sub;
|
||||
return head;
|
||||
}
|
||||
|
||||
DMXConfigVirtualPtr
|
||||
dmxConfigCreateVirtual(DMXConfigTokenPtr pStart,
|
||||
DMXConfigStringPtr pName,
|
||||
DMXConfigPairPtr pDim,
|
||||
DMXConfigTokenPtr pOpen,
|
||||
DMXConfigSubPtr pSubentry, DMXConfigTokenPtr pClose)
|
||||
{
|
||||
DMXConfigVirtualPtr pVirtual = dmxConfigAlloc(sizeof(*pVirtual));
|
||||
|
||||
pVirtual->start = pStart;
|
||||
pVirtual->vname = pName;
|
||||
pVirtual->dim = pDim;
|
||||
pVirtual->open = pOpen;
|
||||
pVirtual->subentry = pSubentry;
|
||||
pVirtual->close = pClose;
|
||||
|
||||
pVirtual->name = pName ? pName->string : NULL;
|
||||
pVirtual->width = pDim ? pDim->x : 0;
|
||||
pVirtual->height = pDim ? pDim->y : 0;
|
||||
|
||||
return pVirtual;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeVirtual(DMXConfigVirtualPtr virtual)
|
||||
{
|
||||
dmxConfigFreeToken(virtual->start);
|
||||
dmxConfigFreeString(virtual->vname);
|
||||
dmxConfigFreePair(virtual->dim);
|
||||
dmxConfigFreeToken(virtual->open);
|
||||
dmxConfigFreeSub(virtual->subentry);
|
||||
dmxConfigFreeToken(virtual->close);
|
||||
dmxConfigFree(virtual);
|
||||
}
|
||||
|
||||
DMXConfigEntryPtr
|
||||
dmxConfigCreateEntry(DMXConfigType type,
|
||||
DMXConfigCommentPtr comment, DMXConfigVirtualPtr virtual)
|
||||
{
|
||||
DMXConfigEntryPtr pEntry = dmxConfigAlloc(sizeof(*pEntry));
|
||||
|
||||
pEntry->type = type;
|
||||
switch (type) {
|
||||
case dmxConfigComment:
|
||||
pEntry->comment = comment;
|
||||
break;
|
||||
case dmxConfigVirtual:
|
||||
pEntry->virtual = virtual;
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("Type %d not supported in entry\n", type);
|
||||
break;
|
||||
}
|
||||
return pEntry;
|
||||
}
|
||||
|
||||
void
|
||||
dmxConfigFreeEntry(DMXConfigEntryPtr entry)
|
||||
{
|
||||
DMXConfigEntryPtr pt;
|
||||
|
||||
for (pt = entry; pt; pt = pt->next) {
|
||||
switch (pt->type) {
|
||||
case dmxConfigComment:
|
||||
dmxConfigFreeComment(pt->comment);
|
||||
break;
|
||||
case dmxConfigVirtual:
|
||||
dmxConfigFreeVirtual(pt->virtual);
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("Type %d not supported in entry\n", pt->type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
dmxConfigFree(entry);
|
||||
}
|
||||
|
||||
DMXConfigEntryPtr
|
||||
dmxConfigAddEntry(DMXConfigEntryPtr head,
|
||||
DMXConfigType type,
|
||||
DMXConfigCommentPtr comment, DMXConfigVirtualPtr virtual)
|
||||
{
|
||||
DMXConfigEntryPtr child = dmxConfigCreateEntry(type, comment, virtual);
|
||||
DMXConfigEntryPtr pt;
|
||||
|
||||
if (!head)
|
||||
return child;
|
||||
|
||||
for (pt = head; pt->next; pt = pt->next);
|
||||
pt->next = child;
|
||||
|
||||
return head;
|
||||
}
|
||||
|
||||
DMXConfigEntryPtr
|
||||
dmxConfigEntryComment(DMXConfigCommentPtr comment)
|
||||
{
|
||||
return dmxConfigCreateEntry(dmxConfigComment, comment, NULL);
|
||||
}
|
||||
|
||||
DMXConfigEntryPtr
|
||||
dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual)
|
||||
{
|
||||
return dmxConfigCreateEntry(dmxConfigVirtual, NULL, virtual);
|
||||
}
|
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Interface to DMX configuration file parser. \see dmxparse.c */
|
||||
|
||||
#ifndef _DMXPARSE_H_
|
||||
#define _DMXPARSE_H_
|
||||
|
||||
#include <stdio.h> /* For FILE */
|
||||
#include <X11/Xfuncproto.h> /* For _X_ATTRIBUTE_PRINTF */
|
||||
|
||||
/** Stores tokens not stored in other structures (e.g., keywords and ;) */
|
||||
typedef struct _DMXConfigToken {
|
||||
int token;
|
||||
int line;
|
||||
const char *comment;
|
||||
} DMXConfigToken, *DMXConfigTokenPtr;
|
||||
|
||||
/** Stores parsed strings. */
|
||||
typedef struct _DMXConfigString {
|
||||
int token;
|
||||
int line;
|
||||
const char *comment;
|
||||
const char *string;
|
||||
struct _DMXConfigString *next;
|
||||
} DMXConfigString, *DMXConfigStringPtr;
|
||||
|
||||
/** Stores parsed numbers. */
|
||||
typedef struct _DMXConfigNumber {
|
||||
int token;
|
||||
int line;
|
||||
const char *comment;
|
||||
int number;
|
||||
} DMXConfigNumber, *DMXConfigNumberPtr;
|
||||
|
||||
/** Stores parsed pairs (e.g., x y) */
|
||||
typedef struct _DMXConfigPair {
|
||||
int token;
|
||||
int line;
|
||||
const char *comment;
|
||||
int x;
|
||||
int y;
|
||||
int xsign;
|
||||
int ysign;
|
||||
} DMXConfigPair, *DMXConfigPairPtr;
|
||||
|
||||
/** Stores parsed comments not stored with a token. */
|
||||
typedef struct _DMXConfigComment {
|
||||
int token;
|
||||
int line;
|
||||
const char *comment;
|
||||
} DMXConfigComment, *DMXConfigCommentPtr;
|
||||
|
||||
typedef enum {
|
||||
dmxConfigComment,
|
||||
dmxConfigVirtual,
|
||||
dmxConfigDisplay,
|
||||
dmxConfigWall,
|
||||
dmxConfigOption,
|
||||
dmxConfigParam
|
||||
} DMXConfigType;
|
||||
|
||||
/** Stores a geometry specification. */
|
||||
typedef struct _DMXConfigPartDim {
|
||||
DMXConfigPairPtr dim;
|
||||
DMXConfigPairPtr offset;
|
||||
} DMXConfigPartDim, *DMXConfigPartDimPtr;
|
||||
|
||||
/** Stores a pair of geometry specifications. */
|
||||
typedef struct _DMXConfigFullDim {
|
||||
DMXConfigPartDimPtr scrn;
|
||||
DMXConfigPartDimPtr root;
|
||||
} DMXConfigFullDim, *DMXConfigFullDimPtr;
|
||||
|
||||
/** Stores parsed display information. */
|
||||
typedef struct _DMXConfigDisplay {
|
||||
/* Summary information */
|
||||
const char *name;
|
||||
/* Screen Window Geometry */
|
||||
int scrnWidth, scrnHeight;
|
||||
int scrnX, scrnY;
|
||||
int scrnXSign, scrnYSign;
|
||||
/* Root Window Geometry */
|
||||
int rootWidth, rootHeight;
|
||||
int rootX, rootY;
|
||||
int rootXSign, rootYSign;
|
||||
/* Origin in global space */
|
||||
int rootXOrigin, rootYOrigin;
|
||||
|
||||
/* Raw configuration information */
|
||||
DMXConfigTokenPtr start;
|
||||
DMXConfigStringPtr dname;
|
||||
DMXConfigFullDimPtr dim;
|
||||
DMXConfigPairPtr origin;
|
||||
DMXConfigTokenPtr end;
|
||||
} DMXConfigDisplay, *DMXConfigDisplayPtr;
|
||||
|
||||
/** Stores parsed wall information. */
|
||||
typedef struct _DMXConfigWall {
|
||||
/* Summary information */
|
||||
int width, height; /* dimensions of displays */
|
||||
int xwall, ywall; /* dimensions of wall, in tiles */
|
||||
|
||||
/* Raw configuration information */
|
||||
DMXConfigTokenPtr start;
|
||||
DMXConfigPairPtr wallDim;
|
||||
DMXConfigPairPtr displayDim;
|
||||
DMXConfigStringPtr nameList;
|
||||
DMXConfigTokenPtr end;
|
||||
} DMXConfigWall, *DMXConfigWallPtr;
|
||||
|
||||
/** Stores parsed option information. */
|
||||
typedef struct _DMXConfigOption {
|
||||
/* Summary information */
|
||||
char *string;
|
||||
|
||||
/* Raw configuration information */
|
||||
DMXConfigTokenPtr start;
|
||||
DMXConfigStringPtr option;
|
||||
DMXConfigTokenPtr end;
|
||||
} DMXConfigOption, *DMXConfigOptionPtr;
|
||||
|
||||
/** Stores parsed param information. */
|
||||
typedef struct _DMXConfigParam {
|
||||
int argc;
|
||||
const char **argv;
|
||||
|
||||
DMXConfigTokenPtr start;
|
||||
DMXConfigTokenPtr open;
|
||||
DMXConfigStringPtr param;
|
||||
DMXConfigTokenPtr close;
|
||||
DMXConfigTokenPtr end; /* Either open/close OR end */
|
||||
struct _DMXConfigParam *next;
|
||||
} DMXConfigParam, *DMXConfigParamPtr;
|
||||
|
||||
/** Stores options under an entry (subentry). */
|
||||
typedef struct _DMXConfigSub {
|
||||
DMXConfigType type;
|
||||
DMXConfigCommentPtr comment;
|
||||
DMXConfigDisplayPtr display;
|
||||
DMXConfigWallPtr wall;
|
||||
DMXConfigOptionPtr option;
|
||||
DMXConfigParamPtr param;
|
||||
struct _DMXConfigSub *next;
|
||||
} DMXConfigSub, *DMXConfigSubPtr;
|
||||
|
||||
/** Stores parsed virtual information. */
|
||||
typedef struct _DMXConfigVirtual {
|
||||
/* Summary information */
|
||||
const char *name;
|
||||
int width, height;
|
||||
|
||||
/* Raw configuration information */
|
||||
DMXConfigTokenPtr start;
|
||||
DMXConfigStringPtr vname;
|
||||
DMXConfigPairPtr dim;
|
||||
DMXConfigTokenPtr open;
|
||||
DMXConfigSubPtr subentry;
|
||||
DMXConfigTokenPtr close;
|
||||
} DMXConfigVirtual, *DMXConfigVirtualPtr;
|
||||
|
||||
/** Heads entry storage. */
|
||||
typedef struct _DMXConfigEntry {
|
||||
DMXConfigType type;
|
||||
DMXConfigCommentPtr comment;
|
||||
DMXConfigVirtualPtr virtual;
|
||||
struct _DMXConfigEntry *next;
|
||||
} DMXConfigEntry, *DMXConfigEntryPtr;
|
||||
|
||||
extern DMXConfigEntryPtr dmxConfigEntry;
|
||||
|
||||
extern void yyerror(const char *message);
|
||||
|
||||
extern void dmxConfigLog(const char *format, ...) _X_ATTRIBUTE_PRINTF(1,0);
|
||||
extern void *dmxConfigAlloc(unsigned long bytes);
|
||||
extern void *dmxConfigRealloc(void *orig,
|
||||
unsigned long orig_bytes, unsigned long bytes);
|
||||
extern const char *dmxConfigCopyString(const char *string, int length);
|
||||
extern void dmxConfigFree(void *area);
|
||||
extern DMXConfigTokenPtr dmxConfigCreateToken(int token, int line,
|
||||
const char *comment);
|
||||
extern void dmxConfigFreeToken(DMXConfigTokenPtr p);
|
||||
extern DMXConfigStringPtr dmxConfigCreateString(int token, int line,
|
||||
const char *comment,
|
||||
const char *string);
|
||||
extern void dmxConfigFreeString(DMXConfigStringPtr p);
|
||||
extern DMXConfigNumberPtr dmxConfigCreateNumber(int token, int line,
|
||||
const char *comment,
|
||||
int number);
|
||||
extern void dmxConfigFreeNumber(DMXConfigNumberPtr p);
|
||||
extern DMXConfigPairPtr dmxConfigCreatePair(int token, int line,
|
||||
const char *comment,
|
||||
int x, int y, int xsign, int ysign);
|
||||
extern void dmxConfigFreePair(DMXConfigPairPtr p);
|
||||
extern DMXConfigCommentPtr dmxConfigCreateComment(int token, int line,
|
||||
const char *comment);
|
||||
extern void dmxConfigFreeComment(DMXConfigCommentPtr p);
|
||||
extern DMXConfigPartDimPtr dmxConfigCreatePartDim(DMXConfigPairPtr pDim,
|
||||
DMXConfigPairPtr pOffset);
|
||||
extern void dmxConfigFreePartDim(DMXConfigPartDimPtr p);
|
||||
extern DMXConfigFullDimPtr dmxConfigCreateFullDim(DMXConfigPartDimPtr pScrn,
|
||||
DMXConfigPartDimPtr pRoot);
|
||||
extern void dmxConfigFreeFullDim(DMXConfigFullDimPtr p);
|
||||
extern DMXConfigDisplayPtr dmxConfigCreateDisplay(DMXConfigTokenPtr pStart,
|
||||
DMXConfigStringPtr pName,
|
||||
DMXConfigFullDimPtr pDim,
|
||||
DMXConfigPairPtr pOrigin,
|
||||
DMXConfigTokenPtr pEnd);
|
||||
extern void dmxConfigFreeDisplay(DMXConfigDisplayPtr p);
|
||||
extern DMXConfigWallPtr dmxConfigCreateWall(DMXConfigTokenPtr pStart,
|
||||
DMXConfigPairPtr pWallDim,
|
||||
DMXConfigPairPtr pDisplayDim,
|
||||
DMXConfigStringPtr pNameList,
|
||||
DMXConfigTokenPtr pEnd);
|
||||
extern void dmxConfigFreeWall(DMXConfigWallPtr p);
|
||||
extern DMXConfigOptionPtr dmxConfigCreateOption(DMXConfigTokenPtr pStart,
|
||||
DMXConfigStringPtr pOption,
|
||||
DMXConfigTokenPtr pEnd);
|
||||
extern void dmxConfigFreeOption(DMXConfigOptionPtr p);
|
||||
extern DMXConfigParamPtr dmxConfigCreateParam(DMXConfigTokenPtr pStart,
|
||||
DMXConfigTokenPtr pOpen,
|
||||
DMXConfigStringPtr pParam,
|
||||
DMXConfigTokenPtr pClose,
|
||||
DMXConfigTokenPtr pEnd);
|
||||
extern void dmxConfigFreeParam(DMXConfigParamPtr p);
|
||||
extern const char **dmxConfigLookupParam(DMXConfigParamPtr p,
|
||||
const char *key, int *argc);
|
||||
extern DMXConfigSubPtr dmxConfigCreateSub(DMXConfigType type,
|
||||
DMXConfigCommentPtr comment,
|
||||
DMXConfigDisplayPtr display,
|
||||
DMXConfigWallPtr wall,
|
||||
DMXConfigOptionPtr option,
|
||||
DMXConfigParamPtr param);
|
||||
extern void dmxConfigFreeSub(DMXConfigSubPtr sub);
|
||||
extern DMXConfigSubPtr dmxConfigSubComment(DMXConfigCommentPtr comment);
|
||||
extern DMXConfigSubPtr dmxConfigSubDisplay(DMXConfigDisplayPtr display);
|
||||
extern DMXConfigSubPtr dmxConfigSubWall(DMXConfigWallPtr wall);
|
||||
extern DMXConfigSubPtr dmxConfigSubOption(DMXConfigOptionPtr option);
|
||||
extern DMXConfigSubPtr dmxConfigSubParam(DMXConfigParamPtr param);
|
||||
extern DMXConfigSubPtr dmxConfigAddSub(DMXConfigSubPtr head,
|
||||
DMXConfigSubPtr sub);
|
||||
extern DMXConfigVirtualPtr dmxConfigCreateVirtual(DMXConfigTokenPtr pStart,
|
||||
DMXConfigStringPtr pName,
|
||||
DMXConfigPairPtr pDim,
|
||||
DMXConfigTokenPtr pOpen,
|
||||
DMXConfigSubPtr pSubentry,
|
||||
DMXConfigTokenPtr pClose);
|
||||
extern void dmxConfigFreeVirtual(DMXConfigVirtualPtr virtual);
|
||||
extern DMXConfigEntryPtr dmxConfigCreateEntry(DMXConfigType type,
|
||||
DMXConfigCommentPtr comment,
|
||||
DMXConfigVirtualPtr virtual);
|
||||
extern void dmxConfigFreeEntry(DMXConfigEntryPtr entry);
|
||||
extern DMXConfigEntryPtr dmxConfigAddEntry(DMXConfigEntryPtr head,
|
||||
DMXConfigType type,
|
||||
DMXConfigCommentPtr comment,
|
||||
DMXConfigVirtualPtr virtual);
|
||||
extern DMXConfigEntryPtr dmxConfigEntryComment(DMXConfigCommentPtr comment);
|
||||
extern DMXConfigEntryPtr dmxConfigEntryVirtual(DMXConfigVirtualPtr virtual);
|
||||
|
||||
#endif
|
|
@ -1,532 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* This file provides support routines and helper functions to be used
|
||||
* to pretty-print DMX configurations.
|
||||
*
|
||||
* Because the DMX configuration file parsing should be capable of being
|
||||
* used in a stand-alone fashion (i.e., independent from the DMX server
|
||||
* source tree), no dependencies on other DMX routines are made. */
|
||||
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include "dmxconfig.h"
|
||||
#include "dmxparse.h"
|
||||
#include "dmxprint.h"
|
||||
#include "parser.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
static FILE *str = NULL;
|
||||
static int indent = 0;
|
||||
static int pos = 0;
|
||||
|
||||
/** Stack of indentation information used for pretty-printing
|
||||
* configuration information. */
|
||||
static struct stack {
|
||||
int base;
|
||||
int comment;
|
||||
int step;
|
||||
struct stack *next;
|
||||
} *stack, initialStack = {
|
||||
0, 0, 4, NULL};
|
||||
|
||||
static void
|
||||
dmxConfigIndent(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (indent < 0)
|
||||
indent = 0;
|
||||
if (indent > 40)
|
||||
indent = 40;
|
||||
for (i = 0; i < indent; i++)
|
||||
fprintf(str, " ");
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigNewline(void)
|
||||
{
|
||||
if (pos)
|
||||
fprintf(str, "\n");
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPushState(int base, int comment, int step)
|
||||
{
|
||||
struct stack *new = dmxConfigAlloc(sizeof(*new));
|
||||
|
||||
new->base = base;
|
||||
new->comment = comment;
|
||||
new->step = step;
|
||||
new->next = stack;
|
||||
stack = new;
|
||||
indent = base;
|
||||
dmxConfigNewline();
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPushComment(void)
|
||||
{
|
||||
if (stack)
|
||||
indent = stack->comment;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPushStep(void)
|
||||
{
|
||||
if (stack)
|
||||
indent = stack->step;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPopState(void)
|
||||
{
|
||||
struct stack *old = stack;
|
||||
|
||||
if (!stack)
|
||||
return;
|
||||
indent = old->base;
|
||||
stack = old->next;
|
||||
if (!stack)
|
||||
dmxConfigLog("Stack underflow\n");
|
||||
dmxConfigFree(old);
|
||||
dmxConfigNewline();
|
||||
}
|
||||
|
||||
static void _X_ATTRIBUTE_PRINTF(4, 5)
|
||||
dmxConfigOutput(int addSpace, int doNewline, const char *comment,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!pos)
|
||||
dmxConfigIndent();
|
||||
else if (addSpace)
|
||||
fprintf(str, " ");
|
||||
|
||||
if (format) {
|
||||
va_start(args, format);
|
||||
/* RATS: This hasn't been audited -- it
|
||||
* could probably result in a buffer
|
||||
* overflow. */
|
||||
pos += vfprintf(str, format, args); /* assumes no newlines! */
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
if (pos)
|
||||
fprintf(str, " ");
|
||||
pos += fprintf(str, "#%s", comment);
|
||||
dmxConfigNewline();
|
||||
dmxConfigPushComment();
|
||||
}
|
||||
else if (doNewline)
|
||||
dmxConfigNewline();
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintComment(DMXConfigCommentPtr p)
|
||||
{
|
||||
dmxConfigOutput(1, 1, p->comment, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintTokenFlag(DMXConfigTokenPtr p, int flag)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
switch (p->token) {
|
||||
case T_VIRTUAL:
|
||||
dmxConfigPushState(0, 4, 4);
|
||||
dmxConfigOutput(0, 0, p->comment, "virtual");
|
||||
break;
|
||||
case T_DISPLAY:
|
||||
dmxConfigPushState(4, 12, 16);
|
||||
dmxConfigOutput(0, 0, p->comment, "display");
|
||||
break;
|
||||
case T_WALL:
|
||||
dmxConfigPushState(4, 12, 16);
|
||||
dmxConfigOutput(0, 0, p->comment, "wall");
|
||||
break;
|
||||
case T_OPTION:
|
||||
dmxConfigPushState(4, 12, 16);
|
||||
dmxConfigOutput(0, 0, p->comment, "option");
|
||||
break;
|
||||
case T_PARAM:
|
||||
dmxConfigPushState(4, 8, 12);
|
||||
dmxConfigOutput(0, 0, p->comment, "param");
|
||||
break;
|
||||
case ';':
|
||||
dmxConfigOutput(0, 1, p->comment, ";");
|
||||
if (flag)
|
||||
dmxConfigPopState();
|
||||
break;
|
||||
case '{':
|
||||
dmxConfigOutput(1, 1, p->comment, "{");
|
||||
dmxConfigPushStep();
|
||||
break;
|
||||
case '}':
|
||||
if (flag)
|
||||
dmxConfigPopState();
|
||||
dmxConfigOutput(0, 1, p->comment, "}");
|
||||
break;
|
||||
case '/':
|
||||
dmxConfigOutput(1, 0, NULL, "/");
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("unknown token %d on line %d\n", p->token, p->line);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintToken(DMXConfigTokenPtr p)
|
||||
{
|
||||
dmxConfigPrintTokenFlag(p, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintTokenNopop(DMXConfigTokenPtr p)
|
||||
{
|
||||
dmxConfigPrintTokenFlag(p, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
dmxConfigPrintQuotedString(const char *s)
|
||||
{
|
||||
const char *pt;
|
||||
|
||||
if (!s || !s[0])
|
||||
return 1; /* Quote empty string */
|
||||
for (pt = s; *pt; ++pt)
|
||||
if (isspace(*pt))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintString(DMXConfigStringPtr p, int quote)
|
||||
{
|
||||
DMXConfigStringPtr pt;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
for (pt = p; pt; pt = pt->next) {
|
||||
if (quote && dmxConfigPrintQuotedString(pt->string)) {
|
||||
dmxConfigOutput(1, 0, pt->comment, "\"%s\"",
|
||||
pt->string ? pt->string : "");
|
||||
}
|
||||
else
|
||||
dmxConfigOutput(1, 0, pt->comment, "%s",
|
||||
pt->string ? pt->string : "");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dmxConfigPrintPair(DMXConfigPairPtr p, int addSpace)
|
||||
{
|
||||
if (!p)
|
||||
return 0;
|
||||
if (p->token == T_OFFSET) {
|
||||
if (!p->comment && !p->x && !p->y && p->xsign >= 0 && p->ysign >= 0)
|
||||
return 0;
|
||||
dmxConfigOutput(addSpace, 0, p->comment, "%c%d%c%d",
|
||||
p->xsign < 0 ? '-' : '+', p->x,
|
||||
p->ysign < 0 ? '-' : '+', p->y);
|
||||
}
|
||||
else {
|
||||
if (!p->comment && !p->x && !p->y)
|
||||
return 0;
|
||||
dmxConfigOutput(addSpace, 0, p->comment, "%s%dx%d",
|
||||
(p->token == T_ORIGIN) ? "@" : "", p->x, p->y);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintDisplay(DMXConfigDisplayPtr p)
|
||||
{
|
||||
DMXConfigToken dummyStart = { T_DISPLAY, 0, NULL };
|
||||
DMXConfigToken dummyEnd = { ';', 0, NULL };
|
||||
DMXConfigToken dummySep = { '/', 0, NULL };
|
||||
DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL };
|
||||
DMXConfigPair dummySDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 };
|
||||
DMXConfigPair dummySOffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 };
|
||||
DMXConfigPair dummyRDim = { T_DIMENSION, 0, NULL, 0, 0, 0, 0 };
|
||||
DMXConfigPair dummyROffset = { T_OFFSET, 0, NULL, 0, 0, 0, 0 };
|
||||
DMXConfigPair dummyOrigin = { T_ORIGIN, 0, NULL, 0, 0, 0, 0 };
|
||||
int output;
|
||||
|
||||
if (p->dname)
|
||||
p->dname->string = p->name;
|
||||
else
|
||||
dummyName.string = p->name;
|
||||
|
||||
if (p->dim && p->dim->scrn && p->dim->scrn->dim) {
|
||||
p->dim->scrn->dim->x = p->scrnWidth;
|
||||
p->dim->scrn->dim->y = p->scrnHeight;
|
||||
}
|
||||
else {
|
||||
dummySDim.x = p->scrnWidth;
|
||||
dummySDim.y = p->scrnHeight;
|
||||
}
|
||||
|
||||
if (p->dim && p->dim->scrn && p->dim->scrn->offset) {
|
||||
p->dim->scrn->offset->x = p->scrnX;
|
||||
p->dim->scrn->offset->y = p->scrnY;
|
||||
}
|
||||
else {
|
||||
dummySOffset.x = p->scrnX;
|
||||
dummySOffset.y = p->scrnY;
|
||||
}
|
||||
|
||||
if (p->dim && p->dim->root && p->dim->root->dim) {
|
||||
p->dim->root->dim->x = p->rootWidth;
|
||||
p->dim->root->dim->y = p->rootHeight;
|
||||
}
|
||||
else {
|
||||
dummyRDim.x = p->rootWidth;
|
||||
dummyRDim.y = p->rootHeight;
|
||||
}
|
||||
|
||||
if (p->dim && p->dim->root && p->dim->root->offset) {
|
||||
p->dim->root->offset->x = p->rootX;
|
||||
p->dim->root->offset->y = p->rootY;
|
||||
}
|
||||
else {
|
||||
dummyROffset.x = p->rootX;
|
||||
dummyROffset.y = p->rootY;
|
||||
}
|
||||
|
||||
if (p->origin) {
|
||||
p->origin->x = p->rootXOrigin, p->origin->y = p->rootYOrigin;
|
||||
p->origin->xsign = p->rootXSign, p->origin->ysign = p->rootYSign;
|
||||
}
|
||||
else {
|
||||
dummyOrigin.x = p->rootXOrigin, dummyOrigin.y = p->rootYOrigin;
|
||||
dummyOrigin.xsign = p->rootXSign, dummyOrigin.ysign = p->rootYSign;
|
||||
}
|
||||
|
||||
dmxConfigPrintToken(p->start ? p->start : &dummyStart);
|
||||
dmxConfigPrintString(p->dname ? p->dname : &dummyName, 1);
|
||||
|
||||
if (p->dim && p->dim->scrn && p->dim->scrn->dim)
|
||||
output = dmxConfigPrintPair(p->dim->scrn->dim, 1);
|
||||
else
|
||||
output = dmxConfigPrintPair(&dummySDim, 1);
|
||||
if (p->dim && p->dim->scrn && p->dim->scrn->offset)
|
||||
dmxConfigPrintPair(p->dim->scrn->offset, !output);
|
||||
else
|
||||
dmxConfigPrintPair(&dummySOffset, !output);
|
||||
|
||||
if (p->scrnWidth != p->rootWidth
|
||||
|| p->scrnHeight != p->rootHeight || p->rootX || p->rootY) {
|
||||
dmxConfigPrintToken(&dummySep);
|
||||
if (p->dim && p->dim->root && p->dim->root->dim)
|
||||
output = dmxConfigPrintPair(p->dim->root->dim, 1);
|
||||
else
|
||||
output = dmxConfigPrintPair(&dummyRDim, 1);
|
||||
if (p->dim && p->dim->root && p->dim->root->offset)
|
||||
dmxConfigPrintPair(p->dim->root->offset, !output);
|
||||
else
|
||||
dmxConfigPrintPair(&dummyROffset, !output);
|
||||
}
|
||||
|
||||
dmxConfigPrintPair(p->origin ? p->origin : &dummyOrigin, 1);
|
||||
dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintWall(DMXConfigWallPtr p)
|
||||
{
|
||||
dmxConfigPrintToken(p->start);
|
||||
dmxConfigPrintPair(p->wallDim, 1);
|
||||
dmxConfigPrintPair(p->displayDim, 1);
|
||||
dmxConfigPrintString(p->nameList, 1);
|
||||
dmxConfigPrintToken(p->end);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintOption(DMXConfigOptionPtr p)
|
||||
{
|
||||
DMXConfigToken dummyStart = { T_OPTION, 0, NULL };
|
||||
DMXConfigString dummyOption = { T_STRING, 0, NULL, NULL, NULL };
|
||||
DMXConfigToken dummyEnd = { ';', 0, NULL };
|
||||
|
||||
dummyOption.string = p->string;
|
||||
|
||||
dmxConfigPrintToken(p->start ? p->start : &dummyStart);
|
||||
dmxConfigPrintString(&dummyOption, 0);
|
||||
dmxConfigPrintToken(p->end ? p->end : &dummyEnd);
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintParam(DMXConfigParamPtr p)
|
||||
{
|
||||
if (!p)
|
||||
return;
|
||||
if (p->start) {
|
||||
if (p->open && p->close) {
|
||||
dmxConfigPrintToken(p->start);
|
||||
dmxConfigPrintToken(p->open);
|
||||
dmxConfigPrintParam(p->next);
|
||||
dmxConfigPrintToken(p->close);
|
||||
}
|
||||
else if (p->end && p->param) {
|
||||
dmxConfigPrintToken(p->start);
|
||||
dmxConfigPrintString(p->param, 1);
|
||||
dmxConfigPrintToken(p->end);
|
||||
}
|
||||
else
|
||||
dmxConfigLog("dmxConfigPrintParam: cannot handle format (a)\n");
|
||||
}
|
||||
else if (p->end && p->param) {
|
||||
dmxConfigPrintString(p->param, 1);
|
||||
dmxConfigPrintTokenNopop(p->end);
|
||||
dmxConfigPrintParam(p->next);
|
||||
}
|
||||
else
|
||||
dmxConfigLog("dmxConfigPrintParam: cannot handle format (b)\n");
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintSub(DMXConfigSubPtr p)
|
||||
{
|
||||
DMXConfigSubPtr pt;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
for (pt = p; pt; pt = pt->next) {
|
||||
switch (pt->type) {
|
||||
case dmxConfigComment:
|
||||
dmxConfigPrintComment(pt->comment);
|
||||
break;
|
||||
case dmxConfigDisplay:
|
||||
dmxConfigPrintDisplay(pt->display);
|
||||
break;
|
||||
case dmxConfigWall:
|
||||
dmxConfigPrintWall(pt->wall);
|
||||
break;
|
||||
case dmxConfigOption:
|
||||
dmxConfigPrintOption(pt->option);
|
||||
break;
|
||||
case dmxConfigParam:
|
||||
dmxConfigPrintParam(pt->param);
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("dmxConfigPrintSub:"
|
||||
" cannot handle type %d in subentry\n", pt->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxConfigPrintVirtual(DMXConfigVirtualPtr p)
|
||||
{
|
||||
DMXConfigToken dummyStart = { T_VIRTUAL, 0, NULL };
|
||||
DMXConfigToken dummyOpen = { '{', 0, NULL };
|
||||
DMXConfigToken dummyClose = { '}', 0, NULL };
|
||||
DMXConfigString dummyName = { T_STRING, 0, NULL, NULL, NULL };
|
||||
DMXConfigPair dummyDim = { T_DIMENSION, 0, NULL, 0, 0 };
|
||||
|
||||
if (p->vname)
|
||||
p->vname->string = p->name;
|
||||
else
|
||||
dummyName.string = p->name;
|
||||
|
||||
if (p->dim)
|
||||
p->dim->x = p->width, p->dim->y = p->height;
|
||||
else
|
||||
dummyDim.x = p->width, dummyDim.y = p->height;
|
||||
|
||||
dmxConfigPrintToken(p->start ? p->start : &dummyStart);
|
||||
dmxConfigPrintString(p->vname ? p->vname : &dummyName, 1);
|
||||
dmxConfigPrintPair(p->dim ? p->dim : &dummyDim, 1);
|
||||
dmxConfigPrintToken(p->open ? p->open : &dummyOpen);
|
||||
dmxConfigPrintSub(p->subentry);
|
||||
dmxConfigPrintToken(p->close ? p->close : &dummyClose);
|
||||
}
|
||||
|
||||
/** The configuration information in \a entry will be pretty-printed to
|
||||
* the \a stream. If \a stream is NULL, then stdout will be used. */
|
||||
void
|
||||
dmxConfigPrint(FILE * stream, DMXConfigEntryPtr entry)
|
||||
{
|
||||
DMXConfigEntryPtr pt;
|
||||
|
||||
if (!stream)
|
||||
str = stdout;
|
||||
else
|
||||
str = stream;
|
||||
|
||||
stack = &initialStack;
|
||||
|
||||
for (pt = entry; pt; pt = pt->next) {
|
||||
switch (pt->type) {
|
||||
case dmxConfigComment:
|
||||
dmxConfigPrintComment(pt->comment);
|
||||
break;
|
||||
case dmxConfigVirtual:
|
||||
dmxConfigPrintVirtual(pt->virtual);
|
||||
break;
|
||||
default:
|
||||
dmxConfigLog("dmxConfigPrint: cannot handle type %d in entry\n",
|
||||
pt->type);
|
||||
}
|
||||
}
|
||||
if (pos)
|
||||
dmxConfigNewline();
|
||||
}
|
||||
|
||||
/** The configuration information in \a p will be pretty-printed to the
|
||||
* \a stream. If \a stream is NULL, then stdout will be used. */
|
||||
void
|
||||
dmxConfigVirtualPrint(FILE * stream, DMXConfigVirtualPtr p)
|
||||
{
|
||||
if (!stream)
|
||||
str = stdout;
|
||||
else
|
||||
str = stream;
|
||||
|
||||
stack = &initialStack;
|
||||
|
||||
dmxConfigPrintVirtual(p);
|
||||
if (pos)
|
||||
dmxConfigNewline();
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Interface to DMX configuration file pretty-printer. \see dmxprint.c */
|
||||
|
||||
#ifndef _DMXPRINT_H_
|
||||
#define _DMXPRINT_H_
|
||||
|
||||
void dmxConfigPrint(FILE * str, DMXConfigEntryPtr entry);
|
||||
void dmxConfigVirtualPrint(FILE * str, DMXConfigVirtualPtr p);
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
* This is a simple filter for testing.
|
||||
*/
|
||||
|
||||
#include "dmxconfig.h"
|
||||
#include "dmxparse.h"
|
||||
#include "dmxprint.h"
|
||||
#include "dmxcompat.h"
|
||||
|
||||
extern int yyparse(void);
|
||||
extern int yydebug;
|
||||
extern FILE *yyin;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
yydebug = 0;
|
||||
yyparse();
|
||||
dmxConfigPrint(stdout, dmxConfigEntry);
|
||||
return 0;
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
include $(top_srcdir)/manpages.am
|
||||
appman_PRE = xdmxconfig.man vdltodmx.man dmxtodmx.man
|
|
@ -1,41 +0,0 @@
|
|||
.\" $XFree86$
|
||||
.\" Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission is hereby granted, free of charge, to any person obtaining
|
||||
.\" a copy of this software and associated documentation files (the
|
||||
.\" "Software"), to deal in the Software without restriction, including
|
||||
.\" without limitation on 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
|
||||
.\" NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
.\" BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
.\" CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
.\" SOFTWARE.
|
||||
.\"
|
||||
.\" Authors:
|
||||
.\" Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
.\"
|
||||
.TH dmxtodmx 1 @vendorversion@
|
||||
.SH NAME
|
||||
dmxtodmx - dmx configuration file parser and printer
|
||||
.SH SYNOPSIS
|
||||
.B dmxtodmx
|
||||
.SH DESCRIPTION
|
||||
.I dmxtodmx
|
||||
reads the standard input, parsing a configuration file for the
|
||||
.I Xdmx
|
||||
distributed multi-head X server. After a successful parse, the file is
|
||||
pretty-printed to standard output.
|
||||
.SH "SEE ALSO"
|
||||
Xdmx(1), vdltodmx(1), xdmxconfig(1)
|
|
@ -1,95 +0,0 @@
|
|||
.\" $XFree86$
|
||||
.\" Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission is hereby granted, free of charge, to any person obtaining
|
||||
.\" a copy of this software and associated documentation files (the
|
||||
.\" "Software"), to deal in the Software without restriction, including
|
||||
.\" without limitation on 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
|
||||
.\" NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
.\" BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
.\" CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
.\" SOFTWARE.
|
||||
.\"
|
||||
.\" Authors:
|
||||
.\" Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
.\"
|
||||
.TH vdltodmx 1 @vendorversion@
|
||||
.SH NAME
|
||||
vdltodmx - dmx configuration file parser and printer
|
||||
.SH SYNOPSIS
|
||||
.B vdltodmx
|
||||
.I infile
|
||||
.I outfile
|
||||
.SH DESCRIPTION
|
||||
.I vdltodmx
|
||||
reads the input file, which should be in VDL configuration file format.
|
||||
After a successful parse, a file in Xdmx configuration file format is
|
||||
written to the output file.
|
||||
.P
|
||||
The VDL file format is used with
|
||||
.IR xmovie ,
|
||||
which is available from
|
||||
http://www.llnl.gov/icc/lc/img/xmovie/xmovie.html
|
||||
.SH EXAMPLE
|
||||
Given the following VDL-format file:
|
||||
.RS
|
||||
.nf
|
||||
0
|
||||
2
|
||||
#
|
||||
#
|
||||
2560 2048 Left two-thirds [restrict=*:2]
|
||||
2
|
||||
:2.1 1280 2048 0 0 0 0
|
||||
:2.2 1280 2048 1280 0 0 0
|
||||
4
|
||||
1280 1024 0 0
|
||||
1280 1024 0 1024
|
||||
1280 1024 1280 0
|
||||
1280 1024 1280 1024
|
||||
#
|
||||
2560 2048 Right two-thirds [restrict=*:2]
|
||||
2
|
||||
:2.2 1280 2048 0 0 0 0
|
||||
:2.3 1280 2048 1280 0 0 0
|
||||
4
|
||||
1280 1024 1280 0
|
||||
1280 1024 1280 1024
|
||||
1280 1024 2560 0
|
||||
1280 1024 2560 1024
|
||||
.fi
|
||||
.RE
|
||||
the following DMX-format file will be produced:
|
||||
.RS
|
||||
.nf
|
||||
#
|
||||
#
|
||||
virtual "Left two-thirds" 2560x2048 {
|
||||
display :2.1 1280x2048;
|
||||
display :2.2 1280x2048 @1280x0;
|
||||
}
|
||||
#
|
||||
virtual "Right two-thirds" 2560x2048 {
|
||||
display :2.2 1280x2048;
|
||||
display :2.3 1280x2048 @1280x0;
|
||||
}
|
||||
.fi
|
||||
.RE
|
||||
.SH BUGS
|
||||
If the VDL file is not in the expected format, the program will probably
|
||||
dump core.
|
||||
.SH "SEE ALSO"
|
||||
Xdmx(1), xdmxconfig(1), vdl(3), xmovie(1)
|
|
@ -1,63 +0,0 @@
|
|||
.\" $XFree86$
|
||||
.\" Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
.\" All Rights Reserved.
|
||||
.\"
|
||||
.\" Permission is hereby granted, free of charge, to any person obtaining
|
||||
.\" a copy of this software and associated documentation files (the
|
||||
.\" "Software"), to deal in the Software without restriction, including
|
||||
.\" without limitation on 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
|
||||
.\" NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
.\" BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
.\" ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
.\" CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
.\" SOFTWARE.
|
||||
.\"
|
||||
.\" Authors:
|
||||
.\" Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
.\"
|
||||
.TH xdmxconfig 1 @vendorversion@
|
||||
.SH NAME
|
||||
xdmxconfig - a graphical configuration tool for Xdmx configuration files
|
||||
.SH SYNOPSIS
|
||||
.B xdmxconfig
|
||||
[filename]
|
||||
.SH DESCRIPTION
|
||||
.I xdmxconfig
|
||||
reads, edits, and writes configuration files for the Xdmx server. The
|
||||
grammar for the configuration file is specified in the Xdmx(1) manual
|
||||
page.
|
||||
.PP
|
||||
To start from scratch, create a "New Global" and specify the name and
|
||||
overall dimensions for the configuration. Then use "New Display" to
|
||||
enter more displays.
|
||||
.PP
|
||||
If there is more than one configuration, the configuration name button
|
||||
will bring up a selection menu.
|
||||
.PP
|
||||
In the right-hand panel, the left mouse button will move the
|
||||
highlighted display at "tool resolution"; the middle mouse button will
|
||||
move the highlighted display by a single pixel (at "wall resolution");
|
||||
and the right mouse button will bring up a menu allowing the highlighted
|
||||
display to be edited or deleted. The arrow keys will also move the
|
||||
highlighted display by a single pixel.
|
||||
.SH BUGS
|
||||
Currently, entries with the
|
||||
.B wall
|
||||
keyword are not editable, but will be preserved in the new output file.
|
||||
The tool will quit when requested by the user, even if a configuration
|
||||
file has not been written out (i.e., without warning). The menu
|
||||
interaction should be improved (menu entries that don't currently work
|
||||
should be greyed-out, for example). The Help button does not work.
|
||||
.SH "SEE ALSO"
|
||||
Xdmx(1), vdltodmx(1)
|
|
@ -1,82 +0,0 @@
|
|||
flex = find_program('flex')
|
||||
bison = find_program('bison')
|
||||
|
||||
lgen = generator(
|
||||
flex,
|
||||
output : '@PLAINNAME@.yy.c',
|
||||
arguments : ['-o', '@OUTPUT@', '@INPUT@']
|
||||
)
|
||||
lfiles = lgen.process('scanner.l')
|
||||
|
||||
pgen = generator(
|
||||
bison,
|
||||
output : ['@BASENAME@.c', '@BASENAME@.h'],
|
||||
arguments : ['@INPUT@', '--defines=@OUTPUT1@', '--output=@OUTPUT0@']
|
||||
)
|
||||
pfiles = pgen.process('parser.y')
|
||||
|
||||
srcs_dmx_config = [
|
||||
'dmxparse.c',
|
||||
'dmxprint.c',
|
||||
'dmxcompat.c',
|
||||
'dmxconfig.c',
|
||||
pfiles,
|
||||
lfiles,
|
||||
]
|
||||
|
||||
dmx_inc = [
|
||||
inc,
|
||||
include_directories('../')
|
||||
]
|
||||
|
||||
dmx_c_args = [
|
||||
'-DHAVE_DMX_CONFIG_H',
|
||||
'-DDMX_LOG_STANDALONE',
|
||||
]
|
||||
|
||||
dmx_config = static_library('dmx_config',
|
||||
srcs_dmx_config,
|
||||
include_directories: dmx_inc,
|
||||
dependencies: common_dep,
|
||||
link_with: libxlibc,
|
||||
c_args: dmx_c_args,
|
||||
)
|
||||
|
||||
executable('xdmxconfig',
|
||||
[
|
||||
'xdmxconfig.c',
|
||||
'../dmxlog.c',
|
||||
'Canvas.c',
|
||||
],
|
||||
include_directories: [
|
||||
inc,
|
||||
include_directories('../')
|
||||
],
|
||||
dependencies: [
|
||||
common_dep,
|
||||
dependency('xaw7'),
|
||||
dependency('xmu'),
|
||||
dependency('xt'),
|
||||
dependency('xpm'),
|
||||
dependency('x11'),
|
||||
],
|
||||
link_with: dmx_config,
|
||||
c_args: dmx_c_args,
|
||||
install: true,
|
||||
)
|
||||
|
||||
executable('vdltodmx',
|
||||
'vdltodmx.c',
|
||||
include_directories: dmx_inc,
|
||||
link_with: dmx_config,
|
||||
c_args: dmx_c_args,
|
||||
install: true,
|
||||
)
|
||||
|
||||
executable('dmxtodmx',
|
||||
'dmxtodmx.c',
|
||||
include_directories: dmx_inc,
|
||||
link_with: dmx_config,
|
||||
c_args: dmx_c_args,
|
||||
install: true,
|
||||
)
|
|
@ -1,227 +0,0 @@
|
|||
/* $XFree86$ */
|
||||
/*
|
||||
* Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
%{
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include "dmxparse.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#define YYDEBUG 1
|
||||
#define YYERROR_VERBOSE
|
||||
#define YY_USE_PROTOS
|
||||
|
||||
extern int yylex(void);
|
||||
DMXConfigEntryPtr dmxConfigEntry = NULL;
|
||||
#define APPEND(type, h, t) \
|
||||
{ \
|
||||
type pt; \
|
||||
for (pt = h; pt->next; pt = pt->next); \
|
||||
pt->next = t; \
|
||||
}
|
||||
%}
|
||||
|
||||
%union {
|
||||
DMXConfigTokenPtr token;
|
||||
DMXConfigStringPtr string;
|
||||
DMXConfigNumberPtr number;
|
||||
DMXConfigPairPtr pair;
|
||||
DMXConfigFullDimPtr fdim;
|
||||
DMXConfigPartDimPtr pdim;
|
||||
DMXConfigDisplayPtr display;
|
||||
DMXConfigWallPtr wall;
|
||||
DMXConfigOptionPtr option;
|
||||
DMXConfigParamPtr param;
|
||||
DMXConfigCommentPtr comment;
|
||||
DMXConfigSubPtr subentry;
|
||||
DMXConfigVirtualPtr virtual;
|
||||
DMXConfigEntryPtr entry;
|
||||
}
|
||||
|
||||
/* Terminals */
|
||||
%token <token> '{' '}' ';' '/' T_VIRTUAL T_DISPLAY T_WALL T_OPTION T_PARAM
|
||||
%token <string> T_STRING
|
||||
%token <pair> T_DIMENSION T_OFFSET T_ORIGIN
|
||||
%token <comment> T_COMMENT T_LINE_COMMENT
|
||||
|
||||
/* Non-termials */
|
||||
%type <token> Display Wall Terminal Open Close
|
||||
%type <string> NameList Name
|
||||
%type <pair> Dimension Offset Origin
|
||||
%type <pdim> PartialDim
|
||||
%type <fdim> FullDim
|
||||
%type <display> DisplayEntry
|
||||
%type <option> OptionEntry
|
||||
%type <param> ParamEntry ParamList Param
|
||||
%type <subentry> SubList Sub
|
||||
%type <wall> WallEntry
|
||||
%type <virtual> Virtual
|
||||
%type <entry> Program EntryList Entry
|
||||
|
||||
%%
|
||||
|
||||
Program : EntryList { dmxConfigEntry = $1; }
|
||||
;
|
||||
|
||||
EntryList : Entry
|
||||
| EntryList Entry { APPEND(DMXConfigEntryPtr,$1,$2); $$ = $1; }
|
||||
;
|
||||
|
||||
Entry : Virtual { $$ = dmxConfigEntryVirtual($1); }
|
||||
| T_LINE_COMMENT { $$ = dmxConfigEntryComment($1); }
|
||||
;
|
||||
|
||||
Virtual : T_VIRTUAL Open SubList Close
|
||||
{ $$ = dmxConfigCreateVirtual($1, NULL, NULL, $2, $3, $4); }
|
||||
| T_VIRTUAL Dimension Open SubList Close
|
||||
{ $$ = dmxConfigCreateVirtual($1, NULL, $2, $3, $4, $5); }
|
||||
| T_VIRTUAL Name Open SubList Close
|
||||
{ $$ = dmxConfigCreateVirtual($1, $2, NULL, $3, $4, $5); }
|
||||
| T_VIRTUAL Name Dimension Open SubList Close
|
||||
{ $$ = dmxConfigCreateVirtual($1, $2, $3, $4, $5, $6 ); }
|
||||
;
|
||||
|
||||
SubList : Sub
|
||||
| SubList Sub { APPEND(DMXConfigSubPtr,$1,$2); $$ = $1; }
|
||||
;
|
||||
|
||||
Sub : T_LINE_COMMENT { $$ = dmxConfigSubComment($1); }
|
||||
| DisplayEntry { $$ = dmxConfigSubDisplay($1); }
|
||||
| WallEntry { $$ = dmxConfigSubWall($1); }
|
||||
| OptionEntry { $$ = dmxConfigSubOption($1); }
|
||||
| ParamEntry { $$ = dmxConfigSubParam($1); }
|
||||
;
|
||||
|
||||
OptionEntry : T_OPTION NameList Terminal
|
||||
{ $$ = dmxConfigCreateOption($1, $2, $3); }
|
||||
;
|
||||
|
||||
ParamEntry : T_PARAM NameList Terminal
|
||||
{ $$ = dmxConfigCreateParam($1, NULL, $2, NULL, $3); }
|
||||
| T_PARAM Open ParamList Close
|
||||
{ $$ = dmxConfigCreateParam($1, $2, NULL, $4, NULL);
|
||||
$$->next = $3;
|
||||
}
|
||||
;
|
||||
|
||||
ParamList : Param
|
||||
| ParamList Param { APPEND(DMXConfigParamPtr,$1,$2); $$ = $1; }
|
||||
;
|
||||
|
||||
Param : NameList Terminal
|
||||
{ $$ = dmxConfigCreateParam(NULL, NULL, $1, NULL, $2); }
|
||||
;
|
||||
|
||||
PartialDim : Dimension Offset
|
||||
{ $$ = dmxConfigCreatePartDim($1, $2); }
|
||||
| Dimension
|
||||
{ $$ = dmxConfigCreatePartDim($1, NULL); }
|
||||
| Offset
|
||||
{ $$ = dmxConfigCreatePartDim(NULL, $1); }
|
||||
;
|
||||
|
||||
FullDim : PartialDim '/' PartialDim
|
||||
{ $$ = dmxConfigCreateFullDim($1, $3); }
|
||||
| '/' PartialDim
|
||||
{ $$ = dmxConfigCreateFullDim(NULL, $2); }
|
||||
| PartialDim
|
||||
{ $$ = dmxConfigCreateFullDim($1, NULL); }
|
||||
;
|
||||
|
||||
DisplayEntry : Display Name FullDim Origin Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, $2, $3, $4, $5); }
|
||||
| Display FullDim Origin Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, NULL, $2, $3, $4); }
|
||||
| Display Name Origin Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, $2, NULL, $3, $4); }
|
||||
|
||||
| Display Name FullDim Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, $2, $3, NULL, $4); }
|
||||
| Display FullDim Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, NULL, $2, NULL, $3); }
|
||||
| Display Name Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, $2, NULL, NULL, $3); }
|
||||
| Display Terminal
|
||||
{ $$ = dmxConfigCreateDisplay($1, NULL, NULL, NULL, $2); }
|
||||
;
|
||||
|
||||
WallEntry : Wall Dimension Dimension NameList Terminal
|
||||
{ $$ = dmxConfigCreateWall($1, $2, $3, $4, $5); }
|
||||
| Wall Dimension NameList Terminal
|
||||
{ $$ = dmxConfigCreateWall($1, $2, NULL, $3, $4); }
|
||||
| Wall NameList Terminal
|
||||
{ $$ = dmxConfigCreateWall($1, NULL, NULL, $2, $3); }
|
||||
;
|
||||
|
||||
Display : T_DISPLAY
|
||||
| T_DISPLAY T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Name : T_STRING
|
||||
| T_STRING T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Dimension : T_DIMENSION
|
||||
| T_DIMENSION T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Offset : T_OFFSET
|
||||
| T_OFFSET T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Origin : T_ORIGIN
|
||||
| T_ORIGIN T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Terminal : ';'
|
||||
| ';' T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Open : '{'
|
||||
| '{' T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Close : '}'
|
||||
| '}' T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
Wall : T_WALL
|
||||
| T_WALL T_COMMENT { $$ = $1; $$->comment = $2->comment; }
|
||||
;
|
||||
|
||||
NameList : Name
|
||||
| NameList Name { APPEND(DMXConfigStringPtr, $1, $2); $$ = $1; }
|
||||
;
|
|
@ -1,187 +0,0 @@
|
|||
/* $XFree86$ */
|
||||
/*
|
||||
* Copyright 2002 Red Hat Inc., Durham, North Carolina.
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation on 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
|
||||
* NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Authors:
|
||||
* Rickard E. (Rik) Faith <faith@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
%{
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#include "dmxparse.h"
|
||||
#include "parser.h"
|
||||
#include "os.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
static int getdimension(int token, const char *text, int leng);
|
||||
static int getstring(int token, const char *text, int leng);
|
||||
static int gettoken(int token, const char *text, int leng);
|
||||
static int getcomment(int token, const char *text, int leng);
|
||||
static int lineno = 1;
|
||||
%}
|
||||
%s OTHER
|
||||
comment #.*
|
||||
word ([[:alpha:]_/:\-\+\.\*][[:alnum:]_/:\-\+\.\*]+)
|
||||
string \"(([^\"\n])|\"\")*\"
|
||||
badstring \"(([^\"\n])|\"\")*
|
||||
number [[:digit:]x]+
|
||||
dimension [[:digit:]]+[[:blank:]]*x[[:blank:]]*[[:digit:]]+
|
||||
offset [+-][[:digit:]]+[[:blank:]]*[+-][[:blank:]]*[[:digit:]]+
|
||||
origin @[[:blank:]]*[[:digit:]]+[[:blank:]]*[[:blank:]]*x[[:digit:]]+
|
||||
NL \n
|
||||
WS [[:blank:]]+
|
||||
%%
|
||||
virtual return gettoken(T_VIRTUAL, yytext, yyleng);
|
||||
display return gettoken(T_DISPLAY, yytext, yyleng);
|
||||
wall return gettoken(T_WALL, yytext, yyleng);
|
||||
option return gettoken(T_OPTION, yytext, yyleng);
|
||||
param return gettoken(T_PARAM, yytext, yyleng);
|
||||
{dimension} return getdimension(T_DIMENSION, yytext, yyleng);
|
||||
{offset} return getdimension(T_OFFSET, yytext+1, yyleng-1);
|
||||
{origin} return getdimension(T_ORIGIN, yytext+1, yyleng-1);
|
||||
{word} return getstring(T_STRING, yytext, yyleng);
|
||||
{string} return getstring(T_STRING, yytext+1, yyleng-2);
|
||||
{NL} ++lineno;
|
||||
{WS}
|
||||
\{ return gettoken(yytext[0], yytext, yyleng);
|
||||
\} return gettoken(yytext[0], yytext, yyleng);
|
||||
\; return gettoken(yytext[0], yytext, yyleng);
|
||||
\/ return gettoken(yytext[0], yytext, yyleng);
|
||||
^{comment} return getcomment(T_LINE_COMMENT, yytext, yyleng);
|
||||
{comment} return getcomment(T_COMMENT, yytext, yyleng);
|
||||
. return getstring(T_STRING, yytext, yyleng);
|
||||
<<EOF>> return 0;
|
||||
%%
|
||||
int yywrap(void)
|
||||
{
|
||||
(void) &yyunput;
|
||||
(void) &input;
|
||||
return 1;
|
||||
}
|
||||
|
||||
_X_NORETURN void yyerror(const char *message)
|
||||
{
|
||||
const char *pt, *end;
|
||||
struct _entry {
|
||||
const char *from;
|
||||
const char *to;
|
||||
} *entry, list[] = {
|
||||
{ "T_VIRTUAL", "\"virtual\"" },
|
||||
{ "T_DISPLAY", "\"display\"" },
|
||||
{ "T_WALL", "\"wall\"" },
|
||||
{ "T_OPTION", "\"option\"" },
|
||||
{ "T_PARAM", "\"param\"" },
|
||||
{ "T_DIMENSION", "dimension (e.g., 2x2 or 1024x768)" },
|
||||
{ "T_OFFSET", "display offset (e.g., +10-10)" },
|
||||
{ "T_ORIGIN", "tile origin (e.g., @1280x1024)" },
|
||||
{ "T_STRING", "string" },
|
||||
{ "T_COMMENT", "comment (e.g., #...)" },
|
||||
{ "T_LINE_COMMENT", "comment (e.g., #...)" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
fprintf(stderr, "parse error on line %d at token \"%*.*s\"\n",
|
||||
lineno, (int)yyleng, (int)yyleng, yytext);
|
||||
end = message + strlen(message);
|
||||
for (pt = message; *pt; pt++) {
|
||||
if (pt[0] == 'T' && pt[1] == '_') {
|
||||
const char *next = strchr(pt, ' ');
|
||||
if (!next || !*next) next = strchr(pt, '\0');
|
||||
if (!next) goto bail;
|
||||
--next;
|
||||
if (next-pt == 1 && next[1]
|
||||
&& next[2] == '\'' && next[3] == '\'') {
|
||||
fprintf(stderr, "\"%c\"", next[1]);
|
||||
pt += 4;
|
||||
goto cnt;
|
||||
}
|
||||
for (entry = list; entry->from; ++entry) {
|
||||
if (!strncmp(entry->from, pt, strlen(entry->from))) {
|
||||
fprintf(stderr, "%s", entry->to);
|
||||
pt = next;
|
||||
goto cnt;
|
||||
}
|
||||
}
|
||||
} else if (end-pt >= 5 && pt[0] == '\'' && pt[1] == '\'' && pt[3]
|
||||
&& pt[4] == '\'' && pt[5] == '\'') {
|
||||
fprintf(stderr, "\"%c\"", pt[3]);
|
||||
pt += 5;
|
||||
} else if (end-pt >= 3 && pt[0] == '\'' && pt[1] && pt[2] == '\'') {
|
||||
fprintf(stderr, "\"%c\"", pt[1]);
|
||||
pt += 3;
|
||||
}
|
||||
bail:
|
||||
putc(*pt, stderr);
|
||||
cnt:
|
||||
;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
static int getdimension(int token, const char *text, int leng)
|
||||
{
|
||||
char *endptr;
|
||||
char *tmp = dmxConfigAlloc(leng+1);
|
||||
int x, y;
|
||||
|
||||
strlcpy(tmp, text, leng+1);
|
||||
x = strtol(tmp, &endptr, 10);
|
||||
while (*endptr && !isdigit(*endptr)) ++endptr;
|
||||
y = strtol(endptr, NULL, 10);
|
||||
dmxConfigFree(tmp);
|
||||
yylval.pair = dmxConfigCreatePair(token, lineno, NULL, x, y, 1, 1);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int getstring(int token, const char *text, int leng)
|
||||
{
|
||||
yylval.string = dmxConfigCreateString(token, lineno, NULL,
|
||||
dmxConfigCopyString(leng ? text : "",
|
||||
leng));
|
||||
return token;
|
||||
}
|
||||
|
||||
static int gettoken(int token, const char *text, int leng)
|
||||
{
|
||||
yylval.token = dmxConfigCreateToken(token, lineno, NULL);
|
||||
return token;
|
||||
}
|
||||
|
||||
static int getcomment(int token, const char *text, int leng)
|
||||
{
|
||||
yylval.comment = dmxConfigCreateComment(token, lineno,
|
||||
dmxConfigCopyString(text + 1,
|
||||
leng - 1));
|
||||
return token;
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
error
|
|
@ -1,2 +0,0 @@
|
|||
parse error on line 1 at token "error"
|
||||
syntax error, unexpected string expecting "virtual" or comment (e.g., #...)
|
|
@ -1 +0,0 @@
|
|||
# comment
|
|
@ -1 +0,0 @@
|
|||
# comment
|
|
@ -1 +0,0 @@
|
|||
virtual
|
|
@ -1,2 +0,0 @@
|
|||
parse error on line 2 at token " "
|
||||
syntax error, unexpected $end, expecting "{" or string or dimension (e.g., 2x2 or 1024x768)
|
|
@ -1 +0,0 @@
|
|||
display
|
|
@ -1,2 +0,0 @@
|
|||
parse error on line 1 at token "display"
|
||||
syntax error, unexpected "display" expecting "virtual" or comment (e.g., #...)
|
|
@ -1 +0,0 @@
|
|||
display;
|
|
@ -1,2 +0,0 @@
|
|||
parse error on line 1 at token "display"
|
||||
syntax error, unexpected "display" expecting "virtual" or comment (e.g., #...)
|
|
@ -1,2 +0,0 @@
|
|||
virtual {
|
||||
}
|
Binary file not shown.
|
@ -1,4 +0,0 @@
|
|||
virtual a {
|
||||
display d0:0 1280x1024;
|
||||
display d1:0 1280x1024;
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
virtual a {
|
||||
display d0:0 1280x1024;
|
||||
display d1:0 1280x1024;
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
# comment a
|
||||
# comment b
|
||||
## comment c
|
||||
# <-- tab
|
||||
# Next comment is empty
|
||||
#
|
||||
# Non empty
|
|
@ -1,7 +0,0 @@
|
|||
# comment a
|
||||
# comment b
|
||||
## comment c
|
||||
# <-- tab
|
||||
# Next comment is empty
|
||||
#
|
||||
# Non empty
|
|
@ -1,3 +0,0 @@
|
|||
virtual a {
|
||||
param a b; # comment
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue